bs - testa programmeringspråk

Permalänk
Medlem

bs - testa programmeringspråk

Har under en tid implementerat ett enkelt Smalltalk/Javascript/Io-likt dynamiskt, objektorienterat och prototypbaserat programmeringspråk i Java för att öva på att skriva parsers och interpretatorer. Parsern är en enkel "recursive-decent parser" med 1-look-a-head och det abstrakta syntaxträdet körs direkt. Språket kan interopera med Java och har stöd för list-literaler ([1, 2]), strängliteraler ("Hello world"), symboler (:symbol) nummer (1, 2.2 etc).

Det obligatoriska "Hello world"-programmet:

$ java -jar bs.jar >> System puts "Hello world".

Interoperabilitet (test.bs):

import("java.io.File"). f := java.io.File new ".". System puts f listFiles.

$ java -jar bs.jar test.bs [lista med="med" filer="filer"]

Det finns bara en operator, tilldelning (:=) alla andra operationer är meddelanden. Därför är "precedence"-ordningen för + - / * osv inte definierad som i exempelvis C.

Exempelvis:

$ java -jar bs.jar >> 10 * 10 + 10 200 # dsv 10 * (10 + 10)

Anledningen är att paranteser är frivilliga. Dsv

10 *(10)

är samma som

10 * 10

Detta innebär att anrop evalueras i samma ordning som med paranteser:

10 *(10 +(10))

Syntaxen (en aning inkomplett):

program ::= statements statements ::= statement { statement } statement ::= assign | expression "." assign ::= identifier := expression expression ::= symbol | call call ::= symbol [message { message }] call ::= message { message } # with parentheses message ::= identifier [ expression ["," {expression}]] message ::= identifier "(" [ expression ["," {expression}]] ")" symbol ::= identifier | number | string | list | block list ::= "[" expression ["," { expression }] "]" block ::= "{" "|" [identifier ["," {identifier}]] "|" statement { statement } "}"

Exempel fiboncci (rekursiv):

<<=(:fib, { | n | (n <= 1) ifTrue { return(n). }, { return(self fib(n - 1) + self fib(n - 2)). }. System puts fib 8. }).

* <<=: definerar en metod, med namnet :fib, och kroppen { | n | ... } som tar ett argument.
* (n <= 1): anropa metoden <= på n med argumentet 1 varpå metoden ifTrue anropas. Om n <= 1 så körs det första blocket annars det andra.
* return(): returnerar ett värde

Exempel (while-loop):

num := 0. {num <= 10.} whileTrue { System puts num. num := num + 1. }.

* {num <= 10.}: Block som methoden whileTrue anropas på. Sålänge num <= 10 körs blocket som är argument till whileTrue.

Språket stödjer "Exceptions":

e := Proto try { Error raise "Raising an error!". }. e catch Error, { | e | System puts e getMessage. }.

Objektorientering:

Person := Proto clone :Person. Person <<= :init, { | name | self <<- :name, :age. age := 10. }. Person <<= :setName, { | n | name := n. }. Person <<= :getName, { return(name). }. Person <<= :toString, { name + age toString. }. Person <<= :getAge, { age. }. p := Person clone "Hello World". System puts p getName. System puts p toString. System puts p getCode. # från Proto System puts p metodSomInteFinns. # NameError

Skapar en ny prototyp av Proto (som är rotobjektet), och lägger till några metoder (<<=).

Ladda ner och testa: https://github.com/isakkarlsson/bs/downloads
Mer information (endast påbörjad): http://isakkarlsson.github.com/bs/
Fler exempel: https://github.com/isakkarlsson/bs/

Notera att prestandan är ganska dålig (ungefär hälften av Ruby senast jag kollade).

Permalänk
Medlem

Ska nog prova det imorrn

Skickades från m.sweclockers.com

Permalänk
Medlem
Skrivet av Kejsarn:

Har under en tid implementerat ett enkelt Smalltalk/Javascript/Io-likt dynamiskt, objektorienterat och prototypbaserat programmeringspråk i Java för att öva på att skriva parsers och interpretatorer. Parsern är en enkel "recursive-decent parser" med 1-look-a-head och det abstrakta syntaxträdet körs direkt. Språket kan interopera med Java och har stöd för list-literaler ([1, 2]), strängliteraler ("Hello world"), symboler (:symbol) nummer (1, 2.2 etc).

Riktigt tufft med ett eget språk! Finns det vissa vedertagna strategier att följa om man vill försöka sig på något sådant här eller är det mest egna idéer som gått in?

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Riktigt tufft med ett eget språk! Finns det vissa vedertagna strategier att följa om man vill försöka sig på något sådant här eller är det mest egna idéer som gått in?

Det finns ganska mycket vedertagna strategier. Läs på om lexers, parsers, context-free grammars, osv. Någon bok som heter något i stil med "kompilatorkonstruktion" borde innehålla det mesta.

Permalänk
Medlem
Skrivet av Teknocide:

Riktigt tufft med ett eget språk! Finns det vissa vedertagna strategier att följa om man vill försöka sig på något sådant här eller är det mest egna idéer som gått in?

Det är inte mycket egna ideer utöver syntaxen som till stora delar är baserad på Smalltalk.

Själva implementationen består av tre traditionella steg;

  • Lexer identifierar tokens såsom nummer (förenklat [1..9]+), strängar (förenklat ".*" ), identifierare (förenklat [a-z]+) osv

  • Parser bygger ett abstrakt syntaxträd utifrån den gramatik som skapats.

  • Interpretator kör trädet

Ett exempel på hur ett simpelt träd kan se ut i ett språk skulle kunna vara:

Expr(lhs = Num(num=2), operator=+, rhs=Num(num=3))

Kan köras med (i psudo-kod):

execute(Expr n): lhs = execute(n.lhs) rhs = execute(n.rhs) op = n.operator return op(lhs, rhs) execute(Num n): return n.num

Med samma teknik kan tex:

Expr(lhs=Expr(lhs=Num(num=2), operator=+, rhs=Num(num=3)), operator=-, rhs=Num(num=2))

köras och borde ge resultatet 3.

I övrigt krävs det en semantik (dsv vad gör olika metoder/funktioner), en stack där variabler och scope hanteras mm.

Permalänk
Medlem

Eller, om man gör en Lisp-dialekt, då behöver man ingen parser. Bara en reader och en evaluator. Att inte fler har fattat att Lisp är det bästa...

Permalänk
Medlem

Lisp i alla dess former är trevligt. Gillar framförallt clojure och emacs-lisp.