Top Banner
Yacc Yet Another Compiler Compiler material adapted from slides by Andy D. Pimentel
49

Yacc Yet Another Compiler Compiler

Feb 16, 2016

Download

Documents

kiefer

Yacc Yet Another Compiler Compiler. Some material adapted from slides by Andy D. Pimentel. LEX and YACC work as a team. How to work ?. LEX and YACC work as a team. call yylex (). [0-9]+. next token is NUM. NUM ‘+’ NUM. Availability. lex , yacc on most UNIX systems - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Yacc Yet  Another Compiler  Compiler

YaccYet Another

Compiler Compiler

Some material adapted from slides by Andy D. Pimentel

Page 2: Yacc Yet  Another Compiler  Compiler

LEX and YACC work as a team

YACCyyparse()

I nput programs

12 + 26

LEXyylex()

How to work ?

Page 3: Yacc Yet  Another Compiler  Compiler

LEX and YACC work as a team

YACCyyparse()

I nput programs

12 + 26

LEXyylex()

call yylex()[0-9]+

next tokenis NUM

NUM ‘+’ NUM

Page 4: Yacc Yet  Another Compiler  Compiler

Availability

• lex, yacc on most UNIX systems• bison: a yacc replacement from

GNU• flex: fast lexical analyzer• BSD yacc• Windows/MS-DOS versions exist

Page 5: Yacc Yet  Another Compiler  Compiler

YACC’s Basic Operational Sequence

a.out

File containing desired grammar in YACC format

YACC program

C source program created by YACC

C compiler

Executable program that will parsegrammar given in gram.y

gram.y

yacc

y.tab.c

ccor gcc

Page 6: Yacc Yet  Another Compiler  Compiler

YACC File Format

Definitions

%%

Rules

%%

Supplementary Code

The identical LEX format was taken from this...

Page 7: Yacc Yet  Another Compiler  Compiler

Rules SectionA context free grammar, e.g.: expr : expr '+' term | term ; term : term '*' factor | factor ; factor : '(' expr ')' | ID | NUM ;

Page 8: Yacc Yet  Another Compiler  Compiler

Definitions section example

