examples: d: demonstrate location tracking

* examples/d/calc/calc.y: Track locations.
* examples/d/calc/calc.test: Check locations.
This commit is contained in:
Adela Vais
2020-09-03 08:42:06 +02:00
committed by Akim Demaille
parent 8032dde383
commit 6e1d83c8a8
3 changed files with 60 additions and 10 deletions

View File

@@ -33,4 +33,19 @@ run 0 5
cat >input <<EOF
1 + 2 * * 3
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"

View File

@@ -22,6 +22,8 @@
%define api.parser.class {Calc}
%define parse.error verbose
%locations
%union {
int ival;
}
@@ -94,13 +96,16 @@ class CalcLexer(R) : Lexer
this(R r) { input = r; }
YYPosition start;
YYPosition end;
// Should be a local in main, shared with %parse-param.
int exit_status = 0;
public void yyerror (string s)
void yyerror(YYLocation loc, string s)
{
exit_status = 1;
stderr.writeln (s);
stderr.writeln(loc.toString(), ": ", s);
}
YYSemanticType semanticVal_;
@@ -116,24 +121,39 @@ class CalcLexer(R) : Lexer
// Skip initial spaces
while (!input.empty && input.front != '\n' && isWhite (input.front))
{
start = end;
end.column++;
input.popFront;
}
if (input.empty)
return TokenKind.YYEOF;
// Numbers.
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;
semanticVal_.ival = input.parse!int;
return TokenKind.NUM;
lenChars++;
copy.popFront;
}
start = end;
end.column += lenChars;
return TokenKind.NUM;
}
// Individual characters
auto ch = input.front;
input.popFront;
start = end;
end.column++;
switch (ch)
{
{
case '=': return TokenKind.EQ;
case '+': return TokenKind.PLUS;
case '-': return TokenKind.MINUS;
@@ -141,9 +161,24 @@ class CalcLexer(R) : Lexer
case '/': return TokenKind.SLASH;
case '(': return TokenKind.LPAR;
case ')': return TokenKind.RPAR;
case '\n': return TokenKind.EOL;
default: assert(0);
case '\n':
{
end.line++;
end.column = 1;
return TokenKind.EOL;
}
default: assert(0);
}
}
YYPosition startPos() const
{
return start;
}
YYPosition endPos() const
{
return end;
}
}