module Parser (parse) where
import Ast
import BasicNumber
import Lexer
import Op
-- parse string to ast
parse :: String -> Ast
parse str = if succ then parser lexeme
else SyntaxError
where
(lexeme, succ) = lexer str
-- parse lexeme list to ast
parser :: [Lexeme] -> Ast
parser lexeme = if rest == [] then ast else SyntaxError
where (ast,rest) = parse_command lexeme
-- parse a lexeme list, return an ast and the rest of the lexeme list
parse_command :: [Lexeme] -> (Ast, [Lexeme])
parse_command [] = (NullCmd,[])
parse_command ((Evar evar):(Op "="):bexpr) =
case bexpr of
[] -> (NullCmd,[])
(Op "'"):bexpr1 -> ((Set evar ast), rest)
where (ast,rest) = parse_bexpr bexpr1
_ -> ((EvalSet evar ast), rest)
where (ast,rest) = parse_bexpr bexpr
parse_command bexpr = ((Eval ast), rest)
where
(ast,rest) = parse_bexpr bexpr
-- parse an expression
parse_bexpr :: [Lexeme] -> (BasicExp, [Lexeme])
parse_bexpr [] = (BSError, [])
parse_bexpr expr = parse_prec 7 expr
parse_prec :: Int -> [Lexeme] -> (BasicExp, [Lexeme])
-- we are now in front of an expression
parse_prec prec rest =
if prec == 0 then parse_bexpr3 rest
else
case rest of
((Op op):rs) -> if opname == "" then (BSError,rest)
else parse_op_acum prec sofar r
where
(t,r) = parse_prec ((opPrec1 op)-1) rs
sofar = Func opname [t]
opname = opName1 op
_ -> parse_op_acum prec t r
where
(t,r) = parse_prec (prec-1) rest
where
parse_op_acum prec sofar r =
case r of
((Op op):rs) -> if prec >= opPrec op then
let
(s1,r1) = parse_op op sofar rs
in parse_op_acum prec s1 r1
else (sofar,r)
_ -> (sofar,r)
-- in front of an operator
parse_op :: String -> BasicExp -> [Lexeme] -> (BasicExp, [Lexeme])
parse_op op sofar rest =
if opname == "" then (BSError, rest)
else
if opAssoc op == "right" then
let (t2,r2) = parse_prec (opPrec op) rest
in ((Func opname [sofar,t2]), r2)
else if opAssoc op == "left" then
parse_left op sofar rest
else
parse_non op sofar rest
where opname = opName op
-- parse operators with no fixity
parse_non :: String -> BasicExp -> [Lexeme] -> (BasicExp, [Lexeme])
parse_non op sofar rest =
((Func (opName op) [sofar,t2]), r2)
where
(t2,r2) = parse_prec ((opPrec op)-1) rest
-- parsing left-associative operators
parse_left :: String -> BasicExp -> [Lexeme] -> (BasicExp, [Lexeme])
parse_left op sofar rest =
case r1 of
((Op nop):rs) ->
if (opPrec op) == (opPrec nop) then
parse_left nop nsofar rs
else
(nsofar,r1)
-- parse_op nop (Func (opName op) [sofar,t1]) rs
_ -> (nsofar,r1)
where
(t1,r1) = parse_prec ((opPrec op)-1) rest
nsofar = Func (opName op) [sofar,t1]
-- atomic expression
parse_bexpr3 :: [Lexeme] -> (BasicExp, [Lexeme])
parse_bexpr3 ((Evar evar):rest) = ((EVar evar), rest)
parse_bexpr3 ((Ide var):Lparen:rest) =
if succ then ((Func var args), r)
else (BSError,r)
where
(args,r,succ) = parse_arglist [] rest
parse_bexpr3 ((Ide var):rest) = ((Var var), rest)
parse_bexpr3 ((Num num):rest) = ((Numb (read num)), rest)
parse_bexpr3 (Lparen:rest) = case r1 of
(Rparen:r2) -> (exp,r2)
_ -> (BSError,r1)
where
(exp,r1) = parse_bexpr rest
parse_bexpr3 x = (BSError,x)
-- parse argument list
parse_arglist :: [BasicExp] -> [Lexeme] -> ([BasicExp], [Lexeme], Bool)
parse_arglist acum (Rparen:x) = (acum, x, True)
parse_arglist acum x = case r1 of
(Comma:rs) -> parse_arglist (acum++[arg]) rs
(Rparen:rs) -> (acum++[arg],rs,True)
_ -> ([],[],False)
where
(arg,r1) = parse_bexpr x
|