Robust distinction between IDENTIFIER and TYPE_NAME tokens.

To distinguish the tokens we used to track the lexer context, which is fragile. This patch implements a better way - combine the two tokens into a common parser rule and let the parser context decide if the declaration is valid, which it already does by checking the naming conflicts. TEST=WebGL conformance tests. Review URL: https://codereview.appspot.com/8797044 Conflicts: src/compiler/glslang_tab.cpp src/compiler/glslang_tab.h git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@2229 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 7b999bd2
......@@ -33,10 +33,8 @@ struct TParseContext {
compileOptions(options),
sourcePath(sourcePath),
treeRoot(0),
lexAfterType(false),
loopNestingLevel(0),
structNestingLevel(0),
inTypeParen(false),
currentFunctionType(NULL),
functionReturnsValue(false),
checksPrecisionErrors(checksPrecErrors),
......@@ -51,10 +49,8 @@ struct TParseContext {
int compileOptions;
const char* sourcePath; // Path of source file or NULL.
TIntermNode* treeRoot; // root of parse tree being created
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // incremented while parsing a struct declaration
bool inTypeParen; // true if in parentheses, looking only for an identifier
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
......
......@@ -98,36 +98,36 @@ O [0-7]
"out" { return OUT_QUAL; }
"inout" { return INOUT_QUAL; }
"float" { context->lexAfterType = true; return FLOAT_TYPE; }
"int" { context->lexAfterType = true; return INT_TYPE; }
"void" { context->lexAfterType = true; return VOID_TYPE; }
"bool" { context->lexAfterType = true; return BOOL_TYPE; }
"float" { return FLOAT_TYPE; }
"int" { return INT_TYPE; }
"void" { return VOID_TYPE; }
"bool" { return BOOL_TYPE; }
"true" { yylval->lex.b = true; return BOOLCONSTANT; }
"false" { yylval->lex.b = false; return BOOLCONSTANT; }
"discard" { return DISCARD; }
"return" { return RETURN; }
"mat2" { context->lexAfterType = true; return MATRIX2; }
"mat3" { context->lexAfterType = true; return MATRIX3; }
"mat4" { context->lexAfterType = true; return MATRIX4; }
"mat2" { return MATRIX2; }
"mat3" { return MATRIX3; }
"mat4" { return MATRIX4; }
"vec2" { context->lexAfterType = true; return VEC2; }
"vec3" { context->lexAfterType = true; return VEC3; }
"vec4" { context->lexAfterType = true; return VEC4; }
"ivec2" { context->lexAfterType = true; return IVEC2; }
"ivec3" { context->lexAfterType = true; return IVEC3; }
"ivec4" { context->lexAfterType = true; return IVEC4; }
"bvec2" { context->lexAfterType = true; return BVEC2; }
"bvec3" { context->lexAfterType = true; return BVEC3; }
"bvec4" { context->lexAfterType = true; return BVEC4; }
"vec2" { return VEC2; }
"vec3" { return VEC3; }
"vec4" { return VEC4; }
"ivec2" { return IVEC2; }
"ivec3" { return IVEC3; }
"ivec4" { return IVEC4; }
"bvec2" { return BVEC2; }
"bvec3" { return BVEC3; }
"bvec4" { return BVEC4; }
"sampler2D" { context->lexAfterType = true; return SAMPLER2D; }
"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; }
"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; }
"sampler2D" { return SAMPLER2D; }
"samplerCube" { return SAMPLERCUBE; }
"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
"sampler2DRect" { return SAMPLER2DRECT; }
"struct" { context->lexAfterType = true; return STRUCT; }
"struct" { return STRUCT; }
"asm" { return reserved_word(yyscanner); }
......@@ -222,14 +222,14 @@ O [0-7]
"!=" { return NE_OP; }
"<<" { return LEFT_OP; }
">>" { return RIGHT_OP; }
";" { context->lexAfterType = false; return SEMICOLON; }
("{"|"<%") { context->lexAfterType = false; return LEFT_BRACE; }
";" { return SEMICOLON; }
("{"|"<%") { return LEFT_BRACE; }
("}"|"%>") { return RIGHT_BRACE; }
"," { if (context->inTypeParen) context->lexAfterType = false; return COMMA; }
"," { return COMMA; }
":" { return COLON; }
"=" { context->lexAfterType = false; return EQUAL; }
"(" { context->lexAfterType = false; context->inTypeParen = true; return LEFT_PAREN; }
")" { context->inTypeParen = false; return RIGHT_PAREN; }
"=" { return EQUAL; }
"(" { return LEFT_PAREN; }
")" { return RIGHT_PAREN; }
("["|"<:") { return LEFT_BRACKET; }
("]"|":>") { return RIGHT_BRACKET; }
"." { BEGIN(FIELDS); return DOT; }
......@@ -280,12 +280,10 @@ int check_type(yyscan_t yyscanner) {
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext);
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
yyextra->lexAfterType = true;
if (variable->isUserType())
token = TYPE_NAME;
}
}
yylval->lex.symbol = symbol;
return token;
......
......@@ -127,6 +127,7 @@ extern void yyerror(TParseContext* context, const char* reason);
%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
%type <lex> identifier
%type <interm> assignment_operator unary_operator
%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
%type <interm.intermTypedNode> expression integer_expression assignment_expression
......@@ -164,6 +165,10 @@ extern void yyerror(TParseContext* context, const char* reason);
%start translation_unit
%%
identifier
: IDENTIFIER
| TYPE_NAME
variable_identifier
: IDENTIFIER {
// The symbol table search was done in the lexical phase
......@@ -1102,7 +1107,7 @@ function_header
parameter_declarator
// Type + name
: type_specifier IDENTIFIER {
: type_specifier identifier {
if ($1.type == EbtVoid) {
context->error($2.line, "illegal use of type 'void'", $2.string->c_str());
context->recover();
......@@ -1113,7 +1118,7 @@ parameter_declarator
$$.line = $2.line;
$$.param = param;
}
| type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
| type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
// Check that we can make an array out of this type
if (context->arrayTypeErrorCheck($3.line, $1))
context->recover();
......@@ -1197,7 +1202,7 @@ init_declarator_list
: single_declaration {
$$ = $1;
}
| init_declarator_list COMMA IDENTIFIER {
| init_declarator_list COMMA identifier {
if ($1.type.type == EbtInvariant && !$3.symbol)
{
context->error($3.line, "undeclared identifier declared as invariant", $3.string->c_str());
......@@ -1219,7 +1224,7 @@ init_declarator_list
if (symbol && variable)
symbol->setId(variable->getUniqueId());
}
| init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
| init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET {
if (context->structQualifierErrorCheck($3.line, $1.type))
context->recover();
......@@ -1237,7 +1242,7 @@ init_declarator_list
context->recover();
}
}
| init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
| init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
if (context->structQualifierErrorCheck($3.line, $1.type))
context->recover();
......@@ -1261,7 +1266,7 @@ init_declarator_list
$$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line);
}
}
| init_declarator_list COMMA IDENTIFIER EQUAL initializer {
| init_declarator_list COMMA identifier EQUAL initializer {
if (context->structQualifierErrorCheck($3.line, $1.type))
context->recover();
......@@ -1288,7 +1293,7 @@ single_declaration
$$.type = $1;
$$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
}
| fully_specified_type IDENTIFIER {
| fully_specified_type identifier {
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
......@@ -1306,7 +1311,7 @@ single_declaration
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
| fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
| fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
context->error($2.line, "unsized array declarations not supported", $2.string->c_str());
context->recover();
......@@ -1314,7 +1319,7 @@ single_declaration
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
$$.type = $1;
}
| fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
| fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
TType type = TType($1);
int size;
if (context->arraySizeErrorCheck($2.line, $4, size))
......@@ -1346,7 +1351,7 @@ single_declaration
symbol->setId(variable->getUniqueId());
}
}
| fully_specified_type IDENTIFIER EQUAL initializer {
| fully_specified_type identifier EQUAL initializer {
if (context->structQualifierErrorCheck($2.line, $1))
context->recover();
......@@ -1697,7 +1702,7 @@ type_specifier_nonarray
;
struct_specifier
: STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
: STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
if (context->reservedErrorCheck($2.line, *$2.string))
context->recover();
......@@ -1784,7 +1789,7 @@ struct_declarator_list
;
struct_declarator
: IDENTIFIER {
: identifier {
if (context->reservedErrorCheck($1.line, *$1.string))
context->recover();
......@@ -1792,7 +1797,7 @@ struct_declarator
$$.line = $1.line;
$$.type->setFieldName(*$1.string);
}
| IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
| identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
if (context->reservedErrorCheck($1.line, *$1.string))
context->recover();
......@@ -1907,7 +1912,7 @@ condition
if (context->boolErrorCheck($1->getLine(), $1))
context->recover();
}
| fully_specified_type IDENTIFIER EQUAL initializer {
| fully_specified_type identifier EQUAL initializer {
TIntermNode* intermNode;
if (context->structQualifierErrorCheck($2.line, $1))
context->recover();
......
......@@ -1214,19 +1214,19 @@ YY_RULE_SETUP
YY_BREAK
case 20:
YY_RULE_SETUP
{ context->lexAfterType = true; return FLOAT_TYPE; }
{ return FLOAT_TYPE; }
YY_BREAK
case 21:
YY_RULE_SETUP
{ context->lexAfterType = true; return INT_TYPE; }
{ return INT_TYPE; }
YY_BREAK
case 22:
YY_RULE_SETUP
{ context->lexAfterType = true; return VOID_TYPE; }
{ return VOID_TYPE; }
YY_BREAK
case 23:
YY_RULE_SETUP
{ context->lexAfterType = true; return BOOL_TYPE; }
{ return BOOL_TYPE; }
YY_BREAK
case 24:
YY_RULE_SETUP
......@@ -1246,71 +1246,71 @@ YY_RULE_SETUP
YY_BREAK
case 28:
YY_RULE_SETUP
{ context->lexAfterType = true; return MATRIX2; }
{ return MATRIX2; }
YY_BREAK
case 29:
YY_RULE_SETUP
{ context->lexAfterType = true; return MATRIX3; }
{ return MATRIX3; }
YY_BREAK
case 30:
YY_RULE_SETUP
{ context->lexAfterType = true; return MATRIX4; }
{ return MATRIX4; }
YY_BREAK
case 31:
YY_RULE_SETUP
{ context->lexAfterType = true; return VEC2; }
{ return VEC2; }
YY_BREAK
case 32:
YY_RULE_SETUP
{ context->lexAfterType = true; return VEC3; }
{ return VEC3; }
YY_BREAK
case 33:
YY_RULE_SETUP
{ context->lexAfterType = true; return VEC4; }
{ return VEC4; }
YY_BREAK
case 34:
YY_RULE_SETUP
{ context->lexAfterType = true; return IVEC2; }
{ return IVEC2; }
YY_BREAK
case 35:
YY_RULE_SETUP
{ context->lexAfterType = true; return IVEC3; }
{ return IVEC3; }
YY_BREAK
case 36:
YY_RULE_SETUP
{ context->lexAfterType = true; return IVEC4; }
{ return IVEC4; }
YY_BREAK
case 37:
YY_RULE_SETUP
{ context->lexAfterType = true; return BVEC2; }
{ return BVEC2; }
YY_BREAK
case 38:
YY_RULE_SETUP
{ context->lexAfterType = true; return BVEC3; }
{ return BVEC3; }
YY_BREAK
case 39:
YY_RULE_SETUP
{ context->lexAfterType = true; return BVEC4; }
{ return BVEC4; }
YY_BREAK
case 40:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLER2D; }
{ return SAMPLER2D; }
YY_BREAK
case 41:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLERCUBE; }
{ return SAMPLERCUBE; }
YY_BREAK
case 42:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
{ return SAMPLER_EXTERNAL_OES; }
YY_BREAK
case 43:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLER2DRECT; }
{ return SAMPLER2DRECT; }
YY_BREAK
case 44:
YY_RULE_SETUP
{ context->lexAfterType = true; return STRUCT; }
{ return STRUCT; }
YY_BREAK
case 45:
YY_RULE_SETUP
......@@ -1621,11 +1621,11 @@ YY_RULE_SETUP
YY_BREAK
case 121:
YY_RULE_SETUP
{ context->lexAfterType = false; return SEMICOLON; }
{ return SEMICOLON; }
YY_BREAK
case 122:
YY_RULE_SETUP
{ context->lexAfterType = false; return LEFT_BRACE; }
{ return LEFT_BRACE; }
YY_BREAK
case 123:
YY_RULE_SETUP
......@@ -1633,7 +1633,7 @@ YY_RULE_SETUP
YY_BREAK
case 124:
YY_RULE_SETUP
{ if (context->inTypeParen) context->lexAfterType = false; return COMMA; }
{ return COMMA; }
YY_BREAK
case 125:
YY_RULE_SETUP
......@@ -1641,15 +1641,15 @@ YY_RULE_SETUP
YY_BREAK
case 126:
YY_RULE_SETUP
{ context->lexAfterType = false; return EQUAL; }
{ return EQUAL; }
YY_BREAK
case 127:
YY_RULE_SETUP
{ context->lexAfterType = false; context->inTypeParen = true; return LEFT_PAREN; }
{ return LEFT_PAREN; }
YY_BREAK
case 128:
YY_RULE_SETUP
{ context->inTypeParen = false; return RIGHT_PAREN; }
{ return RIGHT_PAREN; }
YY_BREAK
case 129:
YY_RULE_SETUP
......@@ -2934,12 +2934,10 @@ int check_type(yyscan_t yyscanner) {
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext);
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
yyextra->lexAfterType = true;
if (variable->isUserType())
token = TYPE_NAME;
}
}
yylval->lex.symbol = symbol;
return token;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment