|
|
date: month_name day ',' year ; |
July 4, 1776 |
month_name : 'J' 'a' 'n' ; month_name : 'F' 'e' 'b' ; ... month_name : 'D' 'e' 'c' ; |
date : month '/' day '/' year ; |
7/4/1776 |
July 4, 1776 |
declarations %% rules %% subroutines |
%% S:; |
A: BODY ; |
A : B C D ; A : E F ; A : G ; |
A : B C D
| E F
| G
;
|
epsilon : ; |
$token name1 name2 name3 |
$start symbol |
A : '(' B ')'
{
hello( 1, "abc" );
}
|
XXX : YYY ZZZ
{
(void) printf("a message\n");
flag = 25;
}
|
{ $$ = 1; }
|
A : B C D ; |
expr : '(' expr ')' ;
|
expr : '(' expr ')'
{
$$ = $2 ;
}
|
A : B ; |
A : B
{
$$ = 1;
}
C
{
x = $2;
y = $3;
}
;
|
$ACT : /* empty */
{
$$ = 1;
}
;
A : B $ACT C
{
x = $2;
y = $3;
}
;
|
node( L, n1, n2 ) |
expr : expr '+' expr
{
$$ = node( '+', $1, $3 );
}
|
%{ int variable = 0; %}
|
%{
int i;
printf("%}");
%}
|
int yylex()
{
extern int yylval;
int c;
...
c = getchar();
...
switch (c)
{
...
case '0':
case '1':
...
case '9':
yylval = c - '0';
return (DIGIT);
...
}
...
}
|
IF shift 34 |
. reduce 18 |
IF shift 34 |
A : x y z ; |
A goto 20 |
$token DING DONG DELL
%%
rhyme : sound place
;
sound : DING DONG
;
place: DELL
;
|
state 0 |
$accept : _rhyme $end
DING shift 3
. error
rhyme goto 1
sound goto 2
state 1
$accept : rhyme_$end
$end accept
. error
state 2
rhyme : sound_place
DELL shift 5
. error
place goto 4
state 3
sound : DING_DONG
DONG shift 6
. error
|
state 4
rhyme : sound place_ (1)
. reduce 1
state 5
place : DELL_ (3)
. reduce 3
state 6
sound : DING DONG_ (2)
. reduce 2
|
DING DONG DELL |
sound : DING DONG |
sound goto 2 |
expr : expr '-' expr |
expr - expr - expr |
( expr - expr ) - expr |
expr - ( expr - expr ) |
expr - expr - expr |
expr - expr |
- expr |
expr - expr |
expr - expr - expr |
expr - expr |
expr - expr |
stat : IF '(' cond ')' stat
| IF '(' cond ')' stat ELSE stat
;
|
IF ( C1 ) IF ( C2 ) S1 ELSE S2 |
IF ( C1 )
{
IF ( C2 )
S1
}
ELSE
S2
|
IF ( C1 )
{
IF ( C2 )
S1
ELSE
S2
}
|
IF ( C1 ) IF ( C2 ) S1 |
IF ( C1 ) stat |
ELSE S2 |
IF ( C1 ) stat ELSE S2 |
IF ( C1 ) IF ( C2 ) S1 ELSE S2 |
IF ( C1 ) stat |
IF ( C1 ) IF ( C2 ) S1 |
23: shift-reduce conflict (shift 45, reduce 18) on ELSE
state 23
stat : IF ( cond ) stat_ (18)
stat : IF ( cond ) stat_ELSE stat
ELSE shift 45
. reduce 18
|
IF ( cond ) stat |
stat : IF ( cond ) stat ELSE_stat |
stat : IF '(' cond ')' stat
|
expr : expr OP expr |
expr : UNARY expr |
%left '+' '-' %left '*' '/' |
A .LT. B .LT. C |
%right '='
%left '+' '-'
%left '*' '/'
%%
expr : expr '=' expr
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| NAME
;
|
a = b = c * d - e - f * g |
a = ( b = ( ((c * d) - e) - (f * g) ) ) |
%left '+' '-'
%left '*' '/'
%%
expr : expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| '-' expr %prec '*'
| NAME
;
|
if (flag) if (anotherflag) x = 1;
else x = 2;
|
%{
#include <stdio.h>
%}
%token SIMPLE IF ELSE
%%
S ; stmnt
;
stmnt : SIMPLE
| if_stmnt
;
if_stmnt : IF stmnt
{ printf("simple if\n");}
| IF stmnt ELSE stmnt
{ printf("if_then_else\n");}
;
%%
int
yylex() {
int c;
c=getchar();
if (c= =EOF) return 0;
else switch(c) {
case 'i': return IF;
case 's': return SIMPLE;
case 'e': return ELSE;
default: return c;
}
}
|
conflicts: 1 shift/reduce |
%{
#include <stdio.h>
%}
%token SIMPLE IF
%nonassoc REDUCE
%nonassoc ELSE
%%
S : stmnt '\n'
;
stmnt : SIMPLE
| if_stmnt
;
if_stmnt : IF stmnt %prec REDUCE
{ printf("simple if");}
| IF stmnt ELSE stmnt
{ printf("if_then_else");}
;
%%
|
%nonassoc IF %nonassoc ELSE |
stat : error |
stat : error ';' |
input : error '\n'
{
(void) printf("Reenter last line: " );
}
input
{
$$ = $4;
}
;
|
yyerrok ; |
input : error '\n'
{
yyerrok;
(void) printf("Reenter last line: " );
}
input
{
$$ = $4;
}
;
|
yyclearin ; |
stat : error
{
resynch();
yyerrok ;
yyclearin;
}
;
|
$ yacc grammar.y |
main()
{
return (yyparse());
}
|
# include <stdio.h>
yyerror(s)
char *s;
{
(void) fprintf(stderr, "%s\n", s);
}
|
name : name rest_of_rule ; |
list : item
| list ',' item
;
|
seq : item
| seq item
;
|
seq : item
| item seq
;
|
seq : /* empty */
| seq item
;
|
%{
int dflag;
%}
... other declarations ...
%%
prog : decls stats
;
decls : /* empty */
{
dflag = 1;
}
| decls declaration
;
stats : /* empty */
{
dflag = 0;
}
| stats statement
;
. . . other rules . . .
|
sent : adj noun verb adj noun
{
look at the sentence ...
}
;
adj : THE
{
$$ = THE;
}
| YOUNG
{
$$ = YOUNG;
}
...
;
noun : DOG
{
$$ = DOG;
}
| CRONE
{
if ( $0 = = YOUNG )
{
(void) printf( "what?\n" );
}
$$ = CRONE;
}
;
...
|
%union
{
body of union
}
|
<name> |
%left <optype> '+' '-' |
%type <nodetype> expr stat |
rule : aaa
{
$<intval>$ = 3;
}
bbb
{
fun( $<intval>2, $<other>0 );
}
;
|
C_IDENTIFIER.
/* grammar for the input to yacc */
/* basic entries */
%token IDENTIFIER /* includes identifiers and literals */
%token C_IDENTIFIER /* identifier (but not literal) */
/* followed by a : */
%token NUMBER /* [0-9]+ */
/* reserved words: %type=>TYPE %left=>LEFT,etc. */
%token LEFT RIGHT NONASSOC TOKEN PREC TYPE START UNION
%token MARK /* the %% mark */
|
%token LCURL /* the %{ mark */
%token RCURL /* the %} mark */
/* ASCII character literals stand for themselves */
%token spec t
%%
spec : defs MARK rules tail
;
tail : MARK
{
In this action,read in the rest of the file
}
| /* empty: the second MARK is optional */
;
defs : /* empty */
| defs def
;
def : START IDENTIFIER
| UNION
{
Copy union definition to output
}
| LCURL
|
{
Copy C code to output file
}
RCURL
| rword tag nlist
;
rword : TOKEN
| LEFT
| RIGHT
| NONASSOC
| TYPE
;
tag : /* empty: union tag is optional */
| '<' IDENTIFIER '>'
;
nlist : nmno
| nlist nmno
| nlist ',' nmno
;
nmno : IDENTIFIER /* Note: literal illegal with % type */
| IDENTIFIER NUMBER /* Note: illegal with % type */
;
/* rule section */
|
rules : C_IDENTIFIER rbody prec
| rules rule
;
rule : C_IDENTIFIER rbody prec
| '|' rbody prec
;
rbody : /* empty */
| rbody IDENTIFIER
| rbody act
;
act : '{'
{
Copy action translate $$ etc.
}
'}'
;
prec : /* empty */
| PREC IDENTIFIER
| PREC IDENTIFIER act
| prec ';'
;
|
%{
# include <stdio.h>
# include <ctype.h>
int regs[26];
int base;
%}
%start list
%token DIGIT LETTER
|
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /* supplies precedence for unary minus */
%% /* beginning of rules section */
list : /* empty */
| list stat '\n'
| list error '\n'
{
yyerrok;
}
;
stat : expr
{
(void) printf( "%d\n", $1 );
}
| LETTER '=' expr
{
regs[$1] = $3;
}
;
|
expr : '(' expr ')'
{
$$ = $2;
}
| expr '+' expr
{
$$ = $1 + $3;
}
| expr '-' expr
{
$$ = $1 - $3;
{
| expr '*' expr
{
$$ = $1 * $3;
}
| expr '/' expr
{
$$ = $1 / $3;
}
| exp '%' expr
{
$$ = $1 % $3;
}
|
| expr '&' expr
{
$$ = $1 & $3;
}
| expr '|' expr
{
$$ = $1 | $3;
}
| '-' expr %prec UMINUS
{
$$ = -$2;
}
| LETTER
{
$$ = reg[$1];
}
| number
;
number : DIGIT
{
$$ = $1; base = ($1= =0) ? 8 ; 10;
}
| number DIGIT
{
|
$$ = base * $1 + $2;
}
;
%% /* beginning of subroutines section */
int yylex( ) /* lexical analysis routine */
{ /* return LETTER for lowercase letter, */
/* yylval = 0 through 25 returns DIGIT */
/* for digit, yylval = 0 through 9 */
/* all other characters are returned immediately */
int c;
/*skip blanks*/
while ((c = getchar()) = = ' ')
;
/* c is now nonblank */
if (islower(c)) {
yylval = c - 'a';
return (LETTER);
}
if (isdigit(c)) {
yylval = c - '0';
return (DIGIT);
|
}
return (c);
}
|
(X,Y) |
2.5 + (3.5 - 4.) |
2.5 + (3.5, 4) |
%{
#include <stdio.h>
#include <ctype.h>
typedef struct interval {
double lo, hi;
} INTERVAL;
INTERVAL vmul(), vdiv();
double atof();
double dreg[26];
INTERVAL vreg[26];
%}
%start lines
%union {
int ival;
double dval;
INTERVAL vval;
|
}
%token <ival> DREG VREG /* indices into dreg, vreg arrays */
%token <dval> CONST /* floating point constant */
%type <dval> dexp /* expression */
%type <vval> vexp /* interval expression */
/* precedence information about the operators */
%left '+' '/-'
%left '*' '/'
%% /* beginning of rules section */
lines : /* empty */
| lines line
;
line : dexp '\n'
{
(void)printf("%15.8f\n", $1);
}
| vexp '\n'
{
(void)printf("(%15.8f, %15.8f)\n", $1.lo, $1.hi);
}
|
| DREG '=' dexp '\n'
{
dreg[$1] = $3;
}
| VREG '=' vexp '\n'
{
vreg[$1] = $3;
}
| error '\n'
{
yyerrok;
}
;
dexp : CONST
| DREG
{
$$ = dreg[$1];
}
| dexp '+' dexp
{
$$ = $1 + $3;
}
| dexp '-' dexp
{
$$ = $1 - $3;
|
}
| dexp '*' dexp
{
$$ = $1 * $3;
}
| dexp '/' dexp
{
$$ = $1 / $3;
}
| '-' dexp
{
$$ = -$2;
}
| '(' dexp ')'
{
$$ = $2;
}
;
vexp : dexp
{
$$.hi = $$.lo = $1;
}
| '(' dexp ',' dexp ')'
{
$$.lo = $2;
|
$$.hi = $4;
if($$.lo > $$.hi) {
(void) printf("interval out of order\n");
YYERROR;
}
}
| VREG
{
$$ = vreg[$1];
}
| vexp '+' vexp
{
$$.hi = $1.hi + $3.hi;
$$.lo = $1.lo + $3.lo;
}
| dexp '+' vexp
{
$$.hi = $1 + $3.hi;
$$.lo = $1 + $3.lo;
}
| vexp '-' vexp
{
$$.hi = $1.hi - $3.lo;
$$.lo = $1.lo - $3.hi;
}
|
| dexp '-' vexp
{
$$.hi = $1 - $3.lo;
$$.lo = $1 - $3.hi;
}
| vexp '*' vexp
{
$$ = vmul($1.lo, $1.hi, $3);
}
| dexp '*' vexp
{
$$ = vmul($1, $1, $3);
}
| vexp '/' vexp
{
if (dcheck($3)) YYERROR;
$$ = vdiv($1.lo, $1.hi, $3);
}
| dexp '/' vexp
{
if (dcheck($3)) YYERROR;
$$ = vdiv($1, $1, $3);
}
| '-' vexp
{
|
$$.hi = -$2.lo; $$.lo = -$2.hi;
}
| '(' vexp ')'
{
$$ = $2;
}
;
%% /* beginning of subroutines section */
# define BSZ 50 /* buffer size for floating point number */
/* lexical analysis */
int yylex()
{
register int c;
/* skip over blanks */
while ((c=getchar()) = = ' ')
;
if (isupper(c)) {
yylval.ival = c - 'A';
return(VREG);
}
if (islower(c)) {
|
yylval.ival = c - 'a';
return(DREG);
}
/* digits, points, exponents */
if (isdigit(c) || c = = '.') {
char buf[BSZ + 1], *cp = buf;
int dot = 0, exp = 0;
for (;(cp - buf) < BSZ; ++cp, c = getchar()) {
*cp = c;
if (isdigit(c))
continue;
if (c = = '.') {
if (dot++ || exp)
return('.'); /* will cause syntax error */
continue;
}
if (c = = 'e') {
if (exp++)
return('e'); /* will cause syntax error */
continue;
}
/* end of number */
|
break;
}
*cp = '\0';
if (cp - buf >= BSZ)
(void)printf("constant too long -- truncated\n");
else
ungetc(c, stdin); /* push back last char read */
yylval.dval = atof(buf);
return(CONST);
}
return(c);
}
INTERVAL
hilo(a, b, c, d)
double a, b, c, d;
{
/* returns the smallest interval containing a, b, c, and d
used by vmul, vdiv routines */
INTERVAL v;
if (a > b){
|
v.hi = a;
v.lo = b;
}
else{
v.hi = b;
v.lo = a;
}
if (c > d) {
if (c > v.hi)
v.hi = c;
if (d < v.lo)
v.lo = d;
}
else {
if (d > v.hi)
v.hi = d;
if (c < v.lo)
v.lo = c;
}
return(v);
}
|
INTERVAL
vmul(a, b, v)
double a, b;
INTERVAL v;
{
return(hilo(a * v.hi, a * v.lo, b * v.hi, b * v.lo));
}
dcheck(v)
INTERVAL v;
{
if (v.hi >= 0. && v.lo <= 0.) {
(void) printf("divisor interval contains 0.\n");
return(1);
}
return(0);
}
INTERVAL
vdiv(a, b, v)
double a, b;
INTERVAL v;
{
return(hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo));
|
Copyright 1997 Sun Microsystems, Inc. All rights reserved.
Comments on: Programming Utilities Guide