| // Copyright 2020 The Tint Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef SRC_READER_WGSL_TOKEN_H_ |
| #define SRC_READER_WGSL_TOKEN_H_ |
| |
| #include <stddef.h> |
| |
| #include <ostream> |
| #include <string> |
| |
| #include "src/source.h" |
| |
| namespace tint { |
| namespace reader { |
| namespace wgsl { |
| |
| /// Stores tokens generated by the Lexer |
| class Token { |
| public: |
| /// The type of the parsed token |
| enum class Type { |
| /// Error result |
| kError = -2, |
| /// Reserved keyword |
| kReservedKeyword = -1, |
| /// Uninitialized token |
| kUninitialized = 0, |
| /// End of input string reached |
| kEOF, |
| |
| /// An identifier |
| kIdentifier, |
| /// A string value |
| kStringLiteral, |
| /// A float value |
| kFloatLiteral, |
| /// An signed int value |
| kSintLiteral, |
| /// A unsigned int value |
| kUintLiteral, |
| |
| /// A '&' |
| kAnd, |
| /// A '&&' |
| kAndAnd, |
| /// A '->' |
| kArrow, |
| /// A '[[' |
| kAttrLeft, |
| /// A ']]' |
| kAttrRight, |
| /// A '/' |
| kForwardSlash, |
| /// A '!' |
| kBang, |
| /// A '[' |
| kBracketLeft, |
| /// A ']' |
| kBracketRight, |
| /// A '{' |
| kBraceLeft, |
| /// A '}' |
| kBraceRight, |
| /// A ':' |
| kColon, |
| /// A ',' |
| kComma, |
| /// A '=' |
| kEqual, |
| /// A '==' |
| kEqualEqual, |
| /// A '>' |
| kGreaterThan, |
| /// A '>=' |
| kGreaterThanEqual, |
| /// A '<' |
| kLessThan, |
| /// A '<=' |
| kLessThanEqual, |
| /// A '%' |
| kMod, |
| /// A '-' |
| kMinus, |
| /// A '::' |
| kNamespace, |
| /// A '!=' |
| kNotEqual, |
| /// A '.' |
| kPeriod, |
| /// A '+' |
| kPlus, |
| /// A '|' |
| kOr, |
| /// A '||' |
| kOrOr, |
| /// A '(' |
| kParenLeft, |
| /// A ')' |
| kParenRight, |
| /// A ';' |
| kSemicolon, |
| /// A '*' |
| kStar, |
| /// A '^' |
| kXor, |
| |
| /// A 'array' |
| kArray, |
| /// A 'as' |
| kAs, |
| /// A 'binding' |
| kBinding, |
| /// A 'bool' |
| kBool, |
| /// A 'block' |
| kBlock, |
| /// A 'break' |
| kBreak, |
| /// A 'builtin' |
| kBuiltin, |
| /// A 'case' |
| kCase, |
| /// A 'cast' |
| kCast, |
| /// A 'compute' |
| kCompute, |
| /// A 'const' |
| kConst, |
| /// A 'continue' |
| kContinue, |
| /// A 'continuing' |
| kContinuing, |
| /// A 'discard' |
| kDiscard, |
| /// A 'default' |
| kDefault, |
| /// A 'else' |
| kElse, |
| /// A 'elseif' |
| kElseIf, |
| /// A 'entry_point' |
| kEntryPoint, |
| /// A 'f32' |
| kF32, |
| /// A 'fallthrough' |
| kFallthrough, |
| /// A 'false' |
| kFalse, |
| /// A 'fn' |
| kFn, |
| // A 'for' |
| kFor, |
| /// A 'fragment' |
| kFragment, |
| /// A 'function' |
| kFunction, |
| /// A 'i32' |
| kI32, |
| /// A 'if' |
| kIf, |
| /// A 'image' |
| kImage, |
| /// A 'import' |
| kImport, |
| /// A 'in' |
| kIn, |
| /// A 'location' |
| kLocation, |
| /// A 'loop' |
| kLoop, |
| /// A 'mat2x2' |
| kMat2x2, |
| /// A 'mat2x3' |
| kMat2x3, |
| /// A 'mat2x4' |
| kMat2x4, |
| /// A 'mat3x2' |
| kMat3x2, |
| /// A 'mat3x3' |
| kMat3x3, |
| /// A 'mat3x4' |
| kMat3x4, |
| /// A 'mat4x2' |
| kMat4x2, |
| /// A 'mat4x3' |
| kMat4x3, |
| /// A 'mat4x4' |
| kMat4x4, |
| /// A 'offset' |
| kOffset, |
| /// A 'out' |
| kOut, |
| /// A 'private' |
| kPrivate, |
| /// A 'ptr' |
| kPtr, |
| /// A 'return' |
| kReturn, |
| /// A 'sampler' |
| kSampler, |
| /// A 'sampler_comparison' |
| kComparisonSampler, |
| /// A 'set' |
| kSet, |
| /// A 'storage_buffer' |
| kStorageBuffer, |
| /// A 'stride' |
| kStride, |
| /// A 'struct' |
| kStruct, |
| /// A 'switch' |
| kSwitch, |
| /// A 'texture_depth_2d' |
| kTextureDepth2d, |
| /// A 'texture_depth_2d_array' |
| kTextureDepth2dArray, |
| /// A 'texture_depth_cube' |
| kTextureDepthCube, |
| /// A 'texture_depth_cube_array' |
| kTextureDepthCubeArray, |
| /// A 'true' |
| kTrue, |
| /// A 'type' |
| kType, |
| /// A 'u32' |
| kU32, |
| /// A 'uniform' |
| kUniform, |
| /// A 'uniform_constant' |
| kUniformConstant, |
| /// A 'var' |
| kVar, |
| /// A 'vec2' |
| kVec2, |
| /// A 'vec3' |
| kVec3, |
| /// A 'vec4' |
| kVec4, |
| /// A 'vertex' |
| kVertex, |
| /// A 'void' |
| kVoid, |
| /// A 'workgroup' |
| kWorkgroup |
| }; |
| |
| /// Converts a token type to a name |
| /// @param type the type to convert |
| /// @returns the token type as as string |
| static std::string TypeToName(Type type); |
| |
| /// Creates an uninitialized token |
| Token(); |
| /// Create a Token |
| /// @param type the Token::Type of the token |
| /// @param source the source of the token |
| Token(Type type, const Source& source); |
| |
| /// Create a string Token |
| /// @param type the Token::Type of the token |
| /// @param source the source of the token |
| /// @param val the source string for the token |
| Token(Type type, const Source& source, const std::string& val); |
| /// Create a unsigned integer Token |
| /// @param source the source of the token |
| /// @param val the source unsigned for the token |
| Token(const Source& source, uint32_t val); |
| /// Create a signed integer Token |
| /// @param source the source of the token |
| /// @param val the source integer for the token |
| Token(const Source& source, int32_t val); |
| /// Create a float Token |
| /// @param source the source of the token |
| /// @param val the source float for the token |
| Token(const Source& source, float val); |
| /// Move constructor |
| Token(Token&&); |
| /// Copy constructor |
| Token(const Token&); |
| ~Token(); |
| |
| /// Assignment operator |
| /// @param b the token to copy |
| /// @return Token |
| Token& operator=(const Token& b); |
| |
| /// Returns true if the token is of the given type |
| /// @param t the type to check against. |
| /// @returns true if the token is of type |t| |
| bool Is(Type t) const { return type_ == t; } |
| |
| /// @returns true if the token is uninitialized |
| bool IsUninitialized() const { return type_ == Type::kUninitialized; } |
| /// @returns true if the token is reserved |
| bool IsReservedKeyword() const { return type_ == Type::kReservedKeyword; } |
| /// @returns true if the token is an error |
| bool IsError() const { return type_ == Type::kError; } |
| /// @returns true if the token is EOF |
| bool IsEof() const { return type_ == Type::kEOF; } |
| /// @returns true if the token is an identifier |
| bool IsIdentifier() const { return type_ == Type::kIdentifier; } |
| /// @returns true if the token is a string |
| bool IsStringLiteral() const { return type_ == Type::kStringLiteral; } |
| /// @returns true if the token is a float |
| bool IsFloatLiteral() const { return type_ == Type::kFloatLiteral; } |
| /// @returns true if the token is an signed int |
| bool IsSintLiteral() const { return type_ == Type::kSintLiteral; } |
| /// @returns true if the token is a unsigned int |
| bool IsUintLiteral() const { return type_ == Type::kUintLiteral; } |
| |
| /// @returns true if token is a '&' |
| bool IsAnd() const { return type_ == Type::kAnd; } |
| /// @returns true if token is a '&&' |
| bool IsAndAnd() const { return type_ == Type::kAndAnd; } |
| /// @returns true if token is a '->' |
| bool IsArrow() const { return type_ == Type::kArrow; } |
| /// @returns true if token is a '[[' |
| bool IsAttrLeft() const { return type_ == Type::kAttrLeft; } |
| /// @returns true if token is a ']]' |
| bool IsAttrRight() const { return type_ == Type::kAttrRight; } |
| /// @returns true if token is a '/' |
| bool IsForwardSlash() const { return type_ == Type::kForwardSlash; } |
| /// @returns true if token is a '!' |
| bool IsBang() const { return type_ == Type::kBang; } |
| /// @returns true if token is a '[' |
| bool IsBracketLeft() const { return type_ == Type::kBracketLeft; } |
| /// @returns true if token is a ']' |
| bool IsBracketRight() const { return type_ == Type::kBracketRight; } |
| /// @returns true if token is a '{' |
| bool IsBraceLeft() const { return type_ == Type::kBraceLeft; } |
| /// @returns true if token is a '}' |
| bool IsBraceRight() const { return type_ == Type::kBraceRight; } |
| /// @returns true if token is a ':' |
| bool IsColon() const { return type_ == Type::kColon; } |
| /// @returns true if token is a ',' |
| bool IsComma() const { return type_ == Type::kComma; } |
| /// @returns true if token is a '=' |
| bool IsEqual() const { return type_ == Type::kEqual; } |
| /// @returns true if token is a '==' |
| bool IsEqualEqual() const { return type_ == Type::kEqualEqual; } |
| /// @returns true if token is a '>' |
| bool IsGreaterThan() const { return type_ == Type::kGreaterThan; } |
| /// @returns true if token is a '>=' |
| bool IsGreaterThanEqual() const { return type_ == Type::kGreaterThanEqual; } |
| /// @returns true if token is a '<' |
| bool IsLessThan() const { return type_ == Type::kLessThan; } |
| /// @returns true if token is a '<=' |
| bool IsLessThanEqual() const { return type_ == Type::kLessThanEqual; } |
| /// @returns true if token is a '%' |
| bool IsMod() const { return type_ == Type::kMod; } |
| /// @returns true if token is a '-' |
| bool IsMinus() const { return type_ == Type::kMinus; } |
| /// @returns true if token is a '::' |
| bool IsNamespace() const { return type_ == Type::kNamespace; } |
| /// @returns true if token is a '!=' |
| bool IsNotEqual() const { return type_ == Type::kNotEqual; } |
| /// @returns true if token is a '.' |
| bool IsPeriod() const { return type_ == Type::kPeriod; } |
| /// @returns true if token is a '+' |
| bool IsPlus() const { return type_ == Type::kPlus; } |
| /// @returns true if token is a '|' |
| bool IsOr() const { return type_ == Type::kOr; } |
| /// @returns true if token is a '||' |
| bool IsOrOr() const { return type_ == Type::kOrOr; } |
| /// @returns true if token is a '(' |
| bool IsParenLeft() const { return type_ == Type::kParenLeft; } |
| /// @returns true if token is a ')' |
| bool IsParenRight() const { return type_ == Type::kParenRight; } |
| /// @returns true if token is a ';' |
| bool IsSemicolon() const { return type_ == Type::kSemicolon; } |
| /// @returns true if token is a '*' |
| bool IsStar() const { return type_ == Type::kStar; } |
| /// @returns true if token is a '^' |
| bool IsXor() const { return type_ == Type::kXor; } |
| |
| /// @returns true if token is a 'array' |
| bool IsArray() const { return type_ == Type::kArray; } |
| /// @returns true if token is a 'as' |
| bool IsAs() const { return type_ == Type::kAs; } |
| /// @returns true if token is a 'binding' |
| bool IsBinding() const { return type_ == Type::kBinding; } |
| /// @returns true if token is a 'block' |
| bool IsBlock() const { return type_ == Type::kBlock; } |
| /// @returns true if token is a 'bool' |
| bool IsBool() const { return type_ == Type::kBool; } |
| /// @returns true if token is a 'break' |
| bool IsBreak() const { return type_ == Type::kBreak; } |
| /// @returns true if token is a 'builtin' |
| bool IsBuiltin() const { return type_ == Type::kBuiltin; } |
| /// @returns true if token is a 'case' |
| bool IsCase() const { return type_ == Type::kCase; } |
| /// @returns true if token is a 'cast' |
| bool IsCast() const { return type_ == Type::kCast; } |
| /// @returns true if token is a 'compute' |
| bool IsCompute() const { return type_ == Type::kCompute; } |
| /// @returns true if token is a 'const' |
| bool IsConst() const { return type_ == Type::kConst; } |
| /// @returns true if token is a 'continue' |
| bool IsContinue() const { return type_ == Type::kContinue; } |
| /// @returns true if token is a 'continuing' |
| bool IsContinuing() const { return type_ == Type::kContinuing; } |
| /// @returns true if token is a 'discard' |
| bool IsDiscard() const { return type_ == Type::kDiscard; } |
| /// @returns true if token is a 'default' |
| bool IsDefault() const { return type_ == Type::kDefault; } |
| /// @returns true if token is a 'else' |
| bool IsElse() const { return type_ == Type::kElse; } |
| /// @returns true if token is a 'elseif' |
| bool IsElseIf() const { return type_ == Type::kElseIf; } |
| /// @returns true if token is a 'entry_point' |
| bool IsEntryPoint() const { return type_ == Type::kEntryPoint; } |
| /// @returns true if token is a 'f32' |
| bool IsF32() const { return type_ == Type::kF32; } |
| /// @returns true if token is a 'fallthrough' |
| bool IsFallthrough() const { return type_ == Type::kFallthrough; } |
| /// @returns true if token is a 'false' |
| bool IsFalse() const { return type_ == Type::kFalse; } |
| /// @returns true if token is a 'fn' |
| bool IsFn() const { return type_ == Type::kFn; } |
| /// @returns true if token is a 'for' |
| bool IsFor() const { return type_ == Type::kFor; } |
| /// @returns true if token is a 'fragment' |
| bool IsFragment() const { return type_ == Type::kFragment; } |
| /// @returns true if token is a 'function' |
| bool IsFunction() const { return type_ == Type::kFunction; } |
| /// @returns true if token is a 'i32' |
| bool IsI32() const { return type_ == Type::kI32; } |
| /// @returns true if token is a 'if' |
| bool IsIf() const { return type_ == Type::kIf; } |
| /// @returns true if token is a 'image' |
| bool IsImage() const { return type_ == Type::kImage; } |
| /// @returns true if token is a 'import' |
| bool IsImport() const { return type_ == Type::kImport; } |
| /// @returns true if token is a 'in' |
| bool IsIn() const { return type_ == Type::kIn; } |
| /// @returns true if token is a 'location' |
| bool IsLocation() const { return type_ == Type::kLocation; } |
| /// @returns true if token is a 'loop' |
| bool IsLoop() const { return type_ == Type::kLoop; } |
| /// @returns true if token is a 'mat2x2' |
| bool IsMat2x2() const { return type_ == Type::kMat2x2; } |
| /// @returns true if token is a 'mat2x3' |
| bool IsMat2x3() const { return type_ == Type::kMat2x3; } |
| /// @returns true if token is a 'mat2x4' |
| bool IsMat2x4() const { return type_ == Type::kMat2x4; } |
| /// @returns true if token is a 'mat3x2' |
| bool IsMat3x2() const { return type_ == Type::kMat3x2; } |
| /// @returns true if token is a 'mat3x3' |
| bool IsMat3x3() const { return type_ == Type::kMat3x3; } |
| /// @returns true if token is a 'mat3x4' |
| bool IsMat3x4() const { return type_ == Type::kMat3x4; } |
| /// @returns true if token is a 'mat4x2' |
| bool IsMat4x2() const { return type_ == Type::kMat4x2; } |
| /// @returns true if token is a 'mat4x3' |
| bool IsMat4x3() const { return type_ == Type::kMat4x3; } |
| /// @returns true if token is a 'mat4x4' |
| bool IsMat4x4() const { return type_ == Type::kMat4x4; } |
| /// @returns true if token is a 'offset' |
| bool IsOffset() const { return type_ == Type::kOffset; } |
| /// @returns true if token is a 'out' |
| bool IsOut() const { return type_ == Type::kOut; } |
| /// @returns true if token is a 'private' |
| bool IsPrivate() const { return type_ == Type::kPrivate; } |
| /// @returns true if token is a 'ptr' |
| bool IsPtr() const { return type_ == Type::kPtr; } |
| /// @returns true if token is a 'return' |
| bool IsReturn() const { return type_ == Type::kReturn; } |
| /// @returns true if token is a 'sampler' |
| bool IsSampler() const { return type_ == Type::kSampler; } |
| /// @returns true if token is a 'sampler_comparison' |
| bool IsComparisonSampler() const { return type_ == Type::kComparisonSampler; } |
| /// @returns true if token is a 'set' |
| bool IsSet() const { return type_ == Type::kSet; } |
| /// @returns true if token is a 'storage_buffer' |
| bool IsStorageBuffer() const { return type_ == Type::kStorageBuffer; } |
| /// @returns true if token is a 'stride' |
| bool IsStride() const { return type_ == Type::kStride; } |
| /// @returns true if token is a 'struct' |
| bool IsStruct() const { return type_ == Type::kStruct; } |
| /// @returns true if token is a 'switch' |
| bool IsSwitch() const { return type_ == Type::kSwitch; } |
| /// @returns true if token is a 'texture_depth_2d' |
| bool IsTextureDepth2d() const { return type_ == Type::kTextureDepth2d; } |
| /// @returns true if token is a 'texture_depth_2d_array' |
| bool IsTextureDepth2dArray() const { |
| return type_ == Type::kTextureDepth2dArray; |
| } |
| /// @returns true if token is a 'texture_depth_cube' |
| bool IsTextureDepthCube() const { return type_ == Type::kTextureDepthCube; } |
| /// @returns true if token is a 'texture_depth_cube_array' |
| bool IsTextureDepthCubeArray() const { |
| return type_ == Type::kTextureDepthCubeArray; |
| } |
| /// @returns true if token is a 'true' |
| bool IsTrue() const { return type_ == Type::kTrue; } |
| /// @returns true if token is a 'type' |
| bool IsType() const { return type_ == Type::kType; } |
| /// @returns true if token is a 'u32' |
| bool IsU32() const { return type_ == Type::kU32; } |
| /// @returns true if token is a 'uniform' |
| bool IsUniform() const { return type_ == Type::kUniform; } |
| /// @returns true if token is a 'uniform_constant' |
| bool IsUniformConstant() const { return type_ == Type::kUniformConstant; } |
| /// @returns true if token is a 'var' |
| bool IsVar() const { return type_ == Type::kVar; } |
| /// @returns true if token is a 'vec2' |
| bool IsVec2() const { return type_ == Type::kVec2; } |
| /// @returns true if token is a 'vec3' |
| bool IsVec3() const { return type_ == Type::kVec3; } |
| /// @returns true if token is a 'vec4' |
| bool IsVec4() const { return type_ == Type::kVec4; } |
| /// @returns true if token is a 'vertex' |
| bool IsVertex() const { return type_ == Type::kVertex; } |
| /// @returns true if token is a 'void' |
| bool IsVoid() const { return type_ == Type::kVoid; } |
| /// @returns true if token is a 'workgroup' |
| bool IsWorkgroup() const { return type_ == Type::kWorkgroup; } |
| |
| /// @returns the source line of the token |
| size_t line() const { return source_.line; } |
| /// @returns the source column of the token |
| size_t column() const { return source_.column; } |
| /// @returns the source information for this token |
| Source source() const { return source_; } |
| |
| /// Returns the string value of the token |
| /// @return const std::string& |
| std::string to_str() const; |
| /// Returns the float value of the token. 0 is returned if the token does not |
| /// contain a float value. |
| /// @return float |
| float to_f32() const; |
| /// Returns the uint32 value of the token. 0 is returned if the token does not |
| /// contain a unsigned integer value. |
| /// @return uint32_t |
| uint32_t to_u32() const; |
| /// Returns the int32 value of the token. 0 is returned if the token does not |
| /// contain a signed integer value. |
| /// @return int32_t |
| int32_t to_i32() const; |
| |
| /// @returns the token type as string |
| std::string to_name() const { return Token::TypeToName(type_); } |
| |
| private: |
| /// The Token::Type of the token |
| Type type_ = Type::kError; |
| /// The source where the token appeared |
| Source source_; |
| /// The string represented by the token |
| std::string val_str_; |
| /// The signed integer represented by the token |
| int32_t val_int_ = 0; |
| /// The unsigned integer represented by the token |
| uint32_t val_uint_ = 0; |
| /// The float value represented by the token |
| float val_float_ = 0.0; |
| }; |
| |
| #ifndef NDEBUG |
| inline std::ostream& operator<<(std::ostream& out, Token::Type type) { |
| out << Token::TypeToName(type); |
| return out; |
| } |
| #endif // NDEBUG |
| |
| } // namespace wgsl |
| } // namespace reader |
| } // namespace tint |
| |
| #endif // SRC_READER_WGSL_TOKEN_H_ |