mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
examples: d: demonstrate location tracking
* examples/d/calc/calc.y: Track locations. * examples/d/calc/calc.test: Check locations.
This commit is contained in:
committed by
Akim Demaille
parent
8032dde383
commit
6e1d83c8a8
@@ -9,7 +9,7 @@ afterwards.
|
|||||||
The usual calculator.
|
The usual calculator.
|
||||||
|
|
||||||
## d/calc.y
|
## d/calc.y
|
||||||
A richer implementation of the calculator.
|
A richer implementation of the calculator, with location tracking.
|
||||||
|
|
||||||
<!---
|
<!---
|
||||||
|
|
||||||
|
|||||||
@@ -33,4 +33,19 @@ run 0 5
|
|||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
1 + 2 * * 3
|
1 + 2 * * 3
|
||||||
EOF
|
EOF
|
||||||
run 1 "err: syntax error, unexpected *, expecting + or - or ( or number"
|
run 1 "err: 1.9: syntax error, unexpected *, expecting + or - or ( or number"
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
1111 + 1111 2222
|
||||||
|
EOF
|
||||||
|
run 1 "err: 1.13-16: syntax error, unexpected number"
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
1 +
|
||||||
|
EOF
|
||||||
|
run 1 "err: 1.4-2.0: syntax error, unexpected end of line, expecting + or - or ( or number"
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
99 009
|
||||||
|
EOF
|
||||||
|
run 1 "err: 1.4-6: syntax error, unexpected number"
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
%define api.parser.class {Calc}
|
%define api.parser.class {Calc}
|
||||||
%define parse.error verbose
|
%define parse.error verbose
|
||||||
|
|
||||||
|
%locations
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
int ival;
|
int ival;
|
||||||
}
|
}
|
||||||
@@ -94,13 +96,16 @@ class CalcLexer(R) : Lexer
|
|||||||
|
|
||||||
this(R r) { input = r; }
|
this(R r) { input = r; }
|
||||||
|
|
||||||
|
YYPosition start;
|
||||||
|
YYPosition end;
|
||||||
|
|
||||||
// Should be a local in main, shared with %parse-param.
|
// Should be a local in main, shared with %parse-param.
|
||||||
int exit_status = 0;
|
int exit_status = 0;
|
||||||
|
|
||||||
public void yyerror (string s)
|
void yyerror(YYLocation loc, string s)
|
||||||
{
|
{
|
||||||
exit_status = 1;
|
exit_status = 1;
|
||||||
stderr.writeln (s);
|
stderr.writeln(loc.toString(), ": ", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
YYSemanticType semanticVal_;
|
YYSemanticType semanticVal_;
|
||||||
@@ -116,24 +121,39 @@ class CalcLexer(R) : Lexer
|
|||||||
|
|
||||||
// Skip initial spaces
|
// Skip initial spaces
|
||||||
while (!input.empty && input.front != '\n' && isWhite (input.front))
|
while (!input.empty && input.front != '\n' && isWhite (input.front))
|
||||||
|
{
|
||||||
|
start = end;
|
||||||
|
end.column++;
|
||||||
input.popFront;
|
input.popFront;
|
||||||
|
}
|
||||||
|
|
||||||
if (input.empty)
|
if (input.empty)
|
||||||
return TokenKind.YYEOF;
|
return TokenKind.YYEOF;
|
||||||
|
|
||||||
// Numbers.
|
// Numbers.
|
||||||
if (input.front.isNumber)
|
if (input.front.isNumber)
|
||||||
|
{
|
||||||
|
int lenChars = 0;
|
||||||
|
auto copy = input;
|
||||||
|
import std.conv : parse;
|
||||||
|
semanticVal_.ival = input.parse!int;
|
||||||
|
while (!input.empty && copy.front != input.front)
|
||||||
{
|
{
|
||||||
import std.conv : parse;
|
lenChars++;
|
||||||
semanticVal_.ival = input.parse!int;
|
copy.popFront;
|
||||||
return TokenKind.NUM;
|
|
||||||
}
|
}
|
||||||
|
start = end;
|
||||||
|
end.column += lenChars;
|
||||||
|
return TokenKind.NUM;
|
||||||
|
}
|
||||||
|
|
||||||
// Individual characters
|
// Individual characters
|
||||||
auto ch = input.front;
|
auto ch = input.front;
|
||||||
input.popFront;
|
input.popFront;
|
||||||
|
start = end;
|
||||||
|
end.column++;
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case '=': return TokenKind.EQ;
|
case '=': return TokenKind.EQ;
|
||||||
case '+': return TokenKind.PLUS;
|
case '+': return TokenKind.PLUS;
|
||||||
case '-': return TokenKind.MINUS;
|
case '-': return TokenKind.MINUS;
|
||||||
@@ -141,9 +161,24 @@ class CalcLexer(R) : Lexer
|
|||||||
case '/': return TokenKind.SLASH;
|
case '/': return TokenKind.SLASH;
|
||||||
case '(': return TokenKind.LPAR;
|
case '(': return TokenKind.LPAR;
|
||||||
case ')': return TokenKind.RPAR;
|
case ')': return TokenKind.RPAR;
|
||||||
case '\n': return TokenKind.EOL;
|
case '\n':
|
||||||
default: assert(0);
|
{
|
||||||
|
end.line++;
|
||||||
|
end.column = 1;
|
||||||
|
return TokenKind.EOL;
|
||||||
}
|
}
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
YYPosition startPos() const
|
||||||
|
{
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
YYPosition endPos() const
|
||||||
|
{
|
||||||
|
return end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user