Progammeringsprog. Compiler i C++

Tags:    c++

hej allesammen!

Som et lille "for-sjov" projekt er jeg gået igang med et lille programmeringssprog "Frozen Language"
Faktisk er det hele gået meget godt, og jeg har fået sat en smule semantik i, men har bare på fornemmelsen at jeg har grebet det helt forkert at.
(Vil BTW også gerne vide, om det kræver assembler viden at lave koden til en .exe)

Compiler:
Fold kodeboks ind/udKode 


example.fls
Fold kodeboks ind/udKode 




9 svar postet i denne tråd vises herunder
2 indlæg har modtaget i alt 4 karma
Sorter efter stemmer Sorter efter dato
hvis tager et eksempel program:

n := 4
a := n

old := 0

b := 1


while (a > b) and (a != old) do

begin

old := a

a := (a + b)/2

b := n/a

end




resultatet af programmet er at a vil være kvadratroden af n (jeg definerede godt nok ikke operatorerne før.

første skridt i pasningen kunne (og som regel er) at tokenize programmet, vi vil så her have følgende tokens:
ASSIGN, IF, THEN, ELSE, WHILE, DO, BEGIN, END, IDENTIFIER, EXPRESSION

tokenizer vi så vores program (evt. ekstra data angives med parantes) så får vi:
IDENTIFIER(n) ASSIGN EXPRESSION(4)
IDENTIFIER(a) ASSIGN EXPRESSION(n)
IDENTIFIER(old) ASSIGN EXPRESSION(0)
IDENTIFIER(B) ASSIGN EXPRESSION(1)
WHILE EXPRESSION((a > b) and (a != old)) DO
BEGIN
IDENTIFIER(old) ASSIGN EXPREESION(a)
IDENTIFIER(a) ASSIGN EXPRESSION((a+b)72)
IDENTIFIER(b) ASSIGN EXPRESSION(n/a)
END

kigger vi lidt på hvad de forskellige tokens svarer til i programkoden så får vi at
IF = "if"
THEN = "then"
ELSE = "else"
WHILE = "while"
DO = "do"
BEGIN = "begin"
END = "end"
disse kan så kaldes for reserverede ord

de resterende er
ASSIGN = ":="
IDENTIFIER = [a-z][a-z0-9]
EXPRESSION = ...
expression har jeg ikke fuldt defineret men jeg håber du har ideen.

vi har nu programmet parset op som en sekvens af tokens.
vi parser det nu igennem for at finde vores nonterminaler (dem der står på venstre side af vores grammatik)

hvis vi har med en assignment at gøre så har vi token mønstret IDENTIFIER ASSIGN EXPRESSION, og så er det blot at fodre vores assignment klasses konstruktør (i interpreter patternet) med ekstra dataene IDENTIFIER og EXPRESSION

Det bliver dog mere komplekst med de statements der kan indeholde andre statements, og således er rekursivt defineret, men det er dog ikke værre end det sagtens kan overkommes.

når du så med objekt referencer har fået opbygget dit syntax træ (for det er egentlig hvad det er), så siger du blot interpret, og dit script eksekveres.

her er wikipedia siden om interpreter patternet
http://en.wikipedia.org/wiki/Interpreter_pattern

og Dijkstra shunting yard (du behøves dog langtfra alt hvad den kan, kig nanvlig på muligheden for konvertering til rpn/postfix notation)
http://en.wikipedia.org/wiki/Shunting_yard_algorithm
http://en.wikipedia.org/wiki/Shunting_yard_algorithm





Hej Jakob,

Tokenize = at lave noget over til "tokens", sammenhængende abstrakte brikker som hver representerer noget. En tokenizer opdeler en længere tekst i små bider efter nogle regler som du sætter op.

Dette foretages oftest samtidig med at man opbygger et "parse træ". Hvilket er en "træ struktur" som representerer programmet.

En del af den leksikale analyse kan overstås ved at se om det er muligt og lovligt at opbygge parsetræet, og sammenholde dette med en "variabel database" som opbygges igennem parsingen.

Opgaven som jeg linkede er en 2. års opgave i Datalogi Studiet på Københavns Universitet.

Læser du fra afsnit 4. har du "opgaven". det vil i bund og grund give dig et sprog som du kan implementere.

Det er et meget "tungt" område du har begivet dig ind på. Så start med at implementere det beskrevne, derefter kan du begybnde på at definere dit eget og kigge på og forstå større eksempler.

Med venlig hilsen
Ieet




Hej Jakob

Jeg lavede for et års tid siden også nogle eksperimenter med fortolkning af et hjemmebrygget sprog, jeg havde dog en lidt anden tilgang til det.

det første jeg gjorde var at tænke over hvordan mit sprog skulle være, og formulerede en kontekst fri grammatik for det, det kunne f.eks. være:

<Script> ::= <Statement>*
<Statement> ::= <Assign>|<If>|<While>|<Block>
<Assign> ::= <Identifier> := <Expression>
<If> ::= if <Expression> then <Statement> | if <Expression> then <Statement> else <Statement>
<While> ::= while <Expression> do <Statement>
<Block> ::= begin <Statement>* end
<Identifier> ::= [a-z][a-z0-9]*
<Expression> ::= <num>|<num><Operator><num>|(Expression)

næste skridt var en parser så jeg fik opdelt alle delene i de nonterminaler der findes (expression var for mig et special tilfælde, den bliver også bare evalueret af Djikstra's shunting yard algoritme)

når det er gjort, så ligger jeg inde med et abstrakt syntax træ.

jeg lavede mit i C#, og anvendte interpreter patternet, jeg havde således en klasse for hver nonterminal, med undtagelse af identifier og expression, som jeg bare kunne sige interpret til, med et kontekst objekt som argument, kontekst objektet indeholder scriptets tilstand, dvs. her er det bare variabler og værdier.

Det mest besværlige her er at skrive parseren, så hvis du vil hurtigt igang, så kan du jo lave det som et xml sprog da du får syntax træet forærende.

I mit hjemmeprojekt havde jeg også funktioner mm. med.





[qoute]
<Script> ::= <Statement>*
<Statement> ::= <Assign>|<If>|<While>|<Block>
<Assign> ::= <Identifier> := <Expression>
<If> ::= if <Expression> then <Statement> | if <Expression> then <Statement> else <Statement>
<While> ::= while <Expression> do <Statement>
<Block> ::= begin <Statement>* end
<Identifier> ::= [a-z][a-z0-9]*
<Expression> ::= <num>|<num><Operator><num>|(Expression)
[/qoute]
Forstod ikke helt det...

Hvad er det nu en parser gør?





Hej Jakob,

Du kan jo starte med at implementere sproget beskrevet i denne her opgave:
http://www.diku.dk/undervisning/2007-2008/2007-2008_b2_ovs/G-opgave.pdf

Det vil give dig et overblik over hvordan du kan implementere dit eget senere. Opgaven er ikke baseret på C++, men kan got implementeres der.

Med venlig hilsen
Ieet







Hej Jakob,

Du kan jo starte med at implementere sproget beskrevet i denne her opgave:
http://www.diku.dk/undervisning/2007-2008/2007-2008_b2_ovs/G-opgave.pdf

Det vil give dig et overblik over hvordan du kan implementere dit eget senere. Opgaven er ikke baseret på C++, men kan got implementeres der.

Med venlig hilsen
Ieet



Implementere?

Forstod heller ikke helt linket...




Implementere?



Hmm...hvis du ikke ved hvad en parser er og hvad 'implementere' betyder, skal du nok ikke lave en compiler.

Men hvis du insisterer så kig hellere på Bison: http://www.gnu.org/software/bison/

Den klarer parsingen for dig, så er det op til dig at gøre et eller andet med resultatet.

Mht. om man behøver assembly viden for at lave exe filer, så er svaret 'det afhænger'.
Hvis DU vil lave exe behøver du ikke assembly...det er endnu værre. Du skal da kunne maskinkode og kende til PE formatet og meget mere.

Men du kan jo springe over ligesom alle andre og generere noget andet kode ud fra dit sprog. Det kunne være C/C++ eller assembly og så lader du en C compiler eller assembler oversætte videre.



Jo, kender godt ordet implementere: At udvide noget, at indsætte noget osv... :S

Det var mere det med at "tokenize" jeg ikke forstod grunden til.

Jeg tror jeg springer maskinkoden over (1000101 right?) og oversætter til C++.
Men hvordan? Hvilke forløb og processer skal der være?



Jo, kender godt ordet implementere: At udvide noget, at indsætte noget osv... :S

Det var mere det med at "tokenize" jeg ikke forstod grunden til.

Jeg tror jeg springer maskinkoden over (1000101 right?) og oversætter til C++.
Men hvordan? Hvilke forløb og processer skal der være?


Uha...det er der skrevet mange meget tykke bøger om.
Det første, du skal, er at "parse" teksten, og det er det Bison kan hjælpe dig med. Efter parsingen har du kodens struktur, og så skal du bare vælge, hvad semantikken er og oversætte det til noget tilsvarende i C/C++, som programmet så skal skrive ud.

Det er mere komplekst end at man kan beskrive det i en kort kommentar her på udvikleren, men det afhænger selvfølgelig også af, hvor komplekst dit sprog er. I ekstreme tilfælde kan 10 linjer C kode være nok til både parsing og kode generering.

Du kan evt. kigge Poul Henning Kamp lidt over skuldrene. Hans Varnish projekt bruger konfigurations filer, som bruger en syntax, han selv har fundet på, og så oversættes denne konfiguration til C kode: http://varnish.projects.linpro.no/



t