summaryrefslogtreecommitdiffstats
path: root/source/slang/parser.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-28 10:20:16 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-28 11:08:03 -0700
commitd601921b71ed44835e8d4fa6f13ff7aefcf7649d (patch)
tree79b9227ef038d173d780a440035e616dc31104bb /source/slang/parser.cpp
parent4b3936e2983dcecd36a3437bd6c7eef8d5fbbffa (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.cpp136
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;