glr2.cc: example: use streams and accept arguments

From a debugger, it is easier to pass a file name than working on
stdin.

* examples/c++/glr/c++-types.yy: Reduce scopes.
Avoid YYSTYPE/YYLTYPE: use the C++ types.
(input, process): New.
(main): Use them.
This commit is contained in:
Akim Demaille
2020-12-19 07:09:55 +01:00
parent 3f473dd2d7
commit 7292ed6e64

View File

@@ -36,20 +36,20 @@
%code %code
{ {
#include <cassert>
#include <cctype>
#include <fstream>
#include <cstring>
#include <cassert> #if __cplusplus < 201103L
#include <cctype> # define nullptr 0
#include <cstdio> #endif
#include <cstdlib>
#include <cstring>
#if __cplusplus < 201103L static yy::parser::semantic_type
# define nullptr 0 stmtMerge (const yy::parser::semantic_type& x0, const yy::parser::semantic_type& x1);
#endif
static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1); static int
yylex (yy::parser::semantic_type* val, yy::parser::location_type* loc);
static int yylex (YYSTYPE *lvalp, YYLTYPE *llocp);
} }
%expect-rr 1 %expect-rr 1
@@ -95,22 +95,25 @@ declarator
; ;
%% %%
std::istream* input = nullptr;
/* A C error reporting function. */ /* A C error reporting function. */
void yy::parser::error (const location_type& l, const std::string& m) void
yy::parser::error (const location_type& l, const std::string& m)
{ {
std::cerr << l << ": " << m << '\n'; std::cerr << l << ": " << m << '\n';
} }
int yylex (YYSTYPE *lvalp, YYLTYPE *llocp) static int
yylex (yy::parser::semantic_type* lvalp, yy::parser::location_type* llocp)
{ {
static int lineNum = 1; static int lineNum = 1;
static int colNum = 0; static int colNum = 0;
while (1) while (1)
{ {
int c; assert (!input->eof ());
assert (!feof (stdin)); int c = input->get ();
c = getchar ();
switch (c) switch (c)
{ {
case EOF: case EOF:
@@ -127,9 +130,9 @@ int yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
break; break;
default: default:
{ {
int tok;
llocp->begin.line = llocp->end.line = lineNum; llocp->begin.line = llocp->end.line = lineNum;
llocp->begin.column = colNum; llocp->begin.column = colNum;
int tok;
if (isalpha (c)) if (isalpha (c))
{ {
std::string form; std::string form;
@@ -137,11 +140,11 @@ int yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
{ {
form += static_cast<char> (c); form += static_cast<char> (c);
colNum += 1; colNum += 1;
c = getchar (); c = input->get ();
} }
while (isalnum (c) || c == '_'); while (isalnum (c) || c == '_');
ungetc (c, stdin); input->unget ();
tok tok
= isupper (static_cast <unsigned char> (form[0])) = isupper (static_cast <unsigned char> (form[0]))
? yy::parser::token::TYPENAME ? yy::parser::token::TYPENAME
@@ -161,18 +164,52 @@ int yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
} }
} }
static YYSTYPE static yy::parser::semantic_type
stmtMerge (YYSTYPE x0, YYSTYPE x1) stmtMerge (const yy::parser::semantic_type& x0, const yy::parser::semantic_type& x1)
{ {
return new Nterm ("<OR>", x0, x1); return new Nterm ("<OR>", x0, x1);
} }
int
process (yy::parser& parse, const std::string& file)
{
bool is_stdin = file == "-" || file.empty ();
if (is_stdin)
input = &std::cin;
else
input = new std::ifstream (file.c_str ());
int status = parse ();
if (!is_stdin)
delete input;
return status;
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
// Enable parse traces on option -p. yy::parser parse;
if (1 < argc && strcmp (argv[1], "-p") == 0)
yydebug = 1; if (getenv ("YYDEBUG"))
yy::parser parser; parse.set_debug_level (1);
return !!parser.parse ();
bool ran = false;
for (int i = 1; i < argc; ++i)
// Enable parse traces on option -p.
if (strcmp (argv[1], "-p") == 0)
parse.set_debug_level (1);
else
{
int status = process (parse, argv[1]);
ran = true;
if (!status)
return status;
}
if (!ran)
{
int status = process (parse, "");
if (!status)
return status;
}
return 0;
} }