Commit 3187a38e by Olli Etuaho

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/300962Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Tryjob-Request: Olli Etuaho <oetuaho@nvidia.com>
parent 3edfe034
......@@ -893,7 +893,6 @@ int DirectiveParser::parseExpressionIf(Token *token)
ExpressionParser expressionParser(&macroExpander, mDiagnostics);
int expression = 0;
macroExpander.lex(token);
expressionParser.parse(token, &expression);
// Check if there are tokens after #if expression.
......
......@@ -110,6 +110,7 @@ typedef __int64 YYSTYPE;
#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 @@ static const yytype_uint8 yytranslate[] =
/* 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 @@ yyreduce:
{
*(context->result) = static_cast<int>((yyvsp[0]));
YYACCEPT;
}
break;
......@@ -1339,8 +1341,12 @@ yyreduce:
{
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 @@ yyreduce:
{
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 @@ yyreduce:
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 @@ yyreduce:
{
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 @@ yyreduce:
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 @@ yyreturn:
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 @@ int yylex(YYSTYPE *lvalp, Context *context)
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 @@ int yylex(YYSTYPE *lvalp, Context *context)
break;
}
// Advance to the next token if the current one is valid.
if (type != 0)
context->lexer->lex(token);
return type;
}
......
......@@ -52,6 +52,7 @@ typedef __int64 YYSTYPE;
#include <stdint.h>
typedef intmax_t YYSTYPE;
#endif // _MSC_VER
#define YYENABLE_NLS 0
#define YYLTYPE_IS_TRIVIAL 1
#define YYSTYPE_IS_TRIVIAL 1
......@@ -104,6 +105,7 @@ static void yyerror(Context* context, const char* reason);
input
: expression {
*(context->result) = static_cast<int>($1);
YYACCEPT;
}
;
......@@ -112,8 +114,12 @@ expression
| TOK_IDENTIFIER {
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);
}
$$ = $1;
}
| expression TOK_OP_OR {
if ($1 != 0)
......@@ -199,11 +205,7 @@ expression
| expression '%' expression {
if ($3 == 0)
{
if (context->isIgnoringErrors())
{
$$ = static_cast<YYSTYPE>(0);
}
else
if (!context->isIgnoringErrors())
{
std::ostringstream stream;
stream << $1 << " % " << $3;
......@@ -211,8 +213,8 @@ expression
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location,
text.c_str());
YYABORT;
}
$$ = static_cast<YYSTYPE>(0);
}
else
{
......@@ -222,11 +224,7 @@ expression
| expression '/' expression {
if ($3 == 0)
{
if (context->isIgnoringErrors())
{
$$ = static_cast<YYSTYPE>(0);
}
else
if (!context->isIgnoringErrors())
{
std::ostringstream stream;
stream << $1 << " / " << $3;
......@@ -234,8 +232,8 @@ expression
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location,
text.c_str());
YYABORT;
}
$$ = static_cast<YYSTYPE>(0);
}
else
{
......@@ -266,9 +264,11 @@ expression
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: {
......@@ -283,11 +283,6 @@ int yylex(YYSTYPE *lvalp, Context *context)
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;
......@@ -336,10 +331,6 @@ int yylex(YYSTYPE *lvalp, Context *context)
break;
}
// Advance to the next token if the current one is valid.
if (type != 0)
context->lexer->lex(token);
return type;
}
......
......@@ -838,8 +838,8 @@ TEST_F(IfTest, ExtraIntExpression)
"#endif\n";
ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_EXPRESSION,
pp::SourceLocation(0, 1), "syntax error"));
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
pp::SourceLocation(0, 1), "1"));
pp::Token token;
mPreprocessor.lex(&token);
......@@ -855,8 +855,8 @@ TEST_F(IfTest, ExtraIdentifierExpression)
"#endif\n";
ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_EXPRESSION,
pp::SourceLocation(0, 2), "syntax error"));
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
pp::SourceLocation(0, 2), "1"));
pp::Token token;
mPreprocessor.lex(&token);
......
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