Make preprocessor ExpressionParser only lex what it can parse
This cleans up ExpressionParser so that the lexer only consumes one extra
token in case the parser finishes. The parser will also finish with
YYACCEPT once it has parsed a complete expression. This will make the
preprocessor to generate a more informative unexpected token error
instead of a syntax error if there are extra tokens after #if.
This will also enable reusing ExpressionParser for parsing expressions in
line directives. The format for a line directive that specifies both line
and file numbers is as follows:
#if line-expression file_expression
ExpressionParser will need to be run twice for each line: first to parse
line-expression and then to parse file-expression. For that reason, it is
essential that ExpressionParser for line-expression stops before
consuming more than one token of file-expression.
BUG=angleproject:989
TEST=angle_unittests, dEQP-GLES3.functional.shaders.preprocessor.*
Change-Id: I0bb92f733c18891eeddbc61e7c5bebdf1003559a
Reviewed-on: https://chromium-review.googlesource.com/300962
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tryjob-Request: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/preprocessor/ExpressionParser.cpp b/src/compiler/preprocessor/ExpressionParser.cpp
index 27dc626..21064b7 100644
--- a/src/compiler/preprocessor/ExpressionParser.cpp
+++ b/src/compiler/preprocessor/ExpressionParser.cpp
@@ -110,6 +110,7 @@
#include <stdint.h>
typedef intmax_t YYSTYPE;
#endif // _MSC_VER
+
#define YYENABLE_NLS 0
#define YYLTYPE_IS_TRIVIAL 1
#define YYSTYPE_IS_TRIVIAL 1
@@ -495,9 +496,9 @@
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 105, 105, 111, 112, 118, 118, 139, 139, 160,
- 163, 166, 169, 172, 175, 178, 181, 184, 187, 190,
- 193, 196, 199, 222, 245, 248, 251, 254, 257, 260
+ 0, 106, 106, 113, 114, 124, 124, 145, 145, 166,
+ 169, 172, 175, 178, 181, 184, 187, 190, 193, 196,
+ 199, 202, 205, 224, 243, 246, 249, 252, 255, 258
};
#endif
@@ -1330,6 +1331,7 @@
{
*(context->result) = static_cast<int>((yyvsp[0]));
+ YYACCEPT;
}
break;
@@ -1339,8 +1341,12 @@
{
if (!context->isIgnoringErrors())
{
- YYABORT;
+ // This rule should be applied right after the token is lexed, so we can
+ // refer to context->token in the error message.
+ context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+ context->token->location, context->token->text);
}
+ (yyval) = (yyvsp[0]);
}
break;
@@ -1518,11 +1524,7 @@
{
if ((yyvsp[0]) == 0)
{
- if (context->isIgnoringErrors())
- {
- (yyval) = static_cast<YYSTYPE>(0);
- }
- else
+ if (!context->isIgnoringErrors())
{
std::ostringstream stream;
stream << (yyvsp[-2]) << " % " << (yyvsp[0]);
@@ -1530,8 +1532,8 @@
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location,
text.c_str());
- YYABORT;
}
+ (yyval) = static_cast<YYSTYPE>(0);
}
else
{
@@ -1546,11 +1548,7 @@
{
if ((yyvsp[0]) == 0)
{
- if (context->isIgnoringErrors())
- {
- (yyval) = static_cast<YYSTYPE>(0);
- }
- else
+ if (!context->isIgnoringErrors())
{
std::ostringstream stream;
stream << (yyvsp[-2]) << " / " << (yyvsp[0]);
@@ -1558,8 +1556,8 @@
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location,
text.c_str());
- YYABORT;
}
+ (yyval) = static_cast<YYSTYPE>(0);
}
else
{
@@ -1851,9 +1849,11 @@
int yylex(YYSTYPE *lvalp, Context *context)
{
+ pp::Token *token = context->token;
+ context->lexer->lex(token);
+
int type = 0;
- pp::Token *token = context->token;
switch (token->type)
{
case pp::Token::CONST_INT: {
@@ -1868,11 +1868,6 @@
break;
}
case pp::Token::IDENTIFIER:
- if (!context->isIgnoringErrors())
- {
- context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
- }
*lvalp = static_cast<YYSTYPE>(-1);
type = TOK_IDENTIFIER;
break;
@@ -1921,10 +1916,6 @@
break;
}
- // Advance to the next token if the current one is valid.
- if (type != 0)
- context->lexer->lex(token);
-
return type;
}