yacc yet another compiler compiler

Download yacc Yet Another Compiler Compiler

Post on 22-Feb-2016

38 views

Category:

Documents

0 download

Embed Size (px)

DESCRIPTION

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

TRANSCRIPT

Slide 1

yaccYet AnotherCompiler CompilerSome material adapted from slides by Andy D. PimentelLEX and YACC work as a team

How to work ?LEX and YACC work as a team

call yylex()[0-9]+next tokenis NUMNUM + NUMAvailabilitylex, yacc on most UNIX systemsbison: a yacc replacement from GNUflex: fast lexical analyzerBSD yaccWindows/MS-DOS versions existSimilar systems that work in other languages (Java, Python, etc) also exisitYACCs Basic Operational Sequencea.outFile containing desired grammar in YACC formatYACC programC source program created by YACCC compilerExecutable program that will parsegrammar given in gram.ygram.yyaccy.tab.cccor gccYACC File FormatDefinitions

%%

Rules

%%

Supplementary CodeThe identical LEX format was taken from this...Rules SectionA context free grammar, e.g.: expr : expr '+' term | term ; term : term '*' factor | factor ; factor : '(' expr ')' | ID | NUM ;Definitions section example%{#include #include %}%token ID NUM%start exprDefine token types (terminals)Define start symbol (non-terminal)Some detailsLEX 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!If you wanted to write your ownint 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;}Semantic actionsexpr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;Semantic actionsexpr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;Semantic actions (contd)expr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;$1Semantic actions (contd)expr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;$2Semantic actions (contd)expr : expr '+' term { $$ = $1 + $3; } | term { $$ = $1; } ;term : term '*' factor { $$ = $1 * $3; } | factor { $$ = $1; } ;factor : '(' expr ')' { $$ = $2; } | ID | NUM ;$3Default: $$ = $1; Precedence / Association1-2-3 = (1-2)-3? or 1-(2-3)? Define - operator is left-association.1-2*3 = 1-(2*3) Define * operator is precedent to - operator

(1) 1 2 - 3(2) 1 2 * 3Precedence / Associationexpr: 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 UMINUSPrecedence / Association%right =%left '' NE LE GE%left '+' '-%left '*' '/' highest precedencelowest precedenceGetting YACC & LEX to work togethercc/gcclex.yy.cy.tab.ca.outBuilding ExampleSuppose you have a lex file called scanner.l and a yacc file called decl.y and want parserSteps 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"YACCRules may be recursiveRules may be ambiguousUses bottom-up Shift/Reduce parsingGet a tokenPush onto stackCan it be reduced (How do we know?)If yes: Reduce using a ruleIf no: Get another tokenYACC cant look ahead > 1 tokenShift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:a = 7; b = 3 + a + 2stack:

Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:= 7; b = 3 + a + 2stack:NAMESHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:7; b = 3 + a + 2stack:NAME =SHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:; b = 3 + a + 2stack:NAME = 7SHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:; b = 3 + a + 2stack:NAME = expREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:; b = 3 + a + 2stack:stmtREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:b = 3 + a + 2stack:stmt ;SHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:= 3 + a + 2stack:stmt ; NAMESHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:3 + a + 2stack:stmt ; NAME =SHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:+ a + 2stack:stmt ; NAME = NUMBERSHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:+ a + 2stack:stmt ; NAME = expREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:a + 2stack:stmt ; NAME = exp +SHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:+ 2stack:stmt ; NAME = exp + NAMESHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:+ 2stack:stmt ; NAME = exp + expREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:+ 2stack:stmt ; NAME = expREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:2stack:stmt ; NAME = exp +SHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:

stack:stmt ; NAME = exp + NUMBERSHIFT!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:

stack:stmt ; NAME = exp + expREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:

stack:stmt ; NAME = expREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:

stack:stmt ; stmtREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:

stack:stmtREDUCE!Shift and reducingstmt: stmt ; stmt | NAME = exp

exp: exp + exp | exp - exp | NAME | NUMBERinput:

stack:stmtDONE!IF-ELSE AmbiguityConsider 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 stmtIF expr IF expr stmt . ELSE stmtIF expr stmt . ELSE stmtIF expr stmt ELSE . stmt IF expr stmt ELSE stmt .IF-ELSE AmbiguityIt is a shift/reduce conflictYACC will always do shift firstSolution 1 : re-write grammar

Solution 2:

IF-ELSE Ambiguitythe rule has the same precedence as token IFXShift/Reduce Conflictsshift/reduce conflictoccurs when a grammar is written in such a way that a decision between shifting and reducing can not be made.e.g.: IF-ELSE ambiguityTo resolve conflict, YACC will choose to shift

Reduce/Reduce ConflictsReduce/Reduce Conflicts:start : expr | stmt;expr : CONSTANT;stmt : CONSTANT;

YACC (Bison) resolves conflict by reducing using rule that is earlier in grammarNot good practice to rely on thisSo, modify grammar to eliminate themError MessagesBad error message:Syntax errorCompiler needs to give programmer a good adviceIt is better to track the line number in LEX:

Use left recursion in yaccLeft recursion

Right recursion

LR parser prefers left recursionLL parser prefers right recursionYacc is a LR parser: use left recursion

YACC Declaration Summary`%start' Specify grammar's start symbol

`%union Declare collection of data types that semantic values may have

`%token Declare terminal symbol (token type name) with no precedence or associativity specified

`%type Declare the type of semantic values for a nonterminal symbol

YACC Declaration Summary`%right Declare terminal symbol (token type name) that is right-associative

`%left Declare terminal symbol (token type name) that is left-associative

`%nonassoc Declare terminal symbol (token type name) that is nonassociativeusing it as associative is a syntax error, e.g.: x op. y op. z is syntax errorYACCyyparse()Input programs12 + 26LEXyylex()YACCyyparse()Input programs12 + 26LEXyylex()expr: expr '-' expr | expr '*' expr | expr '

Recommended

View more >