mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-22 02:33:03 +00:00
examples: lexcalc: demonstrate location tracking
The bistromathic example should not use Flex, it makes it too complex. But it was the only example to show location tracking with Flex. * examples/c/lexcalc/lexcalc.test, examples/c/lexcalc/parse.y, * examples/c/lexcalc/scan.l: Demonstrate location tracking as is done in bistromathic.
This commit is contained in:
3
NEWS
3
NEWS
@@ -101,6 +101,9 @@ GNU Bison NEWS
|
|||||||
There are now two examples in examples/java: a very simple calculator, and
|
There are now two examples in examples/java: a very simple calculator, and
|
||||||
one that tracks locations to provide acurate error messages.
|
one that tracks locations to provide acurate error messages.
|
||||||
|
|
||||||
|
The lexcalc example (a simple example in C based on Flex and Bison) now
|
||||||
|
also demonstrates location tracking.
|
||||||
|
|
||||||
A new C example, bistromathic, is a fully featured calculator using many
|
A new C example, bistromathic, is a fully featured calculator using many
|
||||||
Bison features: pure interface, location tracking, internationalized
|
Bison features: pure interface, location tracking, internationalized
|
||||||
custom error messages, lookahead-correction, rich debug traces, etc.
|
custom error messages, lookahead-correction, rich debug traces, etc.
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ Extracted from the documentation: "Multi-Function Calculator: mfcalc".
|
|||||||
https://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html
|
https://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html
|
||||||
|
|
||||||
## lexcalc - calculator with Flex and Bison
|
## lexcalc - calculator with Flex and Bison
|
||||||
The calculator, redux. This time using a scanner generated by Flex.
|
The calculator with precedence directives and location tracking. It uses
|
||||||
|
Flex to generate the scanner.
|
||||||
|
|
||||||
## reccalc - recursive calculator with Flex and Bison
|
## reccalc - recursive calculator with Flex and Bison
|
||||||
The example builds on top of the previous one to provide a reentrant parser.
|
The example builds on top of the previous one to provide a reentrant parser.
|
||||||
@@ -53,7 +54,7 @@ This example demonstrates the best practices when using Bison.
|
|||||||
- Its interface is pure.
|
- Its interface is pure.
|
||||||
- It uses a custom syntax error with location tracking, lookahead correction
|
- It uses a custom syntax error with location tracking, lookahead correction
|
||||||
and token internationalization.
|
and token internationalization.
|
||||||
- It enables debug trace support with formatting of semantic values.
|
- It supports debug traces with semantic values.
|
||||||
- It uses named references instead of the traditional $1, $2, etc.
|
- It uses named references instead of the traditional $1, $2, etc.
|
||||||
|
|
||||||
It also uses Flex to generate the scanner.
|
It also uses Flex to generate the scanner.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ This example demonstrates the best practices when using Bison.
|
|||||||
- Its interface is pure.
|
- Its interface is pure.
|
||||||
- It uses a custom syntax error with location tracking, lookahead correction
|
- It uses a custom syntax error with location tracking, lookahead correction
|
||||||
and token internationalization.
|
and token internationalization.
|
||||||
- It enables debug trace support with formatting of semantic values.
|
- It supports debug traces with semantic values.
|
||||||
- It uses named references instead of the traditional $1, $2, etc.
|
- It uses named references instead of the traditional $1, $2, etc.
|
||||||
|
|
||||||
It also uses Flex to generate the scanner.
|
It also uses Flex to generate the scanner.
|
||||||
|
|||||||
@@ -209,10 +209,10 @@ yyreport_syntax_error (const yyparse_context_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by yyparse on error.
|
// Called by yyparse on error.
|
||||||
void yyerror (YYLTYPE *loc, char const *s)
|
void yyerror (YYLTYPE *loc, char const *msg)
|
||||||
{
|
{
|
||||||
YY_LOCATION_PRINT (stderr, *loc);
|
YY_LOCATION_PRINT (stderr, *loc);
|
||||||
fprintf (stderr, ": %s\n", s);
|
fprintf (stderr, ": %s\n", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char const* argv[])
|
int main (int argc, char const* argv[])
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
This directory contains lexcalc, the traditional example of using Flex and
|
This directory contains lexcalc, the traditional example of using Flex and
|
||||||
Bison to build a simple calculator.
|
Bison to build a simple calculator.
|
||||||
|
|
||||||
|
It features detailed syntax errors with locations.
|
||||||
|
|
||||||
<!---
|
<!---
|
||||||
Local Variables:
|
Local Variables:
|
||||||
fill-column: 76
|
fill-column: 76
|
||||||
|
|||||||
@@ -29,4 +29,9 @@ run -noerr 0 9 -p
|
|||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
(1+2) *
|
(1+2) *
|
||||||
EOF
|
EOF
|
||||||
run 1 'err: syntax error, unexpected end-of-line, expecting ( or number'
|
run 1 'err: 1.8-2.0: syntax error, unexpected end-of-line, expecting ( or number'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
1 / (2 - 2)
|
||||||
|
EOF
|
||||||
|
run 1 'err: 1.1-11: error: division by zero"
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
{
|
{
|
||||||
// Tell Flex the expected prototype of yylex.
|
// Tell Flex the expected prototype of yylex.
|
||||||
#define YY_DECL \
|
#define YY_DECL \
|
||||||
enum yytokentype yylex (YYSTYPE* yylval, int *nerrs)
|
enum yytokentype yylex (YYSTYPE* yylval, YYLTYPE *yylloc, int *nerrs)
|
||||||
YY_DECL;
|
YY_DECL;
|
||||||
|
|
||||||
void yyerror (int *nerrs, const char *msg);
|
void yyerror (YYLTYPE *loc, int *nerrs, const char *msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emitted on top of the implementation file.
|
// Emitted on top of the implementation file.
|
||||||
@@ -33,6 +33,9 @@
|
|||||||
// Generate detailed error messages.
|
// Generate detailed error messages.
|
||||||
%define parse.error detailed
|
%define parse.error detailed
|
||||||
|
|
||||||
|
// with locations.
|
||||||
|
%locations
|
||||||
|
|
||||||
// Enable debug traces (see yydebug in main).
|
// Enable debug traces (see yydebug in main).
|
||||||
%define parse.trace
|
%define parse.trace
|
||||||
|
|
||||||
@@ -78,7 +81,7 @@ exp:
|
|||||||
{
|
{
|
||||||
if ($3 == 0)
|
if ($3 == 0)
|
||||||
{
|
{
|
||||||
yyerror (nerrs, "invalid division by zero");
|
yyerror (&@$, nerrs, "error: division by zero");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -90,9 +93,10 @@ exp:
|
|||||||
%%
|
%%
|
||||||
// Epilogue (C code).
|
// Epilogue (C code).
|
||||||
|
|
||||||
void yyerror (int *nerrs, const char *msg)
|
void yyerror (YYLTYPE *loc, int *nerrs, const char *msg)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s\n", msg);
|
YY_LOCATION_PRINT (stderr, *loc);
|
||||||
|
fprintf (stderr, ": %s\n", msg);
|
||||||
++*nerrs;
|
++*nerrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,24 @@
|
|||||||
#include <stdlib.h> /* strtol */
|
#include <stdlib.h> /* strtol */
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
|
||||||
|
// Each time a rule is matched, advance the end cursor/position.
|
||||||
|
#define YY_USER_ACTION \
|
||||||
|
yylloc->last_column += yyleng;
|
||||||
|
|
||||||
|
// Move the first position onto the last.
|
||||||
|
#define LOCATION_STEP() \
|
||||||
|
do { \
|
||||||
|
yylloc->first_line = yylloc->last_line; \
|
||||||
|
yylloc->first_column = yylloc->last_column; \
|
||||||
|
} while (0)
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
%{
|
||||||
|
// Each time yylex is called, move the head position to the end one.
|
||||||
|
LOCATION_STEP ();
|
||||||
|
%}
|
||||||
/* Rules. */
|
/* Rules. */
|
||||||
|
|
||||||
"+" return TOK_PLUS;
|
"+" return TOK_PLUS;
|
||||||
@@ -27,17 +42,17 @@
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
long n = strtol (yytext, NULL, 10);
|
long n = strtol (yytext, NULL, 10);
|
||||||
if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
|
if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
|
||||||
yyerror (nerrs, "integer is out of range");
|
yyerror (yylloc, nerrs, "integer is out of range");
|
||||||
yylval->TOK_NUM = (int) n;
|
yylval->TOK_NUM = (int) n;
|
||||||
return TOK_NUM;
|
return TOK_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"\n" yylloc->last_line++; yylloc->last_column = 1; return TOK_EOL;
|
||||||
|
|
||||||
/* Ignore white spaces. */
|
/* Ignore white spaces. */
|
||||||
[ \t]+ continue;
|
[ \t]+ LOCATION_STEP (); continue;
|
||||||
|
|
||||||
"\n" return TOK_EOL;
|
. yyerror (yylloc, nerrs, "syntax error, invalid character"); continue;
|
||||||
|
|
||||||
. yyerror (nerrs, "syntax error, invalid character");
|
|
||||||
|
|
||||||
<<EOF>> return TOK_EOF;
|
<<EOF>> return TOK_EOF;
|
||||||
%%
|
%%
|
||||||
|
|||||||
Reference in New Issue
Block a user