v 0.2

parser_v_0.2.zip
Compressed Archive in ZIP Format 16.8 KB

Instructions

 

> ghci Main.hs

> main

 

 

Sample input

a = b + c
       b = 1 * 2 + 3 * 4

c = 5 - 6 - 7

 

 

Sample output

Success (Node Definition
+-- Leaf (TSymbol "a")
+-- Leaf (TKeyword "=")
`-- Node FunCall
   +-- Leaf (TSymbol "+")
   +-- Leaf (TSymbol "b")
   `-- Leaf (TSymbol "c")
,[])
`-- Success (Node Definition
   +-- Leaf (TSymbol "b")
   +-- Leaf (TKeyword "=")
   `-- Node FunCall
       +-- Leaf (TSymbol "+")
       +-- Node FunCall
       |   +-- Leaf (TSymbol "*")
       |   +-- Leaf (TValue (VInt 1))
       |   `-- Leaf (TValue (VInt 2))
       `-- Node FunCall
           +-- Leaf (TSymbol "*")
           +-- Leaf (TValue (VInt 3))
           `-- Leaf (TValue (VInt 4))
   ,[])

Success (Node Definition
+-- Leaf (TSymbol "c")
+-- Leaf (TKeyword "=")
`-- Node FunCall
   +-- Leaf (TSymbol "-")
   +-- Node FunCall
   |   +-- Leaf (TSymbol "-")
   |   +-- Leaf (TValue (VInt 5))
   |   `-- Leaf (TValue (VInt 6))
   `-- Leaf (TValue (VInt 7))
,[])


Parser definition exerpt

pDefinition :: FunParser
pDefinition [] = Failure "Nothing to parse"
pDefinition toks = p_seq Definition [pSymbol, pKeyword "=", pExpr] toks

pSymbol :: FunParser
pSymbol (t:ts) = case t of
       TSymbol _ -> Success (leaf t, ts)
       otherwise -> Failure "Symbol expected."

pKeyword :: String -> FunParser
pKeyword key (t:ts) = case t of
       TKeyword k | k == key -> Success (leaf t, ts)
       otherwise    -> Failure (key ++ " expected instead of " ++ show t)
...


Remarks

  • spaces are important, they delimit the tokens
  • things like "@%*!" are valid symbols (try it!)
  • the tokenizer is fairly advanced
  • the parser looses source location information
  • straightforward to add new operators and priorities, efficient parsing ...but the code is a bit tricky