From d0d9aae96800844756a6784363ec510aebb69a70 Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Wed, 28 Mar 2012 10:10:51 -0700 Subject: [PATCH] Fix parser so that spaces aren't needed around "..." in foreach statements. Issue #207. --- lex.ll | 121 ++++++++++++++++++++++++++++++++++--------------------- parse.yy | 32 +++++++++++++-- 2 files changed, 104 insertions(+), 49 deletions(-) diff --git a/lex.ll b/lex.ll index 4130372f..96c19d1d 100644 --- a/lex.ll +++ b/lex.ll @@ -43,6 +43,7 @@ #include static uint64_t lParseBinary(const char *ptr, SourcePos pos, char **endPtr); +static int lParseInteger(bool dotdotdot); static void lCComment(SourcePos *); static void lCppComment(SourcePos *); static void lHandleCppHash(SourcePos *); @@ -322,7 +323,8 @@ inline int ispcRand() { %option nounistd WHITESPACE [ \t\r]+ -INT_NUMBER (([0-9]+)|(0x[0-9a-fA-F]+)|(0b[01]+))[kMG]? +INT_NUMBER (([0-9]+)|(0x[0-9a-fA-F]+)|(0b[01]+))[uUlL]*[kMG]?[uUlL]* +INT_NUMBER_DOTDOTDOT (([0-9]+)|(0x[0-9a-fA-F]+)|(0b[01]+))[uUlL]*[kMG]?[uUlL]*\.\.\. FLOAT_NUMBER (([0-9]+|(([0-9]+\.[0-9]*[fF]?)|(\.[0-9]+)))([eE][-+]?[0-9]+)?[fF]?) HEX_FLOAT_NUMBER (0x[01](\.[0-9a-fA-F]*)?p[-+]?[0-9]+[fF]?) @@ -406,53 +408,14 @@ L?\"(\\.|[^\\"])*\" { lStringConst(&yylval, &yylloc); return TOKEN_STRING_LITERA return TOKEN_IDENTIFIER; } -{INT_NUMBER}+(u|U|l|L)*? { +{INT_NUMBER} { RT; - int ls = 0, us = 0; + return lParseInteger(false); +} - char *endPtr = NULL; - if (yytext[0] == '0' && yytext[1] == 'b') - yylval.intVal = lParseBinary(yytext+2, yylloc, &endPtr); - else { -#if defined(ISPC_IS_WINDOWS) && !defined(__MINGW32__) - yylval.intVal = _strtoui64(yytext, &endPtr, 0); -#else - // FIXME: should use strtouq and then issue an error if we can't - // fit into 64 bits... - yylval.intVal = strtoull(yytext, &endPtr, 0); -#endif - } - - bool kilo = false, mega = false, giga = false; - for (; *endPtr; endPtr++) { - if (*endPtr == 'k') - kilo = true; - else if (*endPtr == 'M') - mega = true; - else if (*endPtr == 'G') - giga = true; - else if (*endPtr == 'l' || *endPtr == 'L') - ls++; - else if (*endPtr == 'u' || *endPtr == 'U') - us++; - } - if (kilo) - yylval.intVal *= 1024; - if (mega) - yylval.intVal *= 1024*1024; - if (giga) - yylval.intVal *= 1024*1024*1024; - - if (ls >= 2) - return us ? TOKEN_UINT64_CONSTANT : TOKEN_INT64_CONSTANT; - else if (ls == 1) - return us ? TOKEN_UINT32_CONSTANT : TOKEN_INT32_CONSTANT; - - // See if we can fit this into a 32-bit integer... - if ((yylval.intVal & 0xffffffff) == yylval.intVal) - return us ? TOKEN_UINT32_CONSTANT : TOKEN_INT32_CONSTANT; - else - return us ? TOKEN_UINT64_CONSTANT : TOKEN_INT64_CONSTANT; +{INT_NUMBER_DOTDOTDOT} { + RT; + return lParseInteger(true); } @@ -562,6 +525,72 @@ lParseBinary(const char *ptr, SourcePos pos, char **endPtr) { } +static int +lParseInteger(bool dotdotdot) { + int ls = 0, us = 0; + + char *endPtr = NULL; + if (yytext[0] == '0' && yytext[1] == 'b') + yylval.intVal = lParseBinary(yytext+2, yylloc, &endPtr); + else { +#if defined(ISPC_IS_WINDOWS) && !defined(__MINGW32__) + yylval.intVal = _strtoui64(yytext, &endPtr, 0); +#else + // FIXME: should use strtouq and then issue an error if we can't + // fit into 64 bits... + yylval.intVal = strtoull(yytext, &endPtr, 0); +#endif + } + + bool kilo = false, mega = false, giga = false; + for (; *endPtr; endPtr++) { + if (*endPtr == 'k') + kilo = true; + else if (*endPtr == 'M') + mega = true; + else if (*endPtr == 'G') + giga = true; + else if (*endPtr == 'l' || *endPtr == 'L') + ls++; + else if (*endPtr == 'u' || *endPtr == 'U') + us++; + else + Assert(dotdotdot && *endPtr == '.'); + } + if (kilo) + yylval.intVal *= 1024; + if (mega) + yylval.intVal *= 1024*1024; + if (giga) + yylval.intVal *= 1024*1024*1024; + + if (dotdotdot) { + if (ls >= 2) + return us ? TOKEN_UINT64DOTDOTDOT_CONSTANT : TOKEN_INT64DOTDOTDOT_CONSTANT; + else if (ls == 1) + return us ? TOKEN_UINT32DOTDOTDOT_CONSTANT : TOKEN_INT32DOTDOTDOT_CONSTANT; + + // See if we can fit this into a 32-bit integer... + if ((yylval.intVal & 0xffffffff) == yylval.intVal) + return us ? TOKEN_UINT32DOTDOTDOT_CONSTANT : TOKEN_INT32DOTDOTDOT_CONSTANT; + else + return us ? TOKEN_UINT64DOTDOTDOT_CONSTANT : TOKEN_INT64DOTDOTDOT_CONSTANT; + } + else { + if (ls >= 2) + return us ? TOKEN_UINT64_CONSTANT : TOKEN_INT64_CONSTANT; + else if (ls == 1) + return us ? TOKEN_UINT32_CONSTANT : TOKEN_INT32_CONSTANT; + + // See if we can fit this into a 32-bit integer... + if ((yylval.intVal & 0xffffffff) == yylval.intVal) + return us ? TOKEN_UINT32_CONSTANT : TOKEN_INT32_CONSTANT; + else + return us ? TOKEN_UINT64_CONSTANT : TOKEN_INT64_CONSTANT; + } +} + + /** Handle a C-style comment in the source. */ static void diff --git a/parse.yy b/parse.yy index cffdc0c9..978b11d7 100644 --- a/parse.yy +++ b/parse.yy @@ -173,8 +173,11 @@ struct ForeachDimension { } -%token TOKEN_INT32_CONSTANT TOKEN_UINT32_CONSTANT TOKEN_INT64_CONSTANT -%token TOKEN_UINT64_CONSTANT TOKEN_FLOAT_CONSTANT TOKEN_STRING_C_LITERAL +%token TOKEN_INT32_CONSTANT TOKEN_UINT32_CONSTANT +%token TOKEN_INT64_CONSTANT TOKEN_UINT64_CONSTANT +%token TOKEN_INT32DOTDOTDOT_CONSTANT TOKEN_UINT32DOTDOTDOT_CONSTANT +%token TOKEN_INT64DOTDOTDOT_CONSTANT TOKEN_UINT64DOTDOTDOT_CONSTANT +%token TOKEN_FLOAT_CONSTANT TOKEN_STRING_C_LITERAL %token TOKEN_IDENTIFIER TOKEN_STRING_LITERAL TOKEN_TYPE_NAME TOKEN_NULL %token TOKEN_PTR_OP TOKEN_INC_OP TOKEN_DEC_OP TOKEN_LEFT_OP TOKEN_RIGHT_OP %token TOKEN_LE_OP TOKEN_GE_OP TOKEN_EQ_OP TOKEN_NE_OP @@ -196,7 +199,7 @@ struct ForeachDimension { %token TOKEN_CIF TOKEN_CDO TOKEN_CFOR TOKEN_CWHILE TOKEN_CBREAK %token TOKEN_CCONTINUE TOKEN_CRETURN TOKEN_SYNC TOKEN_PRINT TOKEN_ASSERT -%type primary_expression postfix_expression +%type primary_expression postfix_expression integer_dotdotdot %type unary_expression cast_expression funcall_expression launch_expression %type multiplicative_expression additive_expression shift_expression %type relational_expression equality_expression and_expression @@ -1620,11 +1623,34 @@ foreach_active_identifier } ; +integer_dotdotdot + : TOKEN_INT32DOTDOTDOT_CONSTANT { + $$ = new ConstExpr(AtomicType::UniformInt32->GetAsConstType(), + (int32_t)yylval.intVal, @1); + } + | TOKEN_UINT32DOTDOTDOT_CONSTANT { + $$ = new ConstExpr(AtomicType::UniformUInt32->GetAsConstType(), + (uint32_t)yylval.intVal, @1); + } + | TOKEN_INT64DOTDOTDOT_CONSTANT { + $$ = new ConstExpr(AtomicType::UniformInt64->GetAsConstType(), + (int64_t)yylval.intVal, @1); + } + | TOKEN_UINT64DOTDOTDOT_CONSTANT { + $$ = new ConstExpr(AtomicType::UniformUInt64->GetAsConstType(), + (uint64_t)yylval.intVal, @1); + } + ; + foreach_dimension_specifier : foreach_identifier '=' assignment_expression TOKEN_DOTDOTDOT assignment_expression { $$ = new ForeachDimension($1, $3, $5); } + | foreach_identifier '=' integer_dotdotdot assignment_expression + { + $$ = new ForeachDimension($1, $3, $4); + } ; foreach_dimension_list