TEAM-ADA Archives

Team Ada: Ada Programming Language Advocacy

TEAM-ADA@LISTSERV.ACM.ORG

Options: Use Forum View

Use Proportional Font
Show HTML Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Tucker Taft <[log in to unmask]>
Reply To:
Tucker Taft <[log in to unmask]>
Date:
Sun, 11 Mar 2001 22:11:22 -0500
Content-Type:
text/plain
Parts/Attachments:
text/plain (153 lines)
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

ATOM RSS1 RSS2