Advertisement
Guest User

Parser

a guest
Jan 19th, 2017
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module Parser where
  2.  
  3. import Data.Char
  4. import Data.Maybe
  5. import Control.Exception
  6.  
  7. import ParserM hiding (Parser)
  8. import qualified ParserM as P
  9. import AST
  10.  
  11. import State(Error)
  12. type Parser  = P.Parser Char
  13.  
  14. --
  15. -- Part I: Expressions.
  16. --
  17.  
  18. -- Variable ::= Char (Char|Digit)^*
  19. identifier :: Parser String
  20. identifier = do c<- satisfy isLetter;
  21.                 cs<- many $ satisfy isAlphaNum
  22.                 return $ c:cs
  23.  
  24. -- Number ::= Digit+ ('.' Digit+)?
  25. digitseq = many1 $ satisfy isDigit
  26. number :: Parser Double
  27. number = do
  28.   ds<- digitseq;
  29.   ds2 <- opt (do {t<- token '.'; ds<- digitseq; return $ t:ds })
  30.   return $ read $ ds ++ fromMaybe "" ds2
  31.  
  32. -- Factor ::= Identifier | Number | '(' Expr ')' | '-' Expr
  33. factor :: Parser Expr
  34. factor = fmap Var identifier +++ fmap Number number
  35.         +++ do { token '-'; e<- expr; return $ Negate e }
  36.         +++ brackets '(' expr ')'
  37.  
  38. -- Term ::= Factor '*' Term  | Factor '/' Term | Factor
  39. term :: Parser Expr
  40. term =
  41.   do { e1<- factor; token '*'; e2 <- term; return $ Times e1 e2 }
  42.   +++
  43.   do { e1<- factor; token '/'; e2 <- term; return $ Div e1 e2 }
  44.   +++ factor
  45.  
  46. -- ATerm ::= Term '+' ATerm | Term
  47. aterm :: Parser Expr
  48. aterm = do { e1<- term; token '+'; e2 <- aterm; return $ Plus e1 e2 }
  49.   +++ term
  50.  
  51. -- Expr ::= ATerm '<=' ATerm | ATerm '=' ATerm | ATerm
  52. expr :: Parser Expr
  53. expr =
  54.   do { e1<- aterm; tokens "<="; e2 <- aterm; return $ LessEq e1 e2 }
  55.   +++
  56.   do { e1<- aterm; token '='; e2 <- aterm; return $ Eq e1 e2 }
  57.   +++
  58.   do {token '<'; e1<- aterm; token ','; e2 <- aterm; token '>'; return $ Pair e1 e2 }
  59.   +++ aterm
  60.  
  61.  
  62.  
  63. --
  64. -- Part II: Commands
  65. --
  66.  
  67. -- cmd ::=
  68. cmd :: Parser Cmd
  69. cmd = choice [printStmt, whileStmt, ifStmt, assignStmt, moveStmt, lineStmt, curveStmt, circleStmt, arcStmt, colourStmt]
  70.  
  71. --         'print' expr
  72. printStmt :: Parser Cmd
  73. printStmt = do
  74.                 tokens "print"
  75.                 e<- expr
  76.                 return $ Print e
  77.  
  78. --         'move' expr
  79. moveStmt :: Parser Cmd
  80. moveStmt = do
  81.                 tokens "move"
  82.                 e<- expr
  83.                 return $ Draw (Move e)
  84.  
  85. --         'line' expr
  86. lineStmt :: Parser Cmd
  87. lineStmt = do
  88.                 tokens "line"
  89.                 e<- expr
  90.                 return $ Draw (Line e)
  91.  
  92. --         'curve' expr expr expr
  93. curveStmt :: Parser Cmd
  94. curveStmt = do
  95.                 tokens "curve"
  96.                 token '('
  97.                 e1<- expr
  98.                 token ','
  99.                 e2<- expr
  100.                 token ','
  101.                 e3<- expr
  102.                 token ')'
  103.                 return $ Draw (Curve e1 e2 e3)
  104.  
  105. --         'circle' expr
  106. circleStmt :: Parser Cmd
  107. circleStmt = do
  108.                 tokens "circle"
  109.                 e<- expr
  110.                 return $ Draw (Circle e)
  111.  
  112. --         'arc' expr
  113. arcStmt :: Parser Cmd
  114. arcStmt = do
  115.                 tokens "arc"
  116.                 token '('
  117.                 e1<- expr
  118.                 token ','
  119.                 e2<- expr
  120.                 token ','
  121.                 e3<- expr
  122.                 token ')'
  123.                 return $ Draw (Arc e1 e2 e3)
  124.  
  125. --         'colour' identifier
  126. colourStmt :: Parser Cmd
  127. colourStmt = do
  128.                 tokens "colour"
  129.                 id<- identifier
  130.                 return $ Draw (Color id)
  131.  
  132. --       | 'while' expr brcmdseq
  133. whileStmt :: Parser Cmd
  134. whileStmt = do
  135.   tokens "while"; e<- expr; cs <- brCmdSeq;
  136.   return $ While e cs
  137.  
  138. --       | 'if' expr brcmdSeq ['else' brcmdseq]
  139. ifStmt :: Parser Cmd
  140. ifStmt = do
  141.   tokens "if"; e<- expr; cs <- brCmdSeq
  142.   ds <- opt (do { tokens "else"; brCmdSeq })
  143.   return $ If e cs (fromMaybe [] ds)
  144.  
  145. --       | identifier ':=' expr
  146. assignStmt :: Parser Cmd
  147. assignStmt =
  148.    do { id <- identifier; tokens ":="; e<- expr; return $ Assign id e }
  149.  
  150. --  brcmdseq ::= '{' cmds '}'
  151. --  cmds     ::= cmd ';' cmds | cmd
  152. brCmdSeq :: Parser [Cmd]
  153. brCmdSeq = brackets '{' (sepby1 cmd ';') '}'
  154.  
  155.  
  156. program :: Parser Prog
  157. program =
  158.   do
  159.     tokens "tsvg"
  160.     id    <- identifier
  161.     num   <- opt (do
  162.                     token '('
  163.                     x<- number
  164.                     token ','
  165.                     y<- number
  166.                     token ')'
  167.                     return (x,y))
  168.     token ';'
  169.     decls <- many (do
  170.                      tokens "var"
  171.                      id<- identifier
  172.                      token ';'
  173.                      return id)
  174.     cmds  <- sepby cmd ';'
  175.     return $ Tsvg id (fromMaybe (1000, 1000) num) decls cmds
  176.   +++
  177.   do
  178.     decls <- many (do
  179.                      tokens "var"
  180.                      id<- identifier
  181.                      token ';'
  182.                      return id)
  183.     cmds  <- sepby cmd ';'
  184.     return $ Prog decls cmds
  185.  
  186.  
  187. --
  188. -- Part III: Main function
  189. --
  190. parseMain :: String -> Error Prog
  191. parseMain inp = case parse program (filter (not.isSpace) inp) of
  192.     [(st, [])] -> Right st
  193.     [(st, r)]  -> Left $ "Parse error on input '" ++ [head r]
  194.         ++ "' (" ++ show (length inp - length r) ++ ")"++ "Rest: "++ tail r
  195.     _ -> Left $ "Parse error (no parse)"
  196.  
  197. parseFromFile :: String-> IO (Error Prog)
  198. parseFromFile filenm =
  199.   catch (do cont<- readFile filenm
  200.             return $ parseMain cont)
  201.         (\e-> return $ Left $ "I/O error: "++ show (e :: IOError))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement