diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-06-28 10:20:16 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-06-28 11:08:03 -0700 |
| commit | d601921b71ed44835e8d4fa6f13ff7aefcf7649d (patch) | |
| tree | 79b9227ef038d173d780a440035e616dc31104bb /source/slang/parser.cpp | |
| parent | 4b3936e2983dcecd36a3437bd6c7eef8d5fbbffa (diff) | |
Actually respect suffixes on numeric literals.
- Add logic to extract the value and suffix from a numeric literal
- This duplicates some of the lexing logic, but this is hard to avoid without redundant runtime work
- Note that I'm not using and stdlib string-to-number code. This should be more robust once it is working, but it is obviously error prone in the near term. The main up-sides to this are:
- We can handle binary integer literals
- We can handle hexadecimal floating-point literals without stdlib support
- We can hypothetically support digit separators, if we ever wanted
- The parser looks at the suffix characters sliced off by the lexer, and tries to pick a type to use for a literal
- It uses `NULL` if there is no suffix, to avoid some nasty order dependencies where the stdlib might need to parse a number before it has seen the definition of `int`
- Right now I only handle a few cases, so there may be bugs lurking here
- The emit logic needs to handle the fact that a literal node in the AST might have a non-default type attached.
- Right now I just quickly check for the most likely types, and emit the literal with a matching suffix. This doesn't seem robust if any source language supports a suffix for a type where a target has no corresponding suffix. In the long term some amount of casting is probably required.
Diffstat (limited to 'source/slang/parser.cpp')
| -rw-r--r-- | source/slang/parser.cpp | 136 |
1 files changed, 128 insertions, 8 deletions
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 5e93d63cb..6437deca2 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -3214,22 +3214,140 @@ namespace Slang } case TokenType::IntegerLiteral: - case TokenType::FloatingPointLiteral: { RefPtr<ConstantExpressionSyntaxNode> constExpr = new ConstantExpressionSyntaxNode(); - auto token = parser->tokenReader.AdvanceToken(); parser->FillPosition(constExpr.Ptr()); - if (token.Type == TokenType::IntegerLiteral) + + auto token = parser->tokenReader.AdvanceToken(); + constExpr->token = token; + + String suffix; + IntegerLiteralValue value = getIntegerLiteralValue(token, &suffix); + + // Look at any suffix on the value + char const* suffixCursor = suffix.begin(); + + RefPtr<ExpressionType> suffixType = nullptr; + if( suffixCursor && *suffixCursor ) { - constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Int; - constExpr->IntValue = StringToInt(token.Content); + int lCount = 0; + int uCount = 0; + int unknownCount = 0; + while(*suffixCursor) + { + switch( *suffixCursor++ ) + { + case 'l': case 'L': + lCount++; + break; + + case 'u': case 'U': + uCount++; + break; + + default: + unknownCount++; + break; + } + } + + if(unknownCount) + { + parser->sink->diagnose(token, Diagnostics::invalidIntegerLiteralSuffix, suffix); + suffixType = ExpressionType::GetError(); + } + // `u` or `ul` suffix -> `uint` + else if(uCount == 1 && (lCount <= 1)) + { + suffixType = ExpressionType::GetUInt(); + } + // `l` suffix on integer -> `int` (== `long`) + else if(lCount == 1 && !uCount) + { + suffixType = ExpressionType::GetInt(); + } + // TODO: probably need `ll` and `ull` + // TODO: are there other suffixes we need to handle? + else + { + parser->sink->diagnose(token, Diagnostics::invalidIntegerLiteralSuffix, suffix); + suffixType = ExpressionType::GetError(); + } } - else if (token.Type == TokenType::FloatingPointLiteral) + + constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Int; + constExpr->IntValue = value; + constExpr->Type = suffixType; + + return constExpr; + } + + + case TokenType::FloatingPointLiteral: + { + RefPtr<ConstantExpressionSyntaxNode> constExpr = new ConstantExpressionSyntaxNode(); + parser->FillPosition(constExpr.Ptr()); + + auto token = parser->tokenReader.AdvanceToken(); + constExpr->token = token; + + String suffix; + FloatingPointLiteralValue value = getFloatingPointLiteralValue(token, &suffix); + + // Look at any suffix on the value + char const* suffixCursor = suffix.begin(); + + RefPtr<ExpressionType> suffixType = nullptr; + if( suffixCursor && *suffixCursor ) { - constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Float; - constExpr->FloatValue = (FloatingPointLiteralValue) StringToDouble(token.Content); + int fCount = 0; + int lCount = 0; + int unknownCount = 0; + while(*suffixCursor) + { + switch( *suffixCursor++ ) + { + case 'f': case 'F': + fCount++; + break; + + case 'l': case 'L': + lCount++; + break; + + default: + unknownCount++; + break; + } + } + + if(unknownCount) + { + parser->sink->diagnose(token, Diagnostics::invalidFloatingPOintLiteralSuffix, suffix); + suffixType = ExpressionType::GetError(); + } + // `f` suffix -> `float` + if(fCount == 1 && !lCount) + { + suffixType = ExpressionType::GetFloat(); + } + // `l` or `lf` suffix on float -> `double` + else if(lCount == 1 && (fCount <= 1)) + { + suffixType = ExpressionType::getDoubleType(); + } + // TODO: are there other suffixes we need to handle? + else + { + parser->sink->diagnose(token, Diagnostics::invalidFloatingPOintLiteralSuffix, suffix); + suffixType = ExpressionType::GetError(); + } } + constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Float; + constExpr->FloatValue = value; + constExpr->Type = suffixType; + return constExpr; } @@ -3237,6 +3355,7 @@ namespace Slang { RefPtr<ConstantExpressionSyntaxNode> constExpr = new ConstantExpressionSyntaxNode(); auto token = parser->tokenReader.AdvanceToken(); + constExpr->token = token; parser->FillPosition(constExpr.Ptr()); constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::String; @@ -3269,6 +3388,7 @@ namespace Slang { RefPtr<ConstantExpressionSyntaxNode> constExpr = new ConstantExpressionSyntaxNode(); auto token = parser->tokenReader.AdvanceToken(); + constExpr->token = token; parser->FillPosition(constExpr.Ptr()); constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Bool; constExpr->IntValue = token.Content == "true" ? 1 : 0; |
