mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-20 01:33:03 +00:00
glr2.cc: add support for api.token.constructor
* data/skeletons/glr2.cc: Add support for api.token.constructor. * examples/c++/glr/c++-types.yy: Use it. * examples/c++/glr/c++-types.test: Adjust expectations for error messages.
This commit is contained in:
5
TODO
5
TODO
@@ -28,11 +28,6 @@ Discourage the use of YYDEBUG in C++ (see thread with Jot). Stop supporting
|
|||||||
|
|
||||||
Add value_type as a synonym for semantic_type.
|
Add value_type as a synonym for semantic_type.
|
||||||
|
|
||||||
** Asymmetries
|
|
||||||
Why are yylval and yylloc treated differently?
|
|
||||||
|
|
||||||
yystack.yyglrShift (create_state_set_index(0), 0, 0, yylval, &yylloc);
|
|
||||||
|
|
||||||
** yyerrok in Java
|
** yyerrok in Java
|
||||||
And add tests in calc.at, to prepare work for D.
|
And add tests in calc.at, to prepare work for D.
|
||||||
|
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ const std::ptrdiff_t strong_index_alias<T>::INVALID_INDEX =
|
|||||||
/// YYSYMBOL. No bounds checking.
|
/// YYSYMBOL. No bounds checking.
|
||||||
static std::string symbol_name (symbol_kind_type yysymbol);]])[
|
static std::string symbol_name (symbol_kind_type yysymbol);]])[
|
||||||
|
|
||||||
|
]b4_token_constructor_define[
|
||||||
# if ]b4_api_PREFIX[DEBUG
|
# if ]b4_api_PREFIX[DEBUG
|
||||||
public:
|
public:
|
||||||
/// \brief Report a symbol value on the debug stream.
|
/// \brief Report a symbol value on the debug stream.
|
||||||
@@ -385,6 +386,8 @@ const std::ptrdiff_t strong_index_alias<T>::INVALID_INDEX =
|
|||||||
]b4_parse_param_vars[
|
]b4_parse_param_vars[
|
||||||
};
|
};
|
||||||
|
|
||||||
|
]b4_token_ctor_if([b4_yytranslate_define([$1])[
|
||||||
|
]b4_public_types_define([$1])])[
|
||||||
]b4_namespace_close[
|
]b4_namespace_close[
|
||||||
|
|
||||||
]b4_percent_code_get([[provides]])[
|
]b4_percent_code_get([[provides]])[
|
||||||
@@ -2911,7 +2914,18 @@ yygetToken (]b4_namespace_ref[::]b4_parser_class[& yyparser, glr_stack& yystack]
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif // YY_EXCEPTIONS
|
#endif // YY_EXCEPTIONS
|
||||||
yychar = ]b4_lex[;
|
{]b4_token_ctor_if([[
|
||||||
|
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_type symbol_type;
|
||||||
|
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind;
|
||||||
|
symbol_type yylookahead = ]b4_lex[;
|
||||||
|
yystack.yytoken = yylookahead.kind ();]b4_variant_if([[
|
||||||
|
]b4_symbol_variant([yystack.yytoken],
|
||||||
|
[yystack.yylval], [move], [yylookahead.value])], [[
|
||||||
|
yystack.yylval = yylookahead.value;]])[]b4_locations_if([
|
||||||
|
yystack.yylloc = yylookahead.location;
|
||||||
|
yylookahead.kind_ = symbol_kind::S_YYEMPTY;])[]], [[
|
||||||
|
yychar = ]b4_lex[;]])[
|
||||||
|
}
|
||||||
#if YY_EXCEPTIONS
|
#if YY_EXCEPTIONS
|
||||||
}
|
}
|
||||||
catch (const ]b4_namespace_ref[::]b4_parser_class[::syntax_error& yyexc)
|
catch (const ]b4_namespace_ref[::]b4_parser_class[::syntax_error& yyexc)
|
||||||
@@ -2920,12 +2934,13 @@ yygetToken (]b4_namespace_ref[::]b4_parser_class[& yyparser, glr_stack& yystack]
|
|||||||
yystack.yylloc = yyexc.location;])[
|
yystack.yylloc = yyexc.location;])[
|
||||||
yyparser.error (]b4_locations_if([yystack.yylloc, ])[yyexc.what ());
|
yyparser.error (]b4_locations_if([yystack.yylloc, ])[yyexc.what ());
|
||||||
// Map errors caught in the scanner to the error token, so that error
|
// Map errors caught in the scanner to the error token, so that error
|
||||||
// handling is started.
|
// handling is started.]b4_token_ctor_if([[
|
||||||
yychar = ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(error, id)[;
|
yystack.yytoken = ]b4_namespace_ref[::]b4_parser_class[::]b4_symbol(error, kind)[;]], [[
|
||||||
|
yychar = ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(error, id)[;]])[
|
||||||
}
|
}
|
||||||
#endif // YY_EXCEPTIONS
|
#endif // YY_EXCEPTIONS]b4_token_ctor_if([], [[
|
||||||
yystack.yytoken
|
yystack.yytoken
|
||||||
= ]b4_namespace_ref[::]b4_parser_class[::yytranslate_ (yychar);
|
= ]b4_namespace_ref[::]b4_parser_class[::yytranslate_ (yychar);]])[
|
||||||
}
|
}
|
||||||
if (yystack.yytoken == ]b4_namespace_ref[::]b4_parser_class[::]b4_symbol(eof, kind)[)
|
if (yystack.yytoken == ]b4_namespace_ref[::]b4_parser_class[::]b4_symbol(eof, kind)[)
|
||||||
YYCDEBUG << "Now at end of input.\n";
|
YYCDEBUG << "Now at end of input.\n";
|
||||||
|
|||||||
@@ -47,4 +47,4 @@ run 0 "\
|
|||||||
5.0-13: <OR>(<init-declare>(T, y, +(z, q)), =(<cast>(y, T), +(z, q)))
|
5.0-13: <OR>(<init-declare>(T, y, +(z, q)), =(<cast>(y, T), +(z, q)))
|
||||||
7.0-15: <error>
|
7.0-15: <error>
|
||||||
9.0-5: +(z, q)
|
9.0-5: +(z, q)
|
||||||
err: 7.5: syntax error, unexpected identifier, expecting '=' or '+' or ')'"
|
err: 7.5: syntax error, unexpected identifier, expecting = or + or )"
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
%glr-parser
|
%glr-parser
|
||||||
%skeleton "glr2.cc"
|
%skeleton "glr2.cc"
|
||||||
%define parse.assert
|
%define parse.assert
|
||||||
|
%define api.token.constructor
|
||||||
%header
|
%header
|
||||||
%locations
|
%locations
|
||||||
%debug
|
%debug
|
||||||
@@ -46,8 +47,8 @@
|
|||||||
static Node
|
static Node
|
||||||
stmtMerge (const Node& x0, const Node& x1);
|
stmtMerge (const Node& x0, const Node& x1);
|
||||||
|
|
||||||
static int
|
static yy::parser::symbol_type
|
||||||
yylex (yy::parser::value_type* val, yy::parser::location_type* loc);
|
yylex ();
|
||||||
}
|
}
|
||||||
|
|
||||||
%expect-rr 1
|
%expect-rr 1
|
||||||
@@ -56,11 +57,16 @@
|
|||||||
%printer { yyo << $$; } <Node>
|
%printer { yyo << $$; } <Node>
|
||||||
|
|
||||||
%token
|
%token
|
||||||
TYPENAME "typename"
|
TYPENAME "typename"
|
||||||
ID "identifier"
|
ID "identifier"
|
||||||
|
SEMICOLON ";"
|
||||||
|
EQUAL "="
|
||||||
|
PLUS "+"
|
||||||
|
LPAREN "("
|
||||||
|
RPAREN ")"
|
||||||
|
|
||||||
%right '='
|
%right "="
|
||||||
%left '+'
|
%left "+"
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@@ -68,30 +74,31 @@ prog : %empty
|
|||||||
| prog stmt { std::cout << @2 << ": " << $2 << '\n'; }
|
| prog stmt { std::cout << @2 << ": " << $2 << '\n'; }
|
||||||
;
|
;
|
||||||
|
|
||||||
stmt : expr ';' %merge <stmtMerge> { $$ = $1; }
|
stmt : expr ";" %merge <stmtMerge> { $$ = $1; }
|
||||||
| decl %merge <stmtMerge>
|
| decl %merge <stmtMerge>
|
||||||
| error ';' { $$ = Nterm ("<error>"); }
|
| error ";" { $$ = Nterm ("<error>"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
expr : ID
|
expr : ID
|
||||||
| TYPENAME '(' expr ')' { $$ = Nterm ("<cast>", $3, $1); }
|
| TYPENAME "(" expr ")" { $$ = Nterm ("<cast>", $3, $1); }
|
||||||
| expr '+' expr { $$ = Nterm ("+", $1, $3); }
|
| expr "+" expr { $$ = Nterm ("+", $1, $3); }
|
||||||
| expr '=' expr { $$ = Nterm ("=", $1, $3); }
|
| expr "=" expr { $$ = Nterm ("=", $1, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
decl : TYPENAME declarator ';'
|
decl : TYPENAME declarator ";"
|
||||||
{ $$ = Nterm ("<declare>", $1, $2); }
|
{ $$ = Nterm ("<declare>", $1, $2); }
|
||||||
| TYPENAME declarator '=' expr ';'
|
| TYPENAME declarator "=" expr ";"
|
||||||
{ $$ = Nterm ("<init-declare>", $1, $2, $4); }
|
{ $$ = Nterm ("<init-declare>", $1, $2, $4); }
|
||||||
;
|
;
|
||||||
|
|
||||||
declarator
|
declarator
|
||||||
: ID
|
: ID
|
||||||
| '(' declarator ')' { $$ = $2; }
|
| "(" declarator ")" { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
std::istream* input = nullptr;
|
std::istream* input = nullptr;
|
||||||
|
yy::parser::location_type loc;
|
||||||
|
|
||||||
// An error reporting function.
|
// An error reporting function.
|
||||||
void
|
void
|
||||||
@@ -100,61 +107,63 @@ yy::parser::error (const location_type& l, const std::string& m)
|
|||||||
std::cerr << l << ": " << m << '\n';
|
std::cerr << l << ": " << m << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static yy::parser::symbol_type
|
||||||
yylex (yy::parser::value_type* lvalp, yy::parser::location_type* llocp)
|
yylex ()
|
||||||
{
|
{
|
||||||
static int lineNum = 1;
|
|
||||||
static int colNum = 0;
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
loc.step ();
|
||||||
|
loc += 1;
|
||||||
assert (!input->eof ());
|
assert (!input->eof ());
|
||||||
switch (int c = input->get ())
|
switch (int c = input->get ())
|
||||||
{
|
{
|
||||||
case EOF:
|
case EOF:
|
||||||
return 0;
|
return yy::parser::make_YYEOF (loc);
|
||||||
case '\t':
|
case '\t':
|
||||||
colNum = (colNum + 7) & ~7;
|
loc.end.column = (loc.end.column + 7) & ~7;
|
||||||
|
loc.step ();
|
||||||
break;
|
break;
|
||||||
case ' ': case '\f':
|
case ' ': case '\f':
|
||||||
colNum += 1;
|
loc.step ();
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
lineNum += 1;
|
loc.lines (1);
|
||||||
colNum = 0;
|
loc.end.column = 0;
|
||||||
|
loc.step ();
|
||||||
break;
|
break;
|
||||||
|
case '+':
|
||||||
|
return yy::parser::make_PLUS (loc);
|
||||||
|
case '=':
|
||||||
|
return yy::parser::make_EQUAL (loc);
|
||||||
|
case '(':
|
||||||
|
return yy::parser::make_LPAREN (loc);
|
||||||
|
case ')':
|
||||||
|
return yy::parser::make_RPAREN (loc);
|
||||||
|
case ';':
|
||||||
|
return yy::parser::make_SEMICOLON (loc);
|
||||||
default:
|
default:
|
||||||
{
|
if (isalpha (c))
|
||||||
llocp->begin.line = llocp->end.line = lineNum;
|
{
|
||||||
llocp->begin.column = colNum;
|
std::string form;
|
||||||
int tok;
|
do
|
||||||
if (isalpha (c))
|
{
|
||||||
{
|
form += static_cast<char> (c);
|
||||||
std::string form;
|
loc += 1;
|
||||||
do
|
c = input->get ();
|
||||||
{
|
}
|
||||||
form += static_cast<char> (c);
|
while (isalnum (c) || c == '_');
|
||||||
colNum += 1;
|
input->unget ();
|
||||||
c = input->get ();
|
loc -= 1;
|
||||||
}
|
if (isupper (static_cast <unsigned char> (form[0])))
|
||||||
while (isalnum (c) || c == '_');
|
return yy::parser::make_TYPENAME (Term (form), loc);
|
||||||
|
else
|
||||||
input->unget ();
|
return yy::parser::make_ID (Term (form), loc);
|
||||||
tok
|
}
|
||||||
= isupper (static_cast <unsigned char> (form[0]))
|
else
|
||||||
? yy::parser::token::TYPENAME
|
{
|
||||||
: yy::parser::token::ID;
|
auto msg = "invalid character: " + std::string(1, static_cast<char> (c));
|
||||||
lvalp->emplace<Node> (Term (form));
|
throw yy::parser::syntax_error (loc, msg);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
colNum += 1;
|
|
||||||
tok = c;
|
|
||||||
lvalp = nullptr;
|
|
||||||
}
|
|
||||||
llocp->end.column = colNum;
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,6 +182,7 @@ process (yy::parser& parse, const std::string& file)
|
|||||||
input = &std::cin;
|
input = &std::cin;
|
||||||
else
|
else
|
||||||
input = new std::ifstream (file.c_str ());
|
input = new std::ifstream (file.c_str ());
|
||||||
|
loc.initialize (nullptr, 1, 0);
|
||||||
int status = parse ();
|
int status = parse ();
|
||||||
if (!is_stdin)
|
if (!is_stdin)
|
||||||
delete input;
|
delete input;
|
||||||
|
|||||||
Reference in New Issue
Block a user