320 likes | 456 Views
Leksikalsk- analyse. Syntax- analyse. Semantik- analyse. Mellemk.- optimering. Kode- generering. Kode- optimering. Parsning: Hvor er vi. If-token Ident-token. IdentX(type=Int). if viggo == 3 then. Gen(Comp, *Viggo,3) Gen(jump if not, adress).
E N D
Leksikalsk- analyse Syntax- analyse Semantik- analyse Mellemk.- optimering Kode- generering Kode- optimering Parsning: Hvor er vi If-token Ident-token ...... IdentX(type=Int) if viggo == 3 then .... Gen(Comp, *Viggo,3) Gen(jump if not, adress) - - - - - - - Front end - - - - - - - - - Mellem- kode - - - - - Compiler - - - - - - Kald til Runtimesys. - Fortolker - - - - - - - - Back end - - - - - - - - -
Top-down parsing A Top-down A B Botton-up x x y LL(1): Fx. Predictive Recursive Descent. Top-down LR(1): Fx. YACC Bottom-up (1): Kan altid afgøre hvilke vej vha. næste token.
LL(1): Predictive Recursive Descent. En procedure pr. non-terminal. Plus: Effektiv. Simpel at skrive i hånden. Minus: Ikke venstre rekursiv. Skal kunne bestemme vej udfra næste token.
LL(1)-Parser program-> ’program’ ’(’idT ’)’ varlist ’begin’ stlist ’end’ varlist-> type identlist ’;’ type-> ’float’ | ’int’ identlist-> idT identelmlist identelmlist-> ’,’idT identelmlist | e stlist-> statement stlist | e statement->idT ’=’ exp ’;’ exp->idTbexp | ’(’ exp ’)’ bexp bexp-> ’+’ exp bexp | ’-’ exp bexp | e
rpdlex.l %{ #include <string.h> #include <stdio.h> #include "symtab.h" #include "rpd.h" %} %% begin {return beginT;} end {return endT;} int {return intT;} float {return floatT;} program {return programT;} [a-zA-Z][a-zA-Z0-9]* {if ((yylval.symptr= lookup_sym(yytext)) == NULL) yylval.symptr= insert_sym(yytext); return idT;} [ \t\n] ; . {return yytext[0];} %%
rpd.h #define intT 256 #define floatT 257 #define idT 258 #define beginT 259 #define endT 260 #define realT 261 #define programT 262 void init_sym(); void program (); void varlist(); void type(); ... ... typedef union { char *string; double dval; struct symnote *symptr; } YYSTYPE; YYSTYPE yylval;
#include <stdio.h> #include "rpd.h" #include "symtab.h" int nextT; voidcheckfor(int token) { if (token != nextT) { printf("Syntax Error \n "); exit(0); } elsenextT = yylex(); }
LL(1)-Parser program-> ’program’ ’(’idT ’)’ varlist ’begin’ stlist ’end’ varlist-> type identlist ’;’ type-> ’float’ | ’int’ identlist-> idT identelmlist identelmlist-> ’,’idT identelmlist | e stlist-> statement stlist | e statement->idT ’=’ exp ’;’ exp->idTbexp | ’(’ exp ’)’ bexp bexp-> ’+’ exp bexp | ’-’ exp bexp | e
rpd.c voidprogram() { checkfor(programT); checkfor('('); checkfor(idT); checkfor(')'); varlist(); checkfor(beginT); stlist(); checkfor(endT); printf("Compilering faerdig.Ingen fejl\n "); }
LL(1)-Parser program-> ’program’ ’(’idT ’)’ varlist ’begin’ stlist ’end’ varlist-> type identlist ’;’ type-> ’float’ | ’int’ identlist-> idT identelmlist identelmlist-> ’,’idT identelmlist | e stlist-> statement stlist | e statement->idT ’=’ exp ’;’ exp->idTbexp | ’(’ exp ’)’ bexp bexp-> ’+’ exp bexp | ’-’ exp bexp | e
rpd.c voidtype() { if (nextT == floatT) { nextT= yylex(); Ctype= floatT; } else { if (nextT == intT) { nextT= yylex(); Ctype= intT; } else { printf("Syntax Error 'int' eller 'float' type forvendtet! \n "); exit(0); } } }
Ifst -> ’if’ exp ’then’ statement | ’if’ exp ’then’ statement ’else’ statement Ifst -> ’if’ exp ’then’ statement ifend Ifend -> e | ’else’ statement A -> x1...... | x2...... | x3...... . . | e Switch (nextT) { case (x1) : .... break; case (x2) : .... break; case (x3) : .... break; . . default : ; }
LL(1)-Parser program-> ’program’ ’(’idT ’)’ varlist ’begin’ stlist ’end’ varlist-> type identlist ’;’ type-> ’float’ | ’int’ identlist-> idT identelmlist identelmlist-> ’,’idT identelmlist | e stlist-> statement stlist | e statement->idT ’=’ exp ’;’ exp->idTbexp | ’(’ exp ’)’ bexp bexp-> ’+’ exp bexp | ’-’ exp bexp | e
rpd.c voididentelmlist() { if (nextT == ',') { nextT= yylex(); checkfor(idT); identelmlist(); } }
rpd.c int main() { init_sym(); nextT = yylex(); program(); }
Venstre rekursiv statementlist -> statementlist statement | e void statementlist() { if (nextT == idT) { statementlist(); statement(); } }
LL(1)-Parser statement-> idT '=' exp ';' exp-> term expBexpB-> termopr term expB | etermopr-> '+' | '-'term-> factor termBtermB-> factoropr factor termB | efactoropr-> '*' | '/'factor-> uopr exp |'(' exp ')' |idTuopr-> '-' | e
EBNF statement->IdT '=' exp';'exp-> term (('+' | '-') term)* term-> sexp (('*' | '/') sexp)*sexp-> '-' element | elementelement->'(' exp ')' | IdT statement IdT = exp ; term + term sexp A=(b + (c - c)) + a * d; sexp * sexp element element element ( exp ) IdT IdT term + term sexp sexp element element IdT ( exp ) term - term
EBNF exp-> term (('+' | '-') term)* voidexp() { term(); while ((nextT == ’+’)||(next == ’-’)) { nextT= yylex(); term(); } }
Botton-upparsning A Top-down A B Botton-up x x y LALR(1): Fx. YACC Bottom-up
Struktur Fo.l Fo.y lex yacc yylex() yyparse() Source kode Target kode
Makefile LEX= flex YACC= bison LIBS= -L/Programmer/GnuWin32/lib -ly -lfl -lm CC= gcc PROG= Fo $(PROG): $(PROG).tab.o lex.yy.o $(CC) -o $@ $(PROG).tab.o lex.yy.o $(LIBS) lex.yy.o: $(PROG).tab.h $(PROG).tab.c: $(PROG).y $(YACC) -d -v $(PROG).y lex.yy.c: $(PROG).l $(LEX) $(PROG).l
Struktur af Fo.y Erklæringer %% Grammatiske regler %% C-kode Erklæringer: %{ #include "symtab.h" #include <stdio.h> . . . %} %token name1 name2 . . .
Grammatiske regler. BNF formalisme. Både Højre og venstre rekursioner er tilladt. Ikke EBNF. Dvs ikke (..)*, (..)+ osv. Mulighed for at at styre precedence. Dvs: exp-> exp + exp | exp * exp | ..... Er OK.
Regler Type 2 produktion {C kode der udføres når hele højresiden er fundet.}; Ifst: IFT ’(’ logikvalue ’)’ statementlist {CodeGen(Ifst,$3,$5);} $$: Attributten til venstre siden af produktionen $n: Attributten til de n’te symbol på højre siden. Typen af attributten angives i definitionen af tokens. Default er typen integer.
Simpel heltalsregner regn.y %token TAL %% regner: exp {printf("= %d\n",$1);}; exp: exp '+' TAL {$$ = $1 + $3;} | TAL {$$ = $1;} |error ’+’ {printf("bad syntaks ppm");}; %% main() { yyparse(); }
Simpel heltals regner regn.l %{ #include "y.tab.h" extern int yylval; %} %% [0-9]+ {yylval = atoi(yytext); return TAL;} [ \t] ; \n return 0; . return yytext[0]; %%
%% statement_list:statement '\n' | statement_list statement '\n' ; statement: VARIABEL '=' expression {$1->value = $3;} | expression {printf("= %e\n",$1);}; expression: expression '+' expression {$$ = $1 + $3;} | expression '-' expression {$$ = $1 - $3;} | expression '*' expression {$$ = $1 * $3;} | expression '/' expression {if ($3 == 0.0) yyerror("divide dy zero"); else $$ = $1 / $3;} | '-' expression %prec UMINUS {$$ = - $2;} | '(' expression ')' {$$= $2;} | TAL {$$ = $1;} | VARIABEL {$$ = $1->value;}; %%
%{ #include <math.h> #include "symtab.h" #include <string.h> %} %union { char *string; double dval; struct symnote *symptr; } %token <symptr> VARIABEL %token <dval> TAL %token LOG EXP SQRT %left '-' '+' %left '*' '/' %right UMINUS %type<dval> expression
regn.tab.h typedef union { char *string; double dval; struct symnote *symptr; } YYSTYPE; #define VARIABEL 257 #define TAL 258 #define LOG 259 #define EXP 260 #define SQRT 261 #define UMINUS 262 extern YYSTYPE yylval;
%{ #include <string.h> #include "symtab.h" #include "regn.tab.h" %} realtal ([0-9]+|([0-9]*\.[0-9]+))([eE][-+]?[0-9]+)? variabelnavn [a-zA-Z][a-zA-Z0-9]* %% {realtal} {yylval.dval = atof(yytext); return TAL;} {variabelnavn} {if ((yylval.symptr= lookup_sym(yytext)) == NULL) yylval.symptr= insert_sym(yytext); return VARIABEL;} [ \t] ; '$' {return 0;} \n|. {return yytext[0];} %%
main() { init_sym(); yyparse(); }