public
Created

Happy example

  • Download Gist
gistfile1.hs
Haskell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
-- Calc.y
-- From http://www.haskell.org/happy/doc/html/sec-using.html
 
{
module Main (main) where
 
import Data.Char
}
 
%name calc
%tokentype { Token }
%error { parseError }
 
%token
let { TokenLet }
in { TokenIn }
int { TokenInt $$ }
var { TokenVar $$ }
'=' { TokenEq }
'+' { TokenPlus }
'-' { TokenMinus }
'*' { TokenTimes }
'/' { TokenDiv }
'(' { TokenOB }
')' { TokenCB }
 
%%
 
Exp :: { [(String, Int)] -> Int }
: let var '=' Exp in Exp { \p -> $6 (($2, $4 p) : p) }
| Exp1 { $1 }
 
Exp1 :: { [(String, Int)] -> Int }
: Exp1 '+' Term { \p -> $1 p + $3 p }
| Exp1 '-' Term { \p -> $1 p - $3 p }
| Term { $1 }
 
Term :: { [(String, Int)] -> Int }
: Term '*' Factor { \p -> $1 p * $3 p }
| Term '/' Factor { \p -> $1 p `div` $3 p }
| Factor { $1 }
 
Factor :: { [(String, Int)] -> Int }
: int { \p -> $1 }
| var { \p -> case lookup $1 p of
Nothing -> error "no var"
Just i -> i }
| '(' Exp ')' { $2 }
 
{
parseError :: [Token] -> a
parseError _ = error "Parse error"
 
data Token
= TokenLet
| TokenIn
| TokenInt Int
| TokenVar String
| TokenEq
| TokenPlus
| TokenMinus
| TokenTimes
| TokenDiv
| TokenOB
| TokenCB
deriving Show
 
lexer :: String -> [Token]
lexer [] = []
lexer (c:cs)
| isSpace c = lexer cs
| isAlpha c = lexVar (c:cs)
| isDigit c = lexNum (c:cs)
lexer ('=':cs) = TokenEq : lexer cs
lexer ('+':cs) = TokenPlus : lexer cs
lexer ('-':cs) = TokenMinus : lexer cs
lexer ('*':cs) = TokenTimes : lexer cs
lexer ('/':cs) = TokenDiv : lexer cs
lexer ('(':cs) = TokenOB : lexer cs
lexer (')':cs) = TokenCB : lexer cs
 
lexNum cs = TokenInt (read num) : lexer rest
where (num,rest) = span isDigit cs
 
lexVar cs =
case span isAlpha cs of
("let", rest) -> TokenLet : lexer rest
("in", rest) -> TokenIn : lexer rest
(var, rest) -> TokenVar var : lexer rest
 
main :: IO ()
main = do
cs <- getContents
print $ calc (lexer cs) []
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.