Commit 78eb5dfb by Jamie Madill Committed by Shannon Woods

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. TRAC #23158 Signed-off-by: Nicolas Capens Merged-by: Jamie Madill Authored-by: alokp@chromium.org git-svn-url: https://code.google.com/p/angleproject/source/detail?r=2190 Review URL: https://codereview.appspot.com/8797044
parent 7eeb9b66
......@@ -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),
......@@ -53,10 +51,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.
......
......@@ -110,20 +110,20 @@ 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; }
"float" { return FLOAT_TYPE; }
"int" { return INT_TYPE; }
"uint" { return ES2_ident_ES3_keyword(context, UINT_TYPE); }
"void" { context->lexAfterType = true; return VOID_TYPE; }
"bool" { context->lexAfterType = true; return BOOL_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; }
"mat2x2" { return ES2_ident_ES3_keyword(context, MATRIX2); }
"mat3x3" { return ES2_ident_ES3_keyword(context, MATRIX3); }
......@@ -136,28 +136,28 @@ O [0-7]
"mat3x4" { return ES2_ident_ES3_keyword(context, MATRIX3x4); }
"mat4x3" { return ES2_ident_ES3_keyword(context, MATRIX4x3); }
"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; }
"uvec2" { return ES2_ident_ES3_keyword(context, UVEC2); }
"uvec3" { return ES2_ident_ES3_keyword(context, UVEC3); }
"uvec4" { return ES2_ident_ES3_keyword(context, UVEC4); }
"sampler2D" { context->lexAfterType = true; return SAMPLER2D; }
"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; }
"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
"sampler2D" { return SAMPLER2D; }
"samplerCube" { return SAMPLERCUBE; }
"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
"sampler3D" { return ES2_reserved_ES3_keyword(context, SAMPLER3D); }
"sampler3DRect" { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); }
"sampler2DShadow" { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); }
"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; }
"sampler2DRect" { return SAMPLER2DRECT; }
"struct" { context->lexAfterType = true; return STRUCT; }
"struct" { return STRUCT; }
"layout" { return ES2_ident_ES3_keyword(context, LAYOUT); }
......@@ -333,14 +333,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; }
......@@ -391,10 +391,9 @@ int check_type(yyscan_t yyscanner) {
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->shaderVersion);
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
yyextra->lexAfterType = true;
token = TYPE_NAME;
}
}
......
......@@ -148,6 +148,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
......@@ -189,6 +190,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
......@@ -918,7 +923,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();
......@@ -929,7 +934,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();
......@@ -1013,7 +1018,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());
......@@ -1035,7 +1040,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();
......@@ -1053,7 +1058,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();
......@@ -1077,7 +1082,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();
......@@ -1104,7 +1109,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);
......@@ -1122,7 +1127,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();
......@@ -1130,7 +1135,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))
......@@ -1162,7 +1167,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();
......@@ -1667,7 +1672,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 {
$$ = context->addStructure($1.line, $2.line, *$2.string, $5);
}
| STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
......@@ -1715,7 +1720,7 @@ struct_declarator_list
;
struct_declarator
: IDENTIFIER {
: identifier {
if (context->reservedErrorCheck($1.line, *$1.string))
context->recover();
......@@ -1723,7 +1728,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();
......@@ -1838,7 +1843,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();
......
......@@ -1427,11 +1427,11 @@ YY_RULE_SETUP
YY_BREAK
case 26:
YY_RULE_SETUP
{ context->lexAfterType = true; return FLOAT_TYPE; }
{ return FLOAT_TYPE; }
YY_BREAK
case 27:
YY_RULE_SETUP
{ context->lexAfterType = true; return INT_TYPE; }
{ return INT_TYPE; }
YY_BREAK
case 28:
YY_RULE_SETUP
......@@ -1439,11 +1439,11 @@ YY_RULE_SETUP
YY_BREAK
case 29:
YY_RULE_SETUP
{ context->lexAfterType = true; return VOID_TYPE; }
{ return VOID_TYPE; }
YY_BREAK
case 30:
YY_RULE_SETUP
{ context->lexAfterType = true; return BOOL_TYPE; }
{ return BOOL_TYPE; }
YY_BREAK
case 31:
YY_RULE_SETUP
......@@ -1463,15 +1463,15 @@ YY_RULE_SETUP
YY_BREAK
case 35:
YY_RULE_SETUP
{ context->lexAfterType = true; return MATRIX2; }
{ return MATRIX2; }
YY_BREAK
case 36:
YY_RULE_SETUP
{ context->lexAfterType = true; return MATRIX3; }
{ return MATRIX3; }
YY_BREAK
case 37:
YY_RULE_SETUP
{ context->lexAfterType = true; return MATRIX4; }
{ return MATRIX4; }
YY_BREAK
case 38:
YY_RULE_SETUP
......@@ -1511,39 +1511,39 @@ YY_RULE_SETUP
YY_BREAK
case 47:
YY_RULE_SETUP
{ context->lexAfterType = true; return VEC2; }
{ return VEC2; }
YY_BREAK
case 48:
YY_RULE_SETUP
{ context->lexAfterType = true; return VEC3; }
{ return VEC3; }
YY_BREAK
case 49:
YY_RULE_SETUP
{ context->lexAfterType = true; return VEC4; }
{ return VEC4; }
YY_BREAK
case 50:
YY_RULE_SETUP
{ context->lexAfterType = true; return IVEC2; }
{ return IVEC2; }
YY_BREAK
case 51:
YY_RULE_SETUP
{ context->lexAfterType = true; return IVEC3; }
{ return IVEC3; }
YY_BREAK
case 52:
YY_RULE_SETUP
{ context->lexAfterType = true; return IVEC4; }
{ return IVEC4; }
YY_BREAK
case 53:
YY_RULE_SETUP
{ context->lexAfterType = true; return BVEC2; }
{ return BVEC2; }
YY_BREAK
case 54:
YY_RULE_SETUP
{ context->lexAfterType = true; return BVEC3; }
{ return BVEC3; }
YY_BREAK
case 55:
YY_RULE_SETUP
{ context->lexAfterType = true; return BVEC4; }
{ return BVEC4; }
YY_BREAK
case 56:
YY_RULE_SETUP
......@@ -1559,15 +1559,15 @@ YY_RULE_SETUP
YY_BREAK
case 59:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLER2D; }
{ return SAMPLER2D; }
YY_BREAK
case 60:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLERCUBE; }
{ return SAMPLERCUBE; }
YY_BREAK
case 61:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
{ return SAMPLER_EXTERNAL_OES; }
YY_BREAK
case 62:
YY_RULE_SETUP
......@@ -1583,11 +1583,11 @@ YY_RULE_SETUP
YY_BREAK
case 65:
YY_RULE_SETUP
{ context->lexAfterType = true; return SAMPLER2DRECT; }
{ return SAMPLER2DRECT; }
YY_BREAK
case 66:
YY_RULE_SETUP
{ context->lexAfterType = true; return STRUCT; }
{ return STRUCT; }
YY_BREAK
case 67:
YY_RULE_SETUP
......@@ -1858,11 +1858,11 @@ YY_RULE_SETUP
YY_BREAK
case 200:
YY_RULE_SETUP
{ context->lexAfterType = false; return SEMICOLON; }
{ return SEMICOLON; }
YY_BREAK
case 201:
YY_RULE_SETUP
{ context->lexAfterType = false; return LEFT_BRACE; }
{ return LEFT_BRACE; }
YY_BREAK
case 202:
YY_RULE_SETUP
......@@ -1870,7 +1870,7 @@ YY_RULE_SETUP
YY_BREAK
case 203:
YY_RULE_SETUP
{ if (context->inTypeParen) context->lexAfterType = false; return COMMA; }
{ return COMMA; }
YY_BREAK
case 204:
YY_RULE_SETUP
......@@ -1878,15 +1878,15 @@ YY_RULE_SETUP
YY_BREAK
case 205:
YY_RULE_SETUP
{ context->lexAfterType = false; return EQUAL; }
{ return EQUAL; }
YY_BREAK
case 206:
YY_RULE_SETUP
{ context->lexAfterType = false; context->inTypeParen = true; return LEFT_PAREN; }
{ return LEFT_PAREN; }
YY_BREAK
case 207:
YY_RULE_SETUP
{ context->inTypeParen = false; return RIGHT_PAREN; }
{ return RIGHT_PAREN; }
YY_BREAK
case 208:
YY_RULE_SETUP
......@@ -3170,10 +3170,9 @@ int check_type(yyscan_t yyscanner) {
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->shaderVersion);
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
yyextra->lexAfterType = true;
token = TYPE_NAME;
}
}
......
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