Automater, sprog og compilere De vigtige emner.
Sprog og compilere Compiler Source sprog Target sprog Programmeringsparadigme: Den stil/metode, som programmerings sproget og/eller programmøren anvender. Target sprog: Resultatet der skal kunne vidrebearbejdes af målsystemet. Mellem kode hvis det kan vidrebearbejdes af målsystemet Fx: C hvis der til målsystemet findes en C compiler. Kode til en virtuelmaskine.
Programmeringsparadigmer. Eksempler på paradigmer: Imperativ programmering - Declarativ programmering. Struktueret programmering - Ustruktueret programmering. Flow-driven programmering - Event-driven programmering. Scalar programmering - Array programmering. Objekt-orienteret programmering. Logisk programmering.
Typesystemer. Programming language static/dynamic stron/weak safety Ada static strong safe assembly none weak unsafe BASIC static weak safe C static weak unsafe C++ static strong unsafe C# static strong safe Clipper dynamic weak safe Fortran static strong safe Java static strong safe Lisp dynamic strong safe Ml static strong safe Objective-C dynamic weak safe Pascal static strong safe Perl 1-5 dynamic weak safe Perl 6 hybrid strong safe PHP dynamic strong safe
Target sprog Tre adr.instruktioner fx: Mellemkode. Res= opr1 Operation opr2 Alm CPU. MOVE src,dist Simple risc CPU. MOVWF dist SUBWF adr Stak maskine. Fx JVM Load opr1 Load opr2 Sub Out Res
Sprog og compilere Compiler Source sprog Target sprog Front end Back end Lexikalsk analyse Syntaks check Semantik check Symbol tabel
Sprog og compilere Compiler Source sprog Target sprog Front end Back end Mellemkode generering Mellemkode optimering Targetkode generering Symbol tabel
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Finde leksikalske enheder dvs enkelt ord. Definision: Regulær grammatik. Implimentation: Parallelle Finit stats automat Værktøj: Fx. Flex. Funktion: Undersøge om sproget overholder syntaksen (Struktur). Definision: Context fri grammatik. Implimentation: Predictive recursive decent eller Pushdown automat Værktøj: Fx. Bison, JavaCC.
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Checke om source programmet giver mening. Fx typecheck, navnekonvensioner og scope Definision: Source sprogets mening. Implimentation: Udstrækt brug af symboltabel. Værktøj: Ingen men struktur fra Bison.
Sprog og compilere Mellemkode generering Mellemkode optimering Targetkode generering Funktion: Repræsentation af source programmet Definision: 3 adr. Baseret koder. Parsertræ. Implimentation: Kodegenererings modul (selv programmeret). Værktøj: Ingen. Funktion: Optimer fx mht hastighed og/eller memory forbrug Definision: Standard fremgangsmåde. Implimentation: Find basic blokker. Optimer hver basic blok. Lav loop optimering. Værktøj: Ingen.
Sprog og compilere Mellemkode generering Mellemkode optimering Targetkode generering Funktion: Omsæt mellemkode til target kode. Definision: Target maskinens instruktionssæt. Implimentation: Ofte simpel omsætning fra mellem kode til targetkode. Brug af symboltabelen. Værktøj: Ingen.
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Finde leksikalske enheder dvs enkelt ord. Definision: Regulær grammatik. Implimentation: Parallelle Finit stats automat Værktøj: Fx. Flex.
Grammatik Et sprog L(G) er mængden af sætninger afledt af grammatikken G. Grammatik er en 4-tupel: G={N,S,P,S}. Hvor: N er et sæt af non-terminale symboler S er et sæt af terminale symboler P er et sæt af produktioner S er sætnings- eller startsymbolet.
a A b -> a g b A -> g A -> a A -> a B A -> B a Grammatik typer: Type 0 grammatik: Fri grammatik Type 1 grammatik: Context−sensitiv grammatik Type 2 grammatik: Context−fri grammatik Type 3 grammatik: Finit grammatik Ingen restriktioner. og enten eller a A b -> a g b A -> g A -> a A -> a B A -> B a
Regulære udtryk | : (): ? * + Alternation Grouping Quantification "gray|grey" matcher gray or grey. Grouping (): "gray|grey" og "gr(a|e)y" matcher bægge gray and grey. Quantification En quantifier efter et tegn eller gruppe af tegn angiver hvor mange gange tegnet eller gruppen skal gentages. ? 0 eller 1 gentagelser : "colou?r" matcher både color og colour. * 0 eller flere gentagelser: "go*gle" matcher ggle, gogle, google, osv. + 1 eller flere gentagelser: "go+gle" matcher gogle, google, osv.
Regulære udtryk Længste udtryk vinder. Hvis lige lange første udtryk. [a-zA-Z][a-zA-Z0-9_]* : Inentifier. [0-9]+ : Integer. if : predefinet ord. ([0-9]+|([0-9]*\.[0-9]+))([eE][-+]?[0-9]+)? : Real ”//”.*$ : C++ kommentar . : alle tegn undtagen newline. Længste udtryk vinder. Hvis lige lange første udtryk.
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Finde leksikalske enheder dvs enkelt ord. Definision: Regulær grammatik. Implimentation: Parallelle Finit stats automat Værktøj: Fx. Flex.
Endelige automater En maskine til at undersøge om en streng tilhøre et sprog L. Maskinen: Deterministic state machine (finite state automata) (Endelig automat). M=(K,T,delta,s,F) hvor: K: er et endeligt sæt af tilstande. T: er et alfabet. delta: er en funktion som afbilder en tilstand og et symbol fra T over I en ny tilstand i.e. K x T -> K s: tilhørende K er initial tilstanden. F: subsæt K er et sæt af slut tilstande. Maskinen arbejder således: Givet en streng T= a1a2a3,...ai Så vi maskinen gennemløbe en sekvens ef tilstande x0,x1,...,xi udfra følgende: x0=s (initial state) x(j+1)=delta(x(j),aj)
Endelige automater. Den rigtige metode FSM. [a-z]([a-z]|[0-9]|_)*
. . Simpel float udtryk: -?[0-9]+(\.[0-9]+)? digit digit -1.3 12.345 456 -23 s1 digit . s2 digit s3 s4 - digit . s5 s1 s2 s3 s4 s5 -------------- s5 x x x x | ’-’ x s3 x x s3| ’.’ s2 s2 s4 s4 s2| ’0’ s2 s2 s4 s4 s2| ’1’ ........... | ’2’ Slutbetingelse: FSA befinder sig i en sluttilstand og næste tegn giver X ved opslag. Fejlbetingelse: FSA befinder sig ikke i en sluttilstand
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Undersøge om sproget overholder syntaksen (Struktur). Definision: Context fri grammatik. Implimentation: Predictive recursive decent eller Pushdown automat Værktøj: Fx. Bison, JavaCC.
Context fri grammatik Grammastart -> program ( ident ) globalvar begin statementlist end ident -> letter tegenlist letter -> a | b | c | d | ........ | å | A | B | ...... | Å tegnlist -> tegn tegnlist | e tegn -> letter | digit digit -> 0 | 1 | 2 | 3 | ...... | 9 globalvar -> type identlist ; type -> char | int | float identlist -> ident | ident , identlist statementlist -> statement statementlist | e statement -> ident = exp ; exp -> exp + exp | exp - exp | exp * exp | exp / exp | (exp) | ident
Backus-Naur form <Grammastart> ::= "program" "(" <ident> ")" <globalvar> "begin" <statementlist> "end” <globalvar> ::= <type> <identlist> ";” <type> ::= "char" | "int" | "float"
EBNF En variation af BNF med nogle ekstra elementer. [..] List af alternative elementer. * En sekvens af nul eller flere elementer. + En sekvens af en eller flere elementer. (..) En gruppe af elementer. BNF: <funklist>::= <funktion> <funklist> | e EBNF: <funklist>::= (<funktion>)*
Parser træer Parsning er processen at aflede en sætning fra et startsymbol ved gentagende anvendelse af produktioner S -> AB A -> A x | y B -> z Sætning: yxxz S A B A A z y x x
Left-most : Right-most afledning Right−most parsing udfolder parsertræet fra højre. Left−most parsing udfolder parsertræet fra venstre. S -> A B Left−most Right−most
Ambiguous (flertydig) grammatik Flere parsertræer for samme sætning: S -> A A A -> x | xx Sætning: xxx S S A A A A x x x x x x Flertydig mening Ikke konsistent compiler
Samme sprog, men ikke samme grammatik Ækvivalent grammatik Samme sprog, men ikke samme grammatik L(G) = L(G’) : G: A -> A x | y G’: A -> x B B -> x B | e A A A B A x x y x B y x e Forskellig mening.
Rekursion Venstre rekursiv: A -> u | A v Fx: funklist-> funklist funktion | e Højre rekursiv: A -> u | v A Fx: funklist-> funktion funklist | e exp -> exp + exp | exp – exp | exp * exp | exp / exp Både højre og venstre rekursiv.
Rekursion: Venstre til højre Venstre rekursiv: A -> u | A v Kan omskrives til: A -> u B B -> v B | e
Precedence og flertydig grammatik exp -> exp + exp | exp – exp | exp * exp | exp / exp | ( exp ) | intT | idT Sætning: 2+3*4 exp exp exp * exp exp + exp exp + exp exp * exp intT intT intT intT intT intT 4 2 3 4 2 3
Korrekt precedence exp-> term expB expB-> termopr term expB | e termopr-> + | - term-> factor termB termB-> factoropr factor termB | e factoropr-> * | / factor-> uopr exp | ( exp ) | intT | idT uopr-> - | e
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Undersøge om sproget overholder syntaksen (Struktur). Definision: Context fri grammatik. Implimentation: Predictive recursive decent eller Pushdown automat Værktøj: Fx. Bison, JavaCC.
Parsing A Top-down A B x x y LL(1): Fx. Predictive Recursive Descent. (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.
#include <stdio.h> #include "rpd.h" #include "symtab.h" int nextT; void checkfor(int token) { if (token != nextT) { printf("Syntax Error \n "); exit(0); } else nextT = 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 -> idT bexp | ’(’ exp ’)’ bexp bexp-> ’+’ exp bexp | ’-’ exp bexp | e
rpd.c void program() { 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 -> idT bexp | ’(’ exp ’)’ bexp bexp-> ’+’ exp bexp | ’-’ exp bexp | e
rpd.c void type() { if (nextT == floatT) { nextT= yylex(); Ctype= floatT; } else { if (nextT == intT) { nextT= yylex(); Ctype= intT; } printf("Syntax Error 'int' eller 'float' type forvendtet! \n "); exit(0); }
rpd.c int main() { init_sym(); nextT = yylex(); program(); }
Venstre rekursiv statementlist -> statementlist statement | e void statementlist() { if (nextT == idT) { statementlist(); statement(); }
EBNF statement-> IdT '=' exp ';' exp-> term (('+' | '-') term)* term-> sexp (('*' | '/') sexp)* sexp-> '-' element | element element-> '(' 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 void exp() { term(); while ((nextT == ’+’)||(next == ’-’)) { exp-> term (('+' | '-') term)* void exp() { term(); while ((nextT == ’+’)||(next == ’-’)) { nextT= yylex(); }
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Underføge om sproget overholder syntaksen (Struktur). Definision: Context fri grammatik. Implimentation: Predictive recursive decent eller Pushdown automat Værktøj: Fx. Bison, JavaCC.
Parsing A A B Botton-up x x y LR(1): Fx. YACC Bottom-up (1): Kan altid afgøre hvilke vej vha. næste token.
Struktur Fo.l Fo.y lex yacc yylex() yyparse() Source kode Target kode
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.
%% 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];}
Sprog og compilere Lexikalsk analyse Syntaks check Semantik check Funktion: Checke om source programmet giver mening. Fx typecheck, navnekonvensioner og scope Definision: Source sprogets mening. Implimentation: Udstrækt brug af symboltabel. Værktøj: Ingen men struktur fra Bison.
Semantik analyse Check om brug af variable svare til typereglerne for sproget. Check procedure-kald svare til proceduren. Check om navne bliver brug i rette sammenhæng float p1(int x) { p1= x(); x= p1(2.4,3); }
Semantik analyse Brug symboltabellen: Typisk indhold: Navn Adresse Simpeltype: Funktion, char, int, float, .... Komplextype: Pointer til symboltabellen Hvis funktion så Returtype Hvis funktion så Parameterliste Brugt Tilskrevet
Sprog og compilere Mellemkode generering Mellemkode optimering Targetkode generering Funktion: Repræsentation af source programmet Definision: 3 adr. Baseret koder. Parsertræ. Implimentation: Kodegenererings modul (selv programmeret). Værktøj: Ingen. Funktion: Optimer fx mht hastighed og/eller memory forbrug Definision: Standard fremgangsmåde. Implimentation: Find basic blokker. Optimer hver basic blok. Lav loop optimering. Værktøj: Ingen.
Mellemkode. Tree-based repræsentation. Three-address koder: Mellemkode som et parsertræ. Three-address koder: A:= b + c a= 0 b= 2 l1: ifz b goto l2 a= a + b b= b – 1 goto l1 l2: int main () { int a=0,b=2; while (b) { a= a+b; b--; }
Basic blokke Blok start: Første statement Label, der hoppes til Statement efter et branch a= 0 b= 2 l1: ifz b goto l2 a= a + b b= b – 1 goto l1 l2:
Basic blok optimering. Commom sub-expression Copy propagation Samme beregning flere gange. Copy propagation Samme værdi i flere variable. Erstat alle med en. Dead-code elimination Variable, der ikke bruges, slettes. Arithmetic transform Constant folding Beregn konstanter Algebraic transform + 0, - 0, * 1 og /1 Reduction in strength Fx: 2*x -> x+x Packing af mellemvariable Frigiv overflødig plads til mellemvariable.
Loop optimering. 1 2b 3 4 5 6 2a 1 2 3 4 5 6
Kodegenerering. Globale og static variable: Når type og contekst kendes: så symnote->adr= Nextstatic; Nextstatic=+ type.VarSize; Lokal variable: Hvis første: NextLokal= 0; Ellers: symnote->adr= NextLokal; NextLokal=+ type.VarSize; a= 0 b= 2 l1: ifz b goto l2 a= a + b b= b – 1 goto l1 l2: For hver linie i mellemkode: Generer koden vha informationer fra symboltabellen. Labels: Anvendelse: Kik i symboltabellen om den er defineret ellers gem i symboltabellen, hvor den bruges. Oprettelse: symnote->adr= LC. Anvendelser: sæt referencer til symnote->adr.