Documente Academic
Documente Profesional
Documente Cultură
Gabriele Stockunaite
19.12.2016
Language Engineering
INTRODUCTION
Then you represent the target language as another such type. Finally the compiler is
really a function from the source type to the target type and the translations are easy to
write and later read. Optimizations are also regular functions that map, say, the target
language to the target language.
This is why functional languages with lightweight syntax and a strong type system are
considered a good option at creating compilers.
Shallow embedding: All Haskell operations immediately translate to the target language.
E.g. the Haskell expression a+b is translated to a String like "a + b” containing that target
language expression.
Deep embedding:
Haskell operations only build an interim Haskell data structure that reflects the
expression tree. E.g. the Haskell expression A+b is translated to the Haskell data
1
structure Add (Var "a") (Var "b"). This structure allows transformations like
optimizations before translating to the target language.
As a drummer I have used jfugue to java code simple melodies and rithms so I decided to
make it more approachable so that you could only write : PLAY A, B and it would
generate all the java code.
2
oneOf :: [a] -> Parser Char
`Monad`: these concepts generalise to all kinds of other applications. The copiler is
based on the example provided in Bristol Tiny Basic code.
RESULTS
import Text.Megaparsec
import Text.Megaparsec.String
data Line = Cmnd Cmnd | Stmt Stmt | Line Int Stmt
data Cmnd = CLEAR | LIST | RUN | BEGIN | FINISH
| PLAYNOTES [Note]
| PLAYSOUNDS Mexpr
| RETURN
| RYTHM Number
data Chord = maj | minor | aug | dim
3
type Note = Char
type Sound = Note | Note Dur | Note Chord | Note Chord Dur
4
<|> LET <$ tok "LET" <*> var <* tok "=" <*> expr
args = sepBy1 ((Left <$> str) <|> (Right <$> expr)) (tok ",")
str = tok "\"" *> some (noneOf ("\n\r\"")) <* tok "\""
expr = Expr <$> ((POS <$ tok "+") <|> (NEG <$ tok "-") <|> pure POS)
mexpr = Mexpr <$> ((PIANO <$ tok "Piano") <|> (VIOLIN <$ tok "Violin") <|> (FLUTE <$ tok
"Flute"))
<*> sounds
5
sounds = sepBy1 sound (tok ",")
<|> ((W <$ tok "w") <|> (H <$ tok "h") <|> (Q <$ tok "q")) <*> note
<|> ((W <$ tok "w") <|> (H <$ tok "h") <|> (Q <$ tok "q")) <*> note <*> chord
note = oneOf ['A', 'B', 'C', 'D' ,'E' , 'F', 'G' ] <* whitespace
number = (some (oneOf ['0' .. '9']) >>= return . read) <* whitespace
6
parseFile :: FilePath -> IO ()
Then the actual translation becomes easy when we have all the language parsed for example
begining the code.
REFERENCES
https://www.reddit.com/r/haskell/comments/21x8br/tutorial_for_building_a_compiler_in_
haskell/
https://wiki.haskell.org/Embedded_domain_specific_language
http://augustss.blogspot.co.uk/search/label/BASIC
http://dev.stephendiehl.com/fun/
https://en.wikipedia.org/wiki/Domain-specific_language
7
https://www.reddit.com/r/haskell/comments/2e8d53/whats_the_best_practice_for_buildin
g_a_dsl_in/
https://wiki.haskell.org/Parsing_a_simple_imperative_language
8