Sun, 11 Mar 2001 22:11:22 -0500
|
Here is a parser for a simple calculator written using ayacc/aflex.
It is one of the examples that comes with the ayacc/aflex
documentation.
Let me know whether you need more information on ayacc/aflex.
I have been using them recently. I compiled them using "my favorite
Ada 95 compiler" after a minor adjustment to the GNAT-compatible sources
(there was an uninitialized variable passed as an IN OUT parameter --
made it an OUT parameter and all was well).
The output they generate is fully compatible with Ada 95.
-Tucker Taft [log in to unmask]
============ calc.y ============
%token '(' ')' number identifier new_line
%right '='
%left '+' '-'
%left '*' '/'
%right dummy
%nonassoc exp
{
type key_type is (cval, ival, noval);
type yystype is record
register : character;
value : integer;
end record;
}
%%
-- Statements is the goal symbol
statements : statements statement
|
;
statement : expr end
{ put_line(integer'image($1.value)); }
| error end -- This should catch various errors
{ put_line("Try again");
yyerrok; -- yyclearin;
}
statement
;
expr : id '=' expr
{ registers($1.register) := $3.value;
$$.value := $3.value; }
| expr '+' expr
{ $$.value := $1.value + $3.value; }
| expr '-' expr
{ $$.value := $1.value - $3.value; }
| expr '*' expr
{ $$.value := $1.value * $3.value; }
| expr '/' expr
{ $$.value := $1.value / $3.value; }
| expr exp expr
{ $$.value := integer(float($1.value) ** $3.value); }
| '-' expr %prec dummy
{ $$.value := - $2.value; }
| '(' expr ')'
{ $$.value := $2.value; }
| number
{ $$.value := character'pos(calc_lex_dfa.yytext(1)) -
character'pos('0'); }
| id
{ $$.value := registers($1.register); }
;
id : identifier
{ $$.register := to_upper(calc_lex_dfa.yytext(1)); }
;
end : new_line
| end_of_input
;
%%
package parser is
procedure yyparse;
end parser;
with yylex, calc_lex_dfa, calc_lex_io, text_io, calc_tokens, calc_goto, calc_shift_reduce;
use text_io, calc_tokens, calc_goto, calc_lex_io, calc_shift_reduce;
package body parser is
registers : array(Character range 'A'..'Z') of integer;
function to_upper(ch : in character) return character is
begin
if ch in 'a'..'z' then
return character'val( character'pos(ch) - (character'pos('a') -
character'pos('A')) );
else
return ch;
end if;
end to_upper;
procedure yyerror(s: string) is
begin
put_line(s);
end;
##
end parser;
============ calc_lex.l ============
%%
[A-Z] { return IDENTIFIER; }
[a-z] { return IDENTIFIER; }
[0-9]+ { return NUMBER; }
"**" { return EXP; }
"(" { return '('; }
")" { return ')'; }
"+" { return '+'; }
"/" { return '/'; }
"*" { return '*'; }
"=" { return '='; }
"-" { return '-'; }
\n { return NEW_LINE; }
[\t ]+ { null;}
%%
with calc_tokens;
use calc_tokens;
##
============ driver.a ============
with parser, calc_lex_io, text_io;
procedure driver is
in_file_name: string(1..80);
last : natural;
begin
text_io.put("Enter input file: ");
text_io.get_line(in_file_name, last);
calc_lex_io.open_input(in_file_name(1..last));
--calc_lex_io.open_input("/dev/tty");
calc_lex_io.create_output;
parser.yyparse;
calc_lex_io.close_input;
calc_lex_io.close_output;
end driver;
============ calc.input ============
1+1
a=5
b=2
c=b+a
|
|
|