%{#include <stdio.h>#include <stdlib.h>%}%token ID NUM%start expr

This is called a terminal

The start symbol (non-terminal)

Page 9: Yacc Yet  Another Compiler  Compiler

Some details• LEX produces a function called yylex()• YACC produces a function called yyparse()

• yyparse() expects to be able to call yylex()

• How to get yylex()?• Write your own!

• If you don't want to write your own: use lex!

Page 10: Yacc Yet  Another Compiler  Compiler

If you wanted to write your own…int yylex(){

if(it's a num)return NUM;

else if(it's an id)return ID;

else if(parsing is done)return 0;

else if(it's an error)return -1;

}

Page 11: Yacc Yet  Another Compiler  Compiler

Semantic actionsexpr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;

Page 12: Yacc Yet  Another Compiler  Compiler

Semantic actionsexpr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;

Page 13: Yacc Yet  Another Compiler  Compiler

Semantic actions (cont’d)

expr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;

$1

Page 14: Yacc Yet  Another Compiler  Compiler

Semantic actions (cont’d)

expr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;

$2

Page 15: Yacc Yet  Another Compiler  Compiler

Semantic actions (cont’d)

expr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;

$3

Default: $$ = $1;

Page 16: Yacc Yet  Another Compiler  Compiler

Precedence / Association

1. 1-2-3 = (1-2)-3? or 1-(2-3)? Define ‘-’ operator is left-association.2. 1-2*3 = 1-(2*3) Define “*” operator is precedent to “-” operator

expr: expr '-' expr | expr '*' expr | expr '<' expr | '(' expr ')' ... ;

(1) 1 – 2 - 3

(2) 1 – 2 * 3

Page 17: Yacc Yet  Another Compiler  Compiler

Precedence / Association

expr : expr ‘+’ expr { $$ = $1 + $3; }| expr ‘-’ expr { $$ = $1 - $3; }| expr ‘*’ expr { $$ = $1 * $3; }| expr ‘/’ expr { if($3==0)yyerror(“divide 0”); else$$ = $1 / $3; }| ‘-’ expr %prec UMINUS {$$ = -$2; }

%left '+' '-'

%left '*' '/'

%noassoc UMINUS

Page 18: Yacc Yet  Another Compiler  Compiler

Precedence / Association

%right ‘=‘%left '<' '>' NE LE GE%left '+' '-‘%left '*' '/'

highest precedence

Page 19: Yacc Yet  Another Compiler  Compiler

Getting YACC & LEX to work together

cc/gcc

lex.yy.c

y.tab.c

a.out

Page 20: Yacc Yet  Another Compiler  Compiler

Building Example

• Suppose you have a lex file called scanner.l and a yacc file called decl.y and want parser

• Steps to build...lex scanner.lyacc -d decl.ygcc -c lex.yy.c y.tab.cgcc -o parser lex.yy.o y.tab.o -ll

Note: scanner should include in the definitions section: #include "y.tab.h"

Page 21: Yacc Yet  Another Compiler  Compiler

YACC• Rules may be recursive• Rules may be ambiguous• Uses bottom-up Shift/Reduce parsing– Get a token– Push onto stack– Can it be reduced (How do we know?)• If yes: Reduce using a rule• If no: Get another token

• YACC can’t look ahead > 1 token

Page 22: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:a = 7; b = 3 + a + 2

stack:<empty>

Page 23: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:= 7; b = 3 + a + 2

stack:NAME

SHIFT!

Page 24: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:7; b = 3 + a + 2

stack:NAME ‘=‘

SHIFT!

Page 25: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:; b = 3 + a + 2

stack:NAME ‘=‘ 7

SHIFT!

Page 26: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBER

input:; b = 3 + a + 2

stack:NAME ‘=‘ exp

REDUCE!

Page 27: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:; b = 3 + a + 2

stack:stmt

REDUCE!

Page 28: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:b = 3 + a + 2

stack:stmt ‘;’

SHIFT!

Page 29: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBER input:= 3 + a + 2

stack:stmt ‘;’ NAME

SHIFT!

Page 30: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:3 + a + 2

stack:stmt ‘;’ NAME ‘=‘

SHIFT!

Page 31: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:+ a + 2

stack:stmt ‘;’ NAME ‘=‘ NUMBER

SHIFT!

Page 32: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:+ a + 2

stack:stmt ‘;’ NAME ‘=‘ exp

REDUCE!

Page 33: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBER

input:a + 2

stack:stmt ‘;’ NAME ‘=‘ exp ‘+’

SHIFT!

Page 34: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:+ 2

stack:stmt ‘;’ NAME ‘=‘ exp ‘+’ NAME

SHIFT!

Page 35: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:+ 2

stack:stmt ‘;’ NAME ‘=‘ exp ‘+’ exp

REDUCE!

Page 36: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:+ 2

stack:stmt ‘;’ NAME ‘=‘ exp

REDUCE!

Page 37: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:2

stack:stmt ‘;’ NAME ‘=‘ exp ‘+’

SHIFT!

Page 38: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:<empty>

stack:stmt ‘;’ NAME ‘=‘ exp ‘+’ NUMBER

SHIFT!

Page 39: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:<empty>

stack:stmt ‘;’ NAME ‘=‘ exp ‘+’ exp

REDUCE!

Page 40: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:<empty>

stack:stmt ‘;’ NAME ‘=‘ exp

REDUCE!

Page 41: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:<empty>

stack:stmt ‘;’ stmt

REDUCE!

Page 42: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:<empty>

stack:stmt

REDUCE!

Page 43: Yacc Yet  Another Compiler  Compiler

Shift and reducing

stmt: stmt ‘;’ stmt | NAME ‘=‘ exp

exp: exp ‘+’ exp | exp ‘-’ exp | NAME

| NUMBERinput:<empty>

stack:stmt

DONE!

Page 44: Yacc Yet  Another Compiler  Compiler

IF-ELSE Ambiguity

• Consider following rule:

Following state : IF expr IF expr stmt . ELSE stmt

• Two possible derivations:

IF expr IF expr stmt . ELSE stmtIF expr IF expr stmt ELSE . stmtIF expr IF expr stmt ELSE stmt .IF expr stmt

IF expr IF expr stmt . ELSE stmtIF expr stmt . ELSE stmtIF expr stmt ELSE . stmt IF expr stmt ELSE stmt .

Page 45: Yacc Yet  Another Compiler  Compiler

IF-ELSE Ambiguity

• It is a shift/reduce conflict• YACC will always do shift first• Solution 1 : re-write grammar

stmt : matched | unmatched ;matched: other_stmt | IF expr THEN matched ELSE matched ;unmatched: IF expr THEN stmt | IF expr THEN matched ELSE unmatched ;

Page 46: Yacc Yet  Another Compiler  Compiler

• Solution 2:

IF-ELSE Ambiguity

the rule has the same precedence as token IFX

Page 47: Yacc Yet  Another Compiler  Compiler

Shift/Reduce Conflicts

• shift/reduce conflict– occurs when a grammar is written in such a

way that a decision between shifting and reducing can not be made.

– e.g.: IF-ELSE ambiguity• To resolve conflict, YACC will choose to shift

Page 48: Yacc Yet  Another Compiler  Compiler

Reduce/Reduce Conflicts• Reduce/Reduce Conflicts:

start : expr | stmt;expr : CONSTANT;stmt : CONSTANT;

• YACC (Bison) resolves conflict by reducing using rule that is earlier in grammar

• Not good practice to rely on this• So, modify grammar to eliminate them

Page 49: Yacc Yet  Another Compiler  Compiler

Use left recursion in yacc

• Left recursion

• Right recursion

• LR parser prefers left recursion• LL parser prefers right recursion• Yacc is a LR parser: use left recursion

list: item | list ',' item ;

list: item | item ',' list ;