Skip to content

Commit 6833b1b

Browse files
committed
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.
1 parent 4aa731d commit 6833b1b

File tree

4 files changed

+86
-66
lines changed

4 files changed

+86
-66
lines changed

TODO

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ Discourage the use of YYDEBUG in C++ (see thread with Jot). Stop supporting
2828

2929
Add value_type as a synonym for semantic_type.
3030

31-
** Asymmetries
32-
Why are yylval and yylloc treated differently?
33-
34-
yystack.yyglrShift (create_state_set_index(0), 0, 0, yylval, &yylloc);
35-
3631
** yyerrok in Java
3732
And add tests in calc.at, to prepare work for D.
3833

data/skeletons/glr2.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ const std::ptrdiff_t strong_index_alias<T>::INVALID_INDEX =
332332
/// YYSYMBOL. No bounds checking.
333333
static std::string symbol_name (symbol_kind_type yysymbol);]])[
334334

335+
]b4_token_constructor_define[
335336
# if ]b4_api_PREFIX[DEBUG
336337
public:
337338
/// \brief Report a symbol value on the debug stream.
@@ -385,6 +386,8 @@ const std::ptrdiff_t strong_index_alias<T>::INVALID_INDEX =
385386
]b4_parse_param_vars[
386387
};
387388

389+
]b4_token_ctor_if([b4_yytranslate_define([$1])[
390+
]b4_public_types_define([$1])])[
388391
]b4_namespace_close[
389392

390393
]b4_percent_code_get([[provides]])[
@@ -2911,7 +2914,18 @@ yygetToken (]b4_namespace_ref[::]b4_parser_class[& yyparser, glr_stack& yystack]
29112914
try
29122915
{
29132916
#endif // YY_EXCEPTIONS
2914-
yychar = ]b4_lex[;
2917+
{]b4_token_ctor_if([[
2918+
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_type symbol_type;
2919+
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind symbol_kind;
2920+
symbol_type yylookahead = ]b4_lex[;
2921+
yystack.yytoken = yylookahead.kind ();]b4_variant_if([[
2922+
]b4_symbol_variant([yystack.yytoken],
2923+
[yystack.yylval], [move], [yylookahead.value])], [[
2924+
yystack.yylval = yylookahead.value;]])[]b4_locations_if([
2925+
yystack.yylloc = yylookahead.location;
2926+
yylookahead.kind_ = symbol_kind::S_YYEMPTY;])[]], [[
2927+
yychar = ]b4_lex[;]])[
2928+
}
29152929
#if YY_EXCEPTIONS
29162930
}
29172931
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]
29202934
yystack.yylloc = yyexc.location;])[
29212935
yyparser.error (]b4_locations_if([yystack.yylloc, ])[yyexc.what ());
29222936
// Map errors caught in the scanner to the error token, so that error
2923-
// handling is started.
2924-
yychar = ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(error, id)[;
2937+
// handling is started.]b4_token_ctor_if([[
2938+
yystack.yytoken = ]b4_namespace_ref[::]b4_parser_class[::]b4_symbol(error, kind)[;]], [[
2939+
yychar = ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(error, id)[;]])[
29252940
}
2926-
#endif // YY_EXCEPTIONS
2941+
#endif // YY_EXCEPTIONS]b4_token_ctor_if([], [[
29272942
yystack.yytoken
2928-
= ]b4_namespace_ref[::]b4_parser_class[::yytranslate_ (yychar);
2943+
= ]b4_namespace_ref[::]b4_parser_class[::yytranslate_ (yychar);]])[
29292944
}
29302945
if (yystack.yytoken == ]b4_namespace_ref[::]b4_parser_class[::]b4_symbol(eof, kind)[)
29312946
YYCDEBUG << "Now at end of input.\n";

examples/c++/glr/c++-types.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ run 0 "\
4747
5.0-13: <OR>(<init-declare>(T, y, +(z, q)), =(<cast>(y, T), +(z, q)))
4848
7.0-15: <error>
4949
9.0-5: +(z, q)
50-
err: 7.5: syntax error, unexpected identifier, expecting '=' or '+' or ')'"
50+
err: 7.5: syntax error, unexpected identifier, expecting = or + or )"

examples/c++/glr/c++-types.yy

Lines changed: 65 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
%glr-parser
2323
%skeleton "glr2.cc"
2424
%define parse.assert
25+
%define api.token.constructor
2526
%header
2627
%locations
2728
%debug
@@ -46,8 +47,8 @@
4647
static Node
4748
stmtMerge (const Node& x0, const Node& x1);
4849

49-
static int
50-
yylex (yy::parser::value_type* val, yy::parser::location_type* loc);
50+
static yy::parser::symbol_type
51+
yylex ();
5152
}
5253

5354
%expect-rr 1
@@ -56,42 +57,48 @@
5657
%printer { yyo << $$; } <Node>
5758

5859
%token
59-
TYPENAME "typename"
60-
ID "identifier"
60+
TYPENAME "typename"
61+
ID "identifier"
62+
SEMICOLON ";"
63+
EQUAL "="
64+
PLUS "+"
65+
LPAREN "("
66+
RPAREN ")"
6167

62-
%right '='
63-
%left '+'
68+
%right "="
69+
%left "+"
6470

6571
%%
6672

