Commit 6adfd0ff authored by matthew-eads's avatar matthew-eads
Browse files

basic portion of grammar generated

parent b2acf6af
Readme for Grammar Generator Prototype
To use the grammar generator, you must first specify the AST for your language
in an ast file (the example `Imp.ast` is provided). The syntax for these is
fairly simple and is explained below. You can then simply run the Grammar Generator
binary with the ast file as input (`./IMP < Imp.ast`). This will print out text
representing a valid input for the Happy parser generator.
Stack is used to manage packages etc. but I can't figure out how to integrate
happy and alex into stack/cabal, so there is a simple Makefile which runs happy
and alex and then hands the rest of the work to stack.
Setup and build with `stack setup`, `make`. The executable is gg-proto,
which takes the .ast file either from the command line or stdin, run with
`stack exec gg-proto file`.
`AST.y` is the grammar for the mini-language for parsing the user's AST declaration.
It reads all the grammar directives, and assembles them into a grammar that represents
a simpler, more universal AST. It should accept everything that is in the user's language,
but could potentially accept things that are not.
`Lexer.x` is the lexer for all generated grammars (the lexer for the AST language is built into `AST.y`).
It has the simple job of parsing some predefined tokens, and feeding them to the parser. It will almost
certainly need adjustments to handle things such as comments, and will likely need to be produced at some
point by the grammar generator, but for now it is sufficient.
`Imp.ast` is the example AST declaration. It is mostly a Haskell data declaration of a
modified impcore language. Lines corresponding to hard syntax are followed by the token `-->`
which is then followed by grammar directives. The possible directives are as follows:
| Operation Type | AST Syntax | Expexted impcore syntax |
|----------------|------------|-------------------------|
| Set | `--> set` | `(set x e)` |
| If | `--> if` | `(if c e1 e2)` |
| While | `--> while` | `(while c b)` |
| Begin | `--> begin` | `(begin (e1 e2 e3))`|
| Var | `--> var` | `x`
| User Defined Function | `--> userdef` | `(foo e)` |
| Integer Literal | `--> int` | `1` |
| Binary Operation | `--> binop '+'` | `(+ 1 2)` |
| Built-in Function | `--> builtin PLUS '+'` | `(+ 1 2)` |
| Custom Syntax | Not yet supported | `(arr[i])` |
##Readme for Grammar Generator Prototype Version 2
This is a much more simplified version of the original
grammar-generator prototype (which is in the mk1 branch).
#Build:
Build using `stack build` which should install all the dependencies
and use ghc to compile the source files in the src directory.
#Run:
The executable produced is `gg-mk2`, which takes a filename
as input. Running `stack exec gg-mk2 file.ast` will run the
grammar generator with the AST specified in the given file.
The file needs to be a valid Haskell file describing the
AST of your program, `src/Imp.ast` is given as an example.
The program currently will print out a portion of a yacc-like
grammar for the AST, devoid of any syntactic niceties.
......@@ -30,6 +30,35 @@ showDecT (DecT n rhs) = n ++ " [" ++ (foldr (\s a -> if a == "" then s else s ++
showRHS :: RHS -> String
showRHS (RHS n types) = n ++ " [" ++ (foldr (\s a -> if a == "" then s else s ++ ", " ++ a) "" types) ++ "] "
isUnique :: [RHS] -> RHS -> Bool
isUnique rules (RHS n types) =
foldr (\(RHS name ts) acc -> acc && (name == n ||ts /= types)) True rules
myappend :: String -> String -> String
myappend s1 s2 = s1 ++ " " ++ s2
makeNums :: Int -> Int -> String
makeNums i 0 = "}"
makeNums i n = " $"++(show (i-n+1))++(makeNums i (n-1))
rrhs :: RHS -> String
rrhs (RHS s ts) = "\t{" ++ s ++ (makeNums (length ts) (length ts))
decTToRule :: DecT -> String
decTToRule (DecT n rhs) =
let rhsToRule = \(RHS s ts) -> (if (isUnique rhs (RHS s ts))
then foldr myappend "" ts
else "\"" ++ s ++ "\" " ++ (foldr myappend "" ts))++ rrhs (RHS s ts)
rhsStrings = map rhsToRule rhs
tab = let makeTab 0 a = a
makeTab n a = makeTab (n - 1) (" " ++ a)
in makeTab (length n) ""
in n ++ ": " ++ (head rhsStrings) ++ "\n" ++
(foldr (\r acc -> tab ++ "| " ++ r ++ "\n" ++ acc) "" (tail rhsStrings))
makeRules :: [DecT] -> String
makeRules decs = foldr (\dec acc -> (decTToRule dec) ++ "\n" ++ acc) "" decs
stypeToString :: StrictType -> String
stypeToString (_, (ConT n)) = showName n
stypeToString (_, (AppT ListT t)) = (stypeToString (IsStrict, t)) ++ "*"
......@@ -41,7 +70,8 @@ parseAstDecs s = let decs = case parseDecs s of
(Left err) -> (trace err undefined)
dataDs = filter isDataD decs
dataNames = foldr (\s a -> if a == "" then s else s ++ "\n" ++ a) "" (map showDecT (map dataDToDecT dataDs))
in dataNames
rules = makeRules (map dataDToDecT dataDs)
in rules
main :: IO ()
main = do {
......
module AST where
type ID = String
data AST = Expression Exp AST
| TopLevlDec Dec AST
data Prog = Prog [AST]
data AST = Expression Exp
| TopLevlDec Dec
data Exp = SET ID Exp
| IF SimpleExp Exp Exp
| WHILE SimpleExp Exp
| BEGIN [Exp]
| SimpleExp SimpleExp
data BinOp = Plus SimpleExp SimpleExp
| Mult SimpleExp SimpleExp
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment