mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-17 00:03:03 +00:00
d: tests: use more a natural approach for the scanner
See f8408562f8.
* tests/calc.at: Stop imitating the C API.
Prepare more tests to run in the future.
%verbose works as expected (what a surprise, it's unrelated to the
skeleton...).
This commit is contained in:
125
tests/calc.at
125
tests/calc.at
@@ -51,10 +51,9 @@ AT_D_IF([m4_pushdef([AT_CALC_MAIN],
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
File input = args.length == 2 ? File (args[1], "r") : stdin;
|
File input = args.length == 2 ? File (args[1], "r") : stdin;
|
||||||
CalcLexer l = new CalcLexer (input);
|
auto l = calcLexer (input);
|
||||||
YYParser p = new YYParser (l);
|
auto p = new YYParser (l);
|
||||||
int status = !p.parse ();
|
return !p.parse ();
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
]])],
|
]])],
|
||||||
[m4_pushdef([AT_CALC_MAIN],
|
[m4_pushdef([AT_CALC_MAIN],
|
||||||
@@ -117,71 +116,38 @@ main (int argc, const char **argv)
|
|||||||
]])])
|
]])])
|
||||||
|
|
||||||
AT_D_IF([m4_pushdef([AT_CALC_LEX],
|
AT_D_IF([m4_pushdef([AT_CALC_LEX],
|
||||||
[[class CalcLexer : Lexer
|
[[import std.range.primitives;
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
auto calcLexer(R)(R range)
|
||||||
|
if (isInputRange!R && is (ElementType!R : dchar))
|
||||||
{
|
{
|
||||||
|
return new CalcLexer!R(range);
|
||||||
|
}
|
||||||
|
|
||||||
this (File i)
|
auto calcLexer (File f)
|
||||||
{
|
{
|
||||||
input = i;
|
import std.algorithm : map, joiner;
|
||||||
}
|
import std.utf : byDchar;
|
||||||
|
|
||||||
File input;
|
return f.byChunk(1024) // avoid making a syscall roundtrip per char
|
||||||
|
.map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[]
|
||||||
|
.joiner // combine chunks into a single virtual range of char
|
||||||
|
.calcLexer; // forward to other overload
|
||||||
|
}
|
||||||
|
|
||||||
int prev_char = -1;
|
class CalcLexer(R) : Lexer
|
||||||
|
if (isInputRange!R && is (ElementType!R : dchar))
|
||||||
|
{
|
||||||
|
R input;
|
||||||
|
|
||||||
int
|
this(R r) { input = r; }
|
||||||
get_char ()
|
|
||||||
{
|
|
||||||
if (prev_char != -1)
|
|
||||||
{
|
|
||||||
auto res = prev_char;
|
|
||||||
prev_char = -1;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto res = input.rawRead (new char[1]);
|
|
||||||
if (res.length == 0)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return res[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
unget_char (int c)
|
|
||||||
{
|
|
||||||
prev_char = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void yyerror (string s)
|
public void yyerror (string s)
|
||||||
{
|
{
|
||||||
stderr.writeln (s);
|
stderr.writeln (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
read_signed_integer ()
|
|
||||||
{
|
|
||||||
int c = get_char ();
|
|
||||||
int sign = 1;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
if (c == '-')
|
|
||||||
{
|
|
||||||
c = get_char ();
|
|
||||||
sign = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (isDigit (c))
|
|
||||||
{
|
|
||||||
n = 10 * n + (c - '0');
|
|
||||||
c = get_char ();
|
|
||||||
}
|
|
||||||
|
|
||||||
unget_char (c);
|
|
||||||
return sign * n;
|
|
||||||
}
|
|
||||||
|
|
||||||
YYSemanticType semanticVal_;
|
YYSemanticType semanticVal_;
|
||||||
|
|
||||||
public final @property YYSemanticType semanticVal()
|
public final @property YYSemanticType semanticVal()
|
||||||
@@ -191,27 +157,27 @@ AT_D_IF([m4_pushdef([AT_CALC_LEX],
|
|||||||
|
|
||||||
int yylex ()
|
int yylex ()
|
||||||
{
|
{
|
||||||
int c;
|
import std.uni : isWhite, isNumber;
|
||||||
/* Skip white spaces. */
|
|
||||||
do
|
|
||||||
{}
|
|
||||||
while ((c = get_char ()) == ' ' || c == '\t');
|
|
||||||
|
|
||||||
/* process numbers */
|
// Skip initial spaces
|
||||||
if (c == '.' || isDigit (c))
|
while (!input.empty && input.front != '\n' && isWhite (input.front))
|
||||||
|
input.popFront;
|
||||||
|
|
||||||
|
// Handle EOF.
|
||||||
|
if (input.empty)
|
||||||
|
return YYTokenType.EOF;
|
||||||
|
|
||||||
|
// Numbers.
|
||||||
|
if (input.front == '.' || input.front.isNumber)
|
||||||
{
|
{
|
||||||
unget_char (c);
|
import std.conv : parse;
|
||||||
semanticVal_.ival = read_signed_integer ();
|
semanticVal_.ival = input.parse!int;
|
||||||
return YYTokenType.NUM;
|
return YYTokenType.NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return end-of-file. */
|
// Individual characters
|
||||||
if (c == EOF)
|
auto c = input.front;
|
||||||
{
|
input.popFront;
|
||||||
return YYTokenType.EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return single chars. */
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -874,3 +840,14 @@ m4_define([AT_CHECK_CALC_LALR1_D],
|
|||||||
[AT_CHECK_CALC([%language "D" $1], [$2])])
|
[AT_CHECK_CALC([%language "D" $1], [$2])])
|
||||||
|
|
||||||
AT_CHECK_CALC_LALR1_D([])
|
AT_CHECK_CALC_LALR1_D([])
|
||||||
|
#AT_CHECK_CALC_LALR1_D([%locations])
|
||||||
|
#AT_CHECK_CALC_LALR1_D([%locations %define api.location.type {Span}])
|
||||||
|
AT_CHECK_CALC_LALR1_D([%define parse.error verbose %define api.prefix {calc} %verbose])
|
||||||
|
|
||||||
|
#AT_CHECK_CALC_LALR1_D([%debug])
|
||||||
|
|
||||||
|
#AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose])
|
||||||
|
#AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.token.prefix {TOK_} %verbose])
|
||||||
|
|
||||||
|
#AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
|
||||||
|
#AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
|
||||||
|
|||||||
Reference in New Issue
Block a user