6773
prog : %empty
6874
| prog stmt { std::cout << @2 << ": " << $2 << '\n'; }
6975
;
7076

71-
stmt : expr ';' %merge <stmtMerge> { $$ = $1; }
77+
stmt : expr ";" %merge <stmtMerge> { $$ = $1; }
7278
| decl %merge <stmtMerge>
73-
| error ';' { $$ = Nterm ("<error>"); }
79+
| error ";" { $$ = Nterm ("<error>"); }
7480
;
7581

7682
expr : ID
77-
| TYPENAME '(' expr ')' { $$ = Nterm ("<cast>", $3, $1); }
78-
| expr '+' expr { $$ = Nterm ("+", $1, $3); }
79-
| expr '=' expr { $$ = Nterm ("=", $1, $3); }
83+
| TYPENAME "(" expr ")" { $$ = Nterm ("<cast>", $3, $1); }
84+
| expr "+" expr { $$ = Nterm ("+", $1, $3); }
85+
| expr "=" expr { $$ = Nterm ("=", $1, $3); }
8086
;
8187

82-
decl : TYPENAME declarator ';'
88+
decl : TYPENAME declarator ";"
8389
{ $$ = Nterm ("<declare>", $1, $2); }
84-
| TYPENAME declarator '=' expr ';'
90+
| TYPENAME declarator "=" expr ";"
8591
{ $$ = Nterm ("<init-declare>", $1, $2, $4); }
8692
;
8793

8894
declarator
8995
: ID
90-
| '(' declarator ')' { $$ = $2; }
96+
| "(" declarator ")" { $$ = $2; }
9197
;
9298

9399
%%
94100
std::istream* input = nullptr;
101+
yy::parser::location_type loc;
95102

96103
// An error reporting function.
97104
void
@@ -100,61 +107,63 @@ yy::parser::error (const location_type& l, const std::string& m)
100107
std::cerr << l << ": " << m << '\n';
101108
}
102109

103-
static int
104-
yylex (yy::parser::value_type* lvalp, yy::parser::location_type* llocp)
110+
static yy::parser::symbol_type
111+
yylex ()
105112
{
106-
static int lineNum = 1;
107-
static int colNum = 0;
108-
109113
while (true)
110114
{
115+
loc.step ();
116+
loc += 1;
111117
assert (!input->eof ());
112118
switch (int c = input->get ())
113119
{
114120
case EOF:
115-
return 0;
121+
return yy::parser::make_YYEOF (loc);
116122
case '\t':
117-
colNum = (colNum + 7) & ~7;
123+
loc.end.column = (loc.end.column + 7) & ~7;
124+
loc.step ();
118125
break;
119126
case ' ': case '\f':
120-
colNum += 1;
127+
loc.step ();
121128
break;
122129
case '\n':
123-
lineNum += 1;
124-
colNum = 0;
130+
loc.lines (1);
131+
loc.end.column = 0;
132+
loc.step ();
125133
break;
134+
case '+':
135+
return yy::parser::make_PLUS (loc);
136+
case '=':
137+
return yy::parser::make_EQUAL (loc);
138+
case '(':
139+
return yy::parser::make_LPAREN (loc);
140+
case ')':
141+
return yy::parser::make_RPAREN (loc);
142+
case ';':
143+
return yy::parser::make_SEMICOLON (loc);
126144
default:
127-
{
128-
llocp->begin.line = llocp->end.line = lineNum;
129-
llocp->begin.column = colNum;
130-
int tok;
131-
if (isalpha (c))
132-
{
133-
std::string form;
134-
do
135-
{
136-
form += static_cast<char> (c);
137-
colNum += 1;
138-
c = input->get ();
139-
}
140-
while (isalnum (c) || c == '_');
141-
142-
input->unget ();
143-
tok
144-
= isupper (static_cast <unsigned char> (form[0]))
145-
? yy::parser::token::TYPENAME
146-
: yy::parser::token::ID;
147-
lvalp->emplace<Node> (Term (form));
148-
}
149-
else
150-
{
151-
colNum += 1;
152-
tok = c;
153-
lvalp = nullptr;
154-
}
155-
llocp->end.column = colNum;
156-
return tok;
157-
}
145+
if (isalpha (c))
146+
{
147+
std::string form;
148+
do
149+
{
150+
form += static_cast<char> (c);
151+
loc += 1;
152+
c = input->get ();
153+
}
154+
while (isalnum (c) || c == '_');
155+
input->unget ();
156+
loc -= 1;
157+
if (isupper (static_cast <unsigned char> (form[0])))
158+
return yy::parser::make_TYPENAME (Term (form), loc);
159+
else
160+
return yy::parser::make_ID (Term (form), loc);
161+
}
162+
else
163+
{
164+
auto msg = "invalid character: " + std::string(1, static_cast<char> (c));
165+
throw yy::parser::syntax_error (loc, msg);
166+
}
158167
}
159168
}
160169
}
@@ -173,6 +182,7 @@ process (yy::parser& parse, const std::string& file)
173182
input = &std::cin;
174183
else
175184
input = new std::ifstream (file.c_str ());
185+
loc.initialize (nullptr, 1, 0);
176186
int status = parse ();
177187
if (!is_stdin)
178188
delete input;

0 commit comments

Comments
 (0)