mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
d: modernize the scanner of the example
https://lists.gnu.org/archive/html/bison-patches/2019-02/msg00121.html * examples/d/calc.y (CalcLexer): Stop shoehorning C's API into D: use a range based approach in the scanner, rather than some imitation of getc/ungetc. (main): Adjust.
This commit is contained in:
committed by
Akim Demaille
parent
8eac78f8ef
commit
f8408562f8
@@ -53,78 +53,63 @@ exp:
|
|||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
class CalcLexer : Lexer {
|
import std.range.primitives;
|
||||||
|
|
||||||
|
auto calcLexer(R)(R range)
|
||||||
|
if (isInputRange!R && is (ElementType!R : dchar))
|
||||||
|
{
|
||||||
|
return new CalcLexer!R(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CalcLexer(R) : Lexer
|
||||||
|
if (isInputRange!R && is (ElementType!R : dchar))
|
||||||
|
{
|
||||||
|
R input;
|
||||||
|
|
||||||
|
this(R r) { input = r; }
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
int
|
|
||||||
get_char ()
|
|
||||||
{
|
|
||||||
import stdc = core.stdc.stdio;
|
|
||||||
return stdc.getc (stdc.stdin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
unget_char (int c)
|
|
||||||
{
|
|
||||||
import stdc = core.stdc.stdio;
|
|
||||||
stdc.ungetc (c, stdc.stdin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void yyerror (string s)
|
public void yyerror (string s)
|
||||||
{
|
{
|
||||||
exit_status = 1;
|
exit_status = 1;
|
||||||
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 ()
|
||||||
{
|
{
|
||||||
return semanticVal_;
|
return semanticVal_;
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
||||||
{
|
{
|
||||||
unget_char (c);
|
input.popFront;
|
||||||
semanticVal_.ival = read_signed_integer ();
|
}
|
||||||
|
|
||||||
|
// Handle EOF.
|
||||||
|
if (input.empty)
|
||||||
|
return YYTokenType.EOF;
|
||||||
|
|
||||||
|
// Numbers.
|
||||||
|
if (input.front == '.' || input.front.isNumber)
|
||||||
|
{
|
||||||
|
import std.conv : parse;
|
||||||
|
semanticVal_.ival = input.parse!int;
|
||||||
return YYTokenType.NUM;
|
return YYTokenType.NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (c)
|
// Individual characters
|
||||||
|
auto ch = input.front;
|
||||||
|
input.popFront;
|
||||||
|
switch (ch)
|
||||||
{
|
{
|
||||||
case EOF: return YYTokenType.EOF;
|
case EOF: return YYTokenType.EOF;
|
||||||
case '=': return YYTokenType.EQ;
|
case '=': return YYTokenType.EQ;
|
||||||
@@ -142,7 +127,16 @@ class CalcLexer : Lexer {
|
|||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
CalcLexer l = new CalcLexer ();
|
import std.algorithm : map, joiner;
|
||||||
|
import std.stdio;
|
||||||
|
import std.utf : byDchar;
|
||||||
|
|
||||||
|
auto l = stdin
|
||||||
|
.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;
|
||||||
|
|
||||||
Calc p = new Calc (l);
|
Calc p = new Calc (l);
|
||||||
p.parse ();
|
p.parse ();
|
||||||
return l.exit_status;
|
return l.exit_status;
|
||||||
|
|||||||
Reference in New Issue
Block a user