mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
251 lines
5.4 KiB
Plaintext
251 lines
5.4 KiB
Plaintext
# Interface with the scanner. -*- Autotest -*-
|
|
|
|
# Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
AT_BANNER([[Interface with the scanner.]])
|
|
|
|
|
|
# -------------- #
|
|
# AT_RAW_YYLEX. #
|
|
# -------------- #
|
|
|
|
m4_pushdef([AT_RAW_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
|
|
|
|
m4_define([AT_RAW_YYLEX(c)],
|
|
[#include <stdlib.h> /* abort */
|
|
AT_YYLEX_PROTOTYPE[
|
|
{
|
|
static const char* input = "0-(1+2)*3/9";
|
|
int c = *input++;
|
|
switch (c)
|
|
{
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
]AT_VAL[.val = c - '0';
|
|
return NUM;
|
|
case '+': return PLUS;
|
|
case '-': return MINUS;
|
|
case '*': return STAR;
|
|
case '/': return SLASH;
|
|
case '(': return LPAR;
|
|
case ')': return RPAR;
|
|
case 0: return 0;
|
|
}
|
|
abort ();
|
|
}
|
|
]])
|
|
|
|
m4_define([AT_RAW_YYLEX(c++)],
|
|
[#include <stdlib.h> /* abort */
|
|
AT_YYLEX_PROTOTYPE[
|
|
{
|
|
static const char* input = "0-(1+2)*3/9";
|
|
int c = *input++;
|
|
switch (c)
|
|
{
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':]AT_TOKEN_CTOR_IF([[
|
|
return yy::parser::make_NUM (c - '0');]], [[
|
|
]AT_VAL[.val = c - '0';
|
|
return yy::parser::token::NUM;]])[
|
|
case '+': return yy::parser::]AT_TOKEN_CTOR_IF([make_PLUS ()], [token::PLUS])[;
|
|
case '-': return yy::parser::]AT_TOKEN_CTOR_IF([make_MINUS ()], [token::MINUS])[;
|
|
case '*': return yy::parser::]AT_TOKEN_CTOR_IF([make_STAR ()], [token::STAR])[;
|
|
case '/': return yy::parser::]AT_TOKEN_CTOR_IF([make_SLASH ()], [token::SLASH])[;
|
|
case '(': return yy::parser::]AT_TOKEN_CTOR_IF([make_LPAR ()], [token::LPAR])[;
|
|
case ')': return yy::parser::]AT_TOKEN_CTOR_IF([make_RPAR ()], [token::RPAR])[;
|
|
case 0: return yy::parser::]AT_TOKEN_CTOR_IF([make_END ()], [token::END])[;
|
|
}
|
|
abort ();
|
|
}
|
|
]])
|
|
|
|
m4_define([AT_RAW_YYLEX(d)],
|
|
[[import std.range.primitives;
|
|
import std.stdio;
|
|
|
|
auto yyLexer(R)(R range)
|
|
if (isInputRange!R && is (ElementType!R : dchar))
|
|
{
|
|
return new YYLexer!R(range);
|
|
}
|
|
|
|
auto yyLexer ()
|
|
{
|
|
return yyLexer("0-(1+2)*3/9");
|
|
}
|
|
|
|
class YYLexer(R) : Lexer
|
|
if (isInputRange!R && is (ElementType!R : dchar))
|
|
{
|
|
R input;
|
|
|
|
this(R r) {
|
|
input = r;
|
|
}
|
|
|
|
]AT_YYERROR_DEFINE[
|
|
|
|
YYSemanticType semanticVal_;
|
|
public final @property YYSemanticType semanticVal ()
|
|
{
|
|
return semanticVal_;
|
|
}
|
|
|
|
int yylex ()
|
|
{
|
|
import std.uni : isNumber;
|
|
// Handle EOF.
|
|
if (input.empty)
|
|
return YYTokenType.EOF;
|
|
|
|
auto c = input.front;
|
|
input.popFront;
|
|
|
|
// Numbers.
|
|
switch (c)
|
|
{
|
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
|
semanticVal_.val = c - '0';
|
|
return YYTokenType.NUM;
|
|
case '+': return YYTokenType.PLUS;
|
|
case '-': return YYTokenType.MINUS;
|
|
case '*': return YYTokenType.STAR;
|
|
case '/': return YYTokenType.SLASH;
|
|
case '(': return YYTokenType.LPAR;
|
|
case ')': return YYTokenType.RPAR;
|
|
default: assert(0);
|
|
}
|
|
}
|
|
}
|
|
]])
|
|
|
|
m4_pushdef([AT_MAIN_DEFINE(d)],
|
|
[[int main ()
|
|
{
|
|
auto l = yyLexer ();
|
|
auto p = new YYParser (l);
|
|
return !p.parse ();
|
|
}]])
|
|
|
|
|
|
## ------------------- ##
|
|
## Raw token numbers. ##
|
|
## ------------------- ##
|
|
|
|
m4_pushdef([AT_TEST],
|
|
[
|
|
AT_SETUP([Token numbers: $1])
|
|
|
|
AT_BISON_OPTION_PUSHDEFS([%debug $1])
|
|
AT_DATA_GRAMMAR([[input.y]],
|
|
[[$1
|
|
%debug
|
|
]AT_D_IF([], [[
|
|
%code
|
|
{
|
|
#include <stdio.h>
|
|
]AT_YYERROR_DECLARE[
|
|
]AT_YYLEX_DECLARE[
|
|
}]])[
|
|
|
|
]AT_VARIANT_IF([[
|
|
%token <int> NUM "number"
|
|
%nterm <int> exp
|
|
]], [[
|
|
%union {
|
|
int val;
|
|
}
|
|
%token <val> NUM "number"
|
|
%nterm <val> exp
|
|
]])[
|
|
|
|
%token
|
|
PLUS "+"
|
|
MINUS "-"
|
|
STAR "*"
|
|
SLASH "/"
|
|
LPAR "("
|
|
RPAR ")"
|
|
END 0
|
|
|
|
%left "+" "-"
|
|
%left "*" "/"
|
|
|
|
%%
|
|
|
|
input
|
|
: exp { printf ("%d\n", $][1); }
|
|
;
|
|
|
|
exp
|
|
: exp "+" exp { $][$][ = $][1 + $][3; }
|
|
| exp "-" exp { $][$][ = $][1 - $][3; }
|
|
| exp "*" exp { $][$][ = $][1 * $][3; }
|
|
| exp "/" exp { $][$][ = $][1 / $][3; }
|
|
| "(" exp ")" { $][$][ = $][2; }
|
|
| "number" { $][$][ = $][1; }
|
|
;
|
|
|
|
%%
|
|
]AT_YYERROR_DEFINE[
|
|
]AT_RAW_YYLEX[
|
|
]AT_MAIN_DEFINE[
|
|
]])
|
|
|
|
AT_FULL_COMPILE([input])
|
|
|
|
# yacc.c, glr.c and glr.cc use 'yytranslate' (and YYTRANSLATE).
|
|
# lalr1.cc uses 'translate_table' (and yytranslate_).
|
|
# lalr1.d uses 'byte[] translate_table =' (and yytranslate_).
|
|
AT_CHECK([[$EGREP -c 'yytranslate\[\]|translate_table\[\]|translate_table =' input.]AT_LANG_EXT],
|
|
[ignore],
|
|
[AT_TOKEN_RAW_IF([0], [1])[
|
|
]])
|
|
|
|
AT_PARSER_CHECK([input], 0,
|
|
[[-1
|
|
]])
|
|
|
|
AT_BISON_OPTION_POPDEFS
|
|
AT_CLEANUP
|
|
])
|
|
|
|
m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc], [lalr1.d]],
|
|
[AT_TEST([%skeleton "]b4_skel["])
|
|
AT_TEST([%skeleton "]b4_skel[" %define api.token.raw])])
|
|
|
|
AT_TEST([%skeleton "lalr1.cc" %define api.token.raw %define api.value.type variant %define api.token.constructor])])
|
|
|
|
m4_popdef([AT_MAIN_DEFINE(d)])
|
|
m4_popdef([AT_TEST])
|