22
Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć alata: sličnost sa interpreterom 1

Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Embed Size (px)

Citation preview

Page 1: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Pravljenje sintaksnog analizatora

Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć alata: sličnost sa interpreterom

1

Page 2: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Sintaksni analizator sa rekurzivnim spuštanjem (recursive-descent)

Ima po jednu (međurekurzivnu) funkciju za svaki neterminal (sintaksnu klasu) Unutar svake funkcije switch po vrsti ulaznog simbola

sa po jednom case klauzulom za svaku produkciju

Sinonim: analiza sa predviđanjem (predictive)Ograničenje: Radi dobro samo ako prvi terminalni simbol u svakom

pod izrazu jednoznačno određuje produkciju Ako to nije slučaj, postoji konflikt

2

Page 3: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer1 (1/3)Specifikacija gramatike

Napraviti sintaksni analizator sa rekurzivnim spuštanjem za zadatu gramatiku Neterminalni simboli: S, E, L

Defišu dozvoljene iskaze i izraze u jeziku

Terminali: let, in, begin, print, end, “;”, “=” Ključne reči, punktoatori i operatori u jeziku

3

S let E in S L endS begin S L L ; S LS print E E num = num

Page 4: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer1 (2/3)Program

4

S let E in S L endS begin S L L ; S LS print E E num = num

enum token {LET, IN, BEGIN, END, PRINT, SEMI, NUM, EQ};extern enum token getToken();

enum token tok;void advance() {tok=getToken();}void eat(enum token t) {if(tok==t) advance(); else error();}

void S(void) {switch(tok) {case LET: eat(LET); E(); eat(IN); S(); break;case BEGIN: eat(BEGIN); S(); L(); break;case PRINT: eat(PRINT); E(); break;default: error();

}}

Page 5: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer1 (3/3)Program

5

S let E in S L endS begin S L L ; S LS print E E num = num

void L(void) {switch(tok) {case END: eat(END); break;case SEMI: eat(SEMI); S(); L(); break;default: error();

}}void E(void) {eat(NUM); eat(EQ); eat(NUM);

}

Page 6: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer sa konfliktima

Gramatika sa konfliktima Tada je potrebno odrediti skupove FIRST i FOLLOW Za niz terminala i neterminala , skup FIRST čine svi

terminali kojima započinju simboli razvijeni iz Npr. za = {T * F}, FIRST() = {id, num, (}

Simbol X je poništiv (nullable) ako se iz njega može razviti prazan niz

Skup FOLLOW(X) je skup terminala koji u rečenicama jezika mogu pratiti X 6

S E $E E + T T T * F F idE E - T T T / F F numE T T F F ( E )

Page 7: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Algoritam za određivanjeFIRST, FOLLOW i NULLABLE

7

Initialize FIRST and FOLLOW to empty sets, and nullable to all false.for each terminal symbol ZFIRST[Z] = {Z}

repeatfor each production X Y1 Y2 ... Ykfor each i from 1 to k, each j from i+1 to kif all the Yi are nullablethen nullable[X] ← true

if Y1 ... Yi-1 are all nullablethen FIRST[X] ← FIRST[X] U FIRST[Yi]

if Yi+1 ... Yk are all nullablethen FOLLOW[Yi] ← FOLLOW[Yi] U FOLLOW[X]

if Yi+1 ... Yj-1 are all nullablethen FOLLOW[Yi] ← FOLLOW[Yi] U FOLLOW[Yj]

until FIRST, FOLLOW, and nullable did not change in this iteration.

Page 8: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Eliminisanje leve rekurzije

8

Opšte pravilo za prepisivanje regularnih izraza sa levom rekurzijom u izraze sa desnom rekurzijom Primenjeno na posmatrani primer

Početni skup produkcija

Rezultat transformacije

X X 1X X 2X 1X 2

X 1 X’X 2 X’X’ 1 X’X’ 2 X’X’

S E $E T E’ T F T’E’ + T E’ T’ * F T’ F idE’ - T E’ T’ / F T’ F numE’ T’ F ( E )

Jezik nakon transformacije:

Page 9: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Sadržaji skupova

9

Simbol nullable FIRST FOLLOWS false ( id numE false ( id num ) $E' true + - ) $T false ( id num ) + - $T' true * / ) + - $F false ( id num ) * / + - $

Pored transformacije jezika, potrebno je odrediti sadržaje skupova Za svaki neterminal: nullable, FIRST i FOLLOW

Page 10: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Interpreter sa rekurzivnimspuštanjem (1/2)

10

enum token {EOF, ID, NUM, PLUS, MINUS, ...};union tokenval {string id; int num; ...};enum token tok;union tokenval tokval;int lookup(string id) {...}int F_follow[] = {RPAREN, TIMES, DIVIDE, PLUS, MINUS, EOF, -1};int F(void) {switch(tok) {case ID: {int i=lookup(tokval.id); advance(); return i;}case NUM: {int i=tokval.num; advance(); return i;}case LPAREN: eat(LPAREN); { int i = E();

eatOrSkipTo(RPAREN, F_follow);return i; }

case EOF:default: printf(“Expected ID, NUM, or (“);

skipto(F_follow); return 0;}

}

F idF numF ( E )

Page 11: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Interpreter sa rekurzivnimspuštanjem (2/2)

11

int T_follow[] = {RPAREN, PLUS, MINUS, EOF, -1};int T(void) {switch(tok) {case ID: case NUM: case LPAREN: return Tprime(F());default: printf(“Expected ID, NUM, or (“);

skipto(T_follow); return 0;}

}int Tprime(int a) {switch(tok) {case TIMES: eat(TIMES); return(a*F());case RPAREN: case PLUS: case MINUS: case EOF: return a;default: ...

}}void eatOrSkipTo(int expected, int *stop) {if(tok==expected) eat(expected);else {printf(...); skipto(stop);}

}

T F T’T’ * F T’T’ / F T’T’

Originalne produkcije:T T * FT T / FT FT se prenosi kroz a

Page 12: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Napomene uz prethodni C kod Semantika

Simboli ID i NUM nose vrednosti tipa sting i int Podrazumeva se postojanje tabele

Koja preslikava ID-ove na NUM-ove (cele brojeve)

Tip pridružen neterminalima E, T, F, itd. je int Semantičke akcije se lako realizuju

Problem: Semantička akcija za veštački simbol T’ Npr. u produkciji T’*FT’ nedostaje levi operand za * Jedan način je da se levi operand prosledi kao argument

Funkcija T ga uzima sa F() i prosleđuje funkciji Tprime

Razvoj simbola u prazan string se prepoznaje pojavom nekog od simbola iz skupa FOLLOW

12

Page 13: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Odnos interpretera i sintaksnog analizatora

Postoji velika sličnost između njihAko se koristi Yacc, razlikuju se samo akcije Interpreter: akcije dovode do direktnog izvršenja

Npr. Iskaz dodele vrednosti zaista upisuje vrednost u promenljivu

Iskaz štampanja (print) sadržaja promenljive ga zaista prikazuje na monitoru, itd.

Sintaksni analizator: akcije izgrađuju stablo apstraktne sintakse dodavanjem novih čvorova To stablo će kasnije u nizu transformacija biti prevedeno u

mašinski kod Tek pri njegovom izvršenje dobijaju se rezultati

13

Page 14: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Gramatika pravolinijskih programaSLP interpreter i sintaksni analizator za SLP Gramatika SLP zadata donjim nizom produkcija

Preuzimanjem struktura iz ručno pisanog SLP interpretera, dolazi se do Yacc specifikacija U slučaju sintaksnog analizatora te strukture

podataka predstavljaju apstraktnu sintaksu

14

S S ; S E id L ES id := E E num L L ES print L E E B E

E S , E B + | - | * | /

Page 15: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer:Specifikacija SLP interpretera (1/2)

15

%{#include "table.h"extern table tab;%}

%union {int ival; string sval;}%token <sval> ID%token <ival> INT%token ASSIGN PRINT LPAREN RPAREN%type <ival> exp

%right SEMICOLON%left MINUS PLUS%left TIMES DIVIDE%start prog

%%prog: stm

Page 16: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer:Specifikacija SLP interpretera (2/2)

16

stm: stm SEMICOLON stmstm: ID ASSIGN exp {update(&tab, $1, $3);}stm: PRINT LPAREN exps RPAREN {printf("\n");}

exps: exp {printf("%d ", $1);}exps: exps COMMA exp {printf("%d ", $3);}

exp: INT {$$ = $1;}exp: ID {$$ = lookup(tab, $1);}exp: exp PLUS exp {$$ = $1 + $3;}exp: exp MINUS exp {$$ = $1 - $3;}exp: exp TIMES exp {$$ = $1 * $3;}exp: exp DIVIDE exp {$$ = $1 / $3;}exp: stm COMMA exp {$$ = $3;}exp: LPAREN exp RPAREN {$$ = $2;}

// $1, $2, itd. se odnose na definicione članove produkcije

Page 17: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer: Specifikacija SLP sinatksnog analizatora (1/2)

17

%{extern A_stm rootprg;%}

%union {int num; string id; A_stm stm; A_exp exp; A_expList expList;}%token <num> INT%token <id> ID%token ASSIGN PRINT LPAREN RPAREN%type <stm> stm prog%type <exp> exp%type <expList> exps%left SEMICOLON%left MINUS PLUS%left TIMES DIVIDE%start prog

%%prog: stm {$$=$1; rootprg=$1;}

Page 18: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer: Specifikacija SLP sinatksnog analizatora (2/2)

18

stm: stm SEMICOLON stm {$$=A_CompoundStm($1,$3);}stm: ID ASSIGN exp {$$=A_AssignStm($1,$3);}stm: PRINT LPAREN exps RPAREN {$$=A_PrintStm($3);}

exps: exp {$$=A_LastExpList($1);}exps: exp COMMA exps {$$=A_PairExpList($1,$3);}

exp: INT {$$=A_NumExp($1);}exp: ID {$$=A_IdExp($1);}exp: exp PLUS exp {$$=A_OpExp($1,A_plus,$3);}exp: exp MINUS exp {$$=A_OpExp($1,A_minus,$3);}exp: exp TIMES exp {$$=$$=A_OpExp($1,A_times,$3);}exp: exp DIVIDE exp {$$=$$=A_OpExp($1,A_div,$3);}exp: stm COMMA exp {$$=A_EseqExp($1,$3);}exp: LPAREN exp RPAREN {$$=$2;}

Page 19: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Apstraktna sintaksa za tiger (1/2)

19

/* Function Prototypes */A_var A_SimpleVar(A_pos pos, S_symbol sym);A_var A_FieldVar(A_pos pos, A_var var, S_symbol sym);A_var A_SubscriptVar(A_pos pos, A_var var, A_exp exp);A_exp A_VarExp(A_pos pos, A_var var);A_exp A_NilExp(A_pos pos);A_exp A_IntExp(A_pos pos, int i);A_exp A_StringExp(A_pos pos, string s);A_exp A_CallExp(A_pos pos, S_symbol func, A_expList args);A_exp A_OpExp(A_pos pos, A_oper oper, A_exp left, A_exp right);A_exp A_RecordExp(A_pos pos, S_symbol typ, A_efieldList fields);A_exp A_SeqExp(A_pos pos, A_expList seq);A_exp A_AssignExp(A_pos pos, A_var var, A_exp exp);A_exp A_IfExp(A_pos pos, A_exp test, A_exp then, A_exp elsee);A_exp A_WhileExp(A_pos pos, A_exp test, A_exp body);A_exp A_ForExp(A_pos pos, S_symbol var, A_exp lo, A_exp hi, A_exp body);A_exp A_BreakExp(A_pos pos);A_exp A_LetExp(A_pos pos, A_decList decs, A_exp body);A_exp A_ArrayExp(A_pos pos, S_symbol typ, A_exp size, A_exp init);

Page 20: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Apstraktna sintaksa za tiger (2/2)

20

A_dec A_FunctionDec(A_pos pos, A_fundecList function);A_dec A_VarDec(A_pos pos, S_symbol var, S_symbol typ, A_exp init);A_dec A_TypeDec(A_pos pos, A_nametyList type);A_ty A_NameTy(A_pos pos, S_symbol name);A_ty A_RecordTy(A_pos pos, A_fieldList record);A_ty A_ArrayTy(A_pos pos, S_symbol array);A_field A_Field(A_pos pos, S_symbol name, S_symbol typ);A_fieldList A_FieldList(A_field head, A_fieldList tail);A_expList A_ExpList(A_exp head, A_expList tail);A_fundec A_Fundec(A_pos pos, S_symbol name, A_fieldList params,

S_symbol result,A_exp body);A_fundecList A_FundecList(A_fundec head, A_fundecList tail);A_decList A_DecList(A_dec head, A_decList tail);A_namety A_Namety(S_symbol name, A_ty ty);A_nametyList A_NametyList(A_namety head, A_nametyList tail);A_efield A_Efield(S_symbol name, A_exp exp);A_efieldList A_EfieldList(A_efield head, A_efieldList tail);

Page 21: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Yacc specifikacija za tiger

21

exp: lvalue {$$=A_VarExp(EM_tokPos,$1);}| NIL {$$=A_NilExp(EM_tokPos);}| INT {$$=A_IntExp(EM_tokPos,$1);}| STRING {$$=A_StringExp(EM_tokPos,$1);}| NEG INT

{$$=A_OpExp(EM_tokPos,A_minusOp,A_IntExp(EM_tokPos,1),A_IntExp(EM_tokPos,$2));}

| functioncall {$$=$1;}| arithmetic {$$=$1;}| comparison {$$=$1;}| booleanexp {$$=$1;}| recordcreation {$$=$1;}| arraycreation {$$=$1;}

;lvalue: ID {$$=A_SimpleVar(EM_tokPos,S_Symbol($1));}

| lvalue DOT ID {$$=A_FieldVar(EM_tokPos,$1,S_Symbol($3));}| ID LBRACK exp RBRACK {$$=A_SubscriptVar(EM_tokPos,

A_SimpleVar(EM_tokPos, S_Symbol($1)),$3);};...

Page 22: Ručno: analizator sa rekurzivnim spuštanjem Uz pomoć … Pravljenje SIA.pdf · Pravljenje sintaksnog analizatora Sintaksni analizator Ručno: analizator sa rekurzivnim spuštanjem

Primer stabla sintaksne analizeProgram queens

22

...\tigerc.exe

..\testcases\queens_book.tigParsing successful!

letExp(decList(functionDec(fundecList(fundec(try,fieldList(field(c,int,TRUE),

fieldList()),iffExp(opExp(EQUAL,varExp(simpleVar(c)),

varExp(simpleVar(N))),

callExp(printboard,expList()),

forExp(r,intExp(0),opExp(MINUS,varExp(simpleVar(N)),

intExp(1)),iffExp(iffExp(iffExp(opExp(EQUAL,varExp(subscriptVar(simpleVar(row),varExp(simpleVar(r)))),

intExp(0)),