1234949Sbapt%pure-parser
2234949Sbapt
3234949Sbapt%parse-param { int regs[26] }
4234949Sbapt%parse-param { int *base }
5234949Sbapt
6234949Sbapt%lex-param { int *base }
7234949Sbapt
8234949Sbapt%{
9234949Sbapt# include <stdio.h>
10234949Sbapt# include <ctype.h>
11234949Sbapt
12234949Sbapt#ifdef YYBISON
13234949Sbapt#define YYSTYPE int
14234949Sbapt#define YYLEX_PARAM base
15234949Sbapt#define YYLEX_DECL() yylex(YYSTYPE *yylval, int *YYLEX_PARAM)
16234949Sbapt#define YYERROR_DECL() yyerror(int regs[26], int *base, const char *s)
17234949Sbaptint YYLEX_DECL();
18234949Sbaptstatic void YYERROR_DECL();
19234949Sbapt#endif
20234949Sbapt
21234949Sbapt%}
22234949Sbapt
23234949Sbapt%start list
24234949Sbapt
25234949Sbapt%token DIGIT LETTER
26234949Sbapt
27234949Sbapt%left '|'
28234949Sbapt%left '&'
29234949Sbapt%left '+' '-'
30234949Sbapt%left '*' '/' '%'
31234949Sbapt%left UMINUS   /* supplies precedence for unary minus */
32234949Sbapt
33234949Sbapt%% /* beginning of rules section */
34234949Sbapt
35234949Sbaptlist  :  /* empty */
36234949Sbapt      |  list stat '\n'
37234949Sbapt      |  list error '\n'
38234949Sbapt            {  yyerrok ; }
39234949Sbapt      ;
40234949Sbapt
41234949Sbaptstat  :  expr
42234949Sbapt            {  printf("%d\n",$1);}
43234949Sbapt      |  LETTER '=' expr
44234949Sbapt            {  regs[$1] = $3; }
45234949Sbapt      ;
46234949Sbapt
47234949Sbaptexpr  :  '(' expr ')'
48234949Sbapt            {  $$ = $2; }
49234949Sbapt      |  expr '+' expr
50234949Sbapt            {  $$ = $1 + $3; }
51234949Sbapt      |  expr '-' expr
52234949Sbapt            {  $$ = $1 - $3; }
53234949Sbapt      |  expr '*' expr
54234949Sbapt            {  $$ = $1 * $3; }
55234949Sbapt      |  expr '/' expr
56234949Sbapt            {  $$ = $1 / $3; }
57234949Sbapt      |  expr '%' expr
58234949Sbapt            {  $$ = $1 % $3; }
59234949Sbapt      |  expr '&' expr
60234949Sbapt            {  $$ = $1 & $3; }
61234949Sbapt      |  expr '|' expr
62234949Sbapt            {  $$ = $1 | $3; }
63234949Sbapt      |  '-' expr %prec UMINUS
64234949Sbapt            {  $$ = - $2; }
65234949Sbapt      |  LETTER
66234949Sbapt            {  $$ = regs[$1]; }
67234949Sbapt      |  number
68234949Sbapt      ;
69234949Sbapt
70234949Sbaptnumber:  DIGIT
71234949Sbapt         {  $$ = $1; (*base) = ($1==0) ? 8 : 10; }
72234949Sbapt      |  number DIGIT
73234949Sbapt         {  $$ = (*base) * $1 + $2; }
74234949Sbapt      ;
75234949Sbapt
76234949Sbapt%% /* start of programs */
77234949Sbapt
78234949Sbapt#ifdef YYBYACC
79234949Sbaptextern int YYLEX_DECL();
80234949Sbapt#endif
81234949Sbapt
82234949Sbaptint
83234949Sbaptmain (void)
84234949Sbapt{
85234949Sbapt    int regs[26];
86234949Sbapt    int base = 10;
87234949Sbapt
88234949Sbapt    while(!feof(stdin)) {
89234949Sbapt	yyparse(regs, &base);
90234949Sbapt    }
91234949Sbapt    return 0;
92234949Sbapt}
93234949Sbapt
94264803Sbapt#define UNUSED(x) ((void)(x))
95264803Sbapt
96234949Sbaptstatic void
97234949SbaptYYERROR_DECL()
98234949Sbapt{
99264803Sbapt    UNUSED(regs); /* %parse-param regs is not actually used here */
100264803Sbapt    UNUSED(base); /* %parse-param base is not actually used here */
101234949Sbapt    fprintf(stderr, "%s\n", s);
102234949Sbapt}
103234949Sbapt
104234949Sbaptint
105234949SbaptYYLEX_DECL()
106234949Sbapt{
107234949Sbapt	/* lexical analysis routine */
108234949Sbapt	/* returns LETTER for a lower case letter, yylval = 0 through 25 */
109234949Sbapt	/* return DIGIT for a digit, yylval = 0 through 9 */
110234949Sbapt	/* all other characters are returned immediately */
111234949Sbapt
112234949Sbapt    int c;
113234949Sbapt
114234949Sbapt    while( (c=getchar()) == ' ' )   { /* skip blanks */ }
115234949Sbapt
116234949Sbapt    /* c is now nonblank */
117234949Sbapt
118234949Sbapt    if( islower( c )) {
119234949Sbapt	*yylval = (c - 'a');
120234949Sbapt	return ( LETTER );
121234949Sbapt    }
122234949Sbapt    if( isdigit( c )) {
123234949Sbapt	*yylval = (c - '0') % (*base);
124234949Sbapt	return ( DIGIT );
125234949Sbapt    }
126234949Sbapt    return( c );
127234949Sbapt}
128