(* Allows more print depth. *) Compiler.Control.Print.printDepth:= 100; datatype arithExp = AST_ID of string | AST_NUM of int | AST_NEG of arithExp | AST_PLUS of arithExp * arithExp | AST_MINUS of arithExp * arithExp | AST_PRODUCT of arithExp * arithExp | AST_QUOTIENT of arithExp * arithExp | AST_ERROR of string; datatype token = ID of string | NUM of int | Plus | Minus | Mult | Div | Neg | LParen | RParen | EOF; signature PCFPARSER = sig val parse : token list -> arithExp end structure PCFparser : PCFPARSER = struct (* Output an error message *) fun error (msg:string) = print msg (* Parses an expression. If an expression is found, returns a tuple containing the ast for the expression and the input following the expression. If an expression is not found, it returns an error and consumes all remaining input. *) (* Expression -> Term TermTail *) fun parseExpression ((ID v)::tl) = parseTermTail(parseTerm((ID v)::tl)) | parseExpression ((NUM n)::tl) = parseTermTail(parseTerm((NUM n)::tl)) | parseExpression (LParen::tl) = parseTermTail(parseTerm(LParen::tl)) | parseExpression (Neg::tl) = parseTermTail(parseTerm(Neg::tl)) (* error cases *) | parseExpression [EOF] = (error "Unexpected end of input\n"; (AST_ERROR "Unexpected end of input", nil)) | parseExpression _ = (error "Fatal error\n"; (AST_ERROR "Fatal error", nil)) (* Parses a term. If a term is found, returns a tuple containing the ast for the term and the input following the factor. If a term is not found, it returns an error and consumes all remaining input. *) (* Term -> Factor FactorTail *) and parseTerm ((ID v)::tl) = parseFactorTail(parseFactor((ID v)::tl)) | parseTerm ((NUM n)::tl) = parseFactorTail(parseFactor((NUM n)::tl)) | parseTerm (LParen::tl) = parseFactorTail(parseFactor(LParen::tl)) | parseTerm (Neg::tl) = parseFactorTail(parseFactor(Neg::tl)) (* error cases *) | parseTerm [EOF] = (error "Unexpected end of input\n"; (AST_ERROR "Unexpected end of input", nil)) | parseTerm _ = (error "Fatal error\n"; (AST_ERROR "Fatal error", nil)) (* Parses a factor. If a factor is found, returns a tuple containing the ast for the factor and the input following the factor. If a factor is not found, it returns an error and consumes all remaining input. *) (* Factor -> Id | Num | ~ Factor | ( Expression ) *) and parseFactor ((ID v)::rest) = (AST_ID v,rest) | parseFactor ((NUM n)::rest) = (AST_NUM n,rest) | parseFactor (Neg::others) = let val (fact,rest) = parseFactor others in (AST_NEG fact,rest) end | parseFactor (LParen::rest) = let val (eTree,rest2) = parseExpression rest in if hd rest2 = RParen then (eTree,tl rest2) else (error "no closing parenthesis\n"; (AST_ERROR "no closing parenthesis",nil)) end (* error cases *) | parseFactor [EOF] = (error "Unexpected end of input\n"; (AST_ERROR "Unexpected end of input", nil)) | parseFactor _ = (error "Fatal error\n"; (AST_ERROR "Fatal error", nil)) (* Parses the tail of a term. If a term is found, returns a tuple containing the ast for the term and the input following the factor. If a term is not found, it returns an error and consumes all remaining input. *) (* TermTail -> { AddOp Term TermTail } *) and parseTermTail (left, Plus::others) = let val (right,rest) = parseTerm others in parseTermTail(AST_PLUS (left,right), rest) end | parseTermTail (left, Minus::others) = let val (right,rest) = parseTerm others in parseTermTail(AST_MINUS (left,right), rest) end | parseTermTail (term, RParen::others) = (term, RParen::others) | parseTermTail (term, EOF::others) = (term, EOF::others) (* error cases *) | parseTermTail _ = (error "Fatal error\n"; (AST_ERROR "Fatal error", nil)) (* Parses the tail of a factor. If a factor is found, returns a tuple containing the ast for the factor and the input following the factor. If a term is not found, it returns an error and consumes all remaining input. *) (* FactorTail -> { MultOP Factor FactorTail } *) and parseFactorTail (left, Mult::others) = let val (right,rest) = parseTerm others in parseFactorTail(AST_PRODUCT(left,right), rest) end | parseFactorTail (left, Div::others) = let val (right,rest) = parseTerm others in parseFactorTail(AST_QUOTIENT (left,right), rest) end (* Legal tokens to follow TermTail *) | parseFactorTail (term, Plus::others) = (term, Plus::others) | parseFactorTail (term, Minus::others) = (term, Minus::others) | parseFactorTail (term, RParen::others) = (term, RParen::others) | parseFactorTail (term, EOF::others) = (term, EOF::others) (* error cases *) | parseFactorTail _ = (error "Fatal error\n"; (AST_ERROR "Fatal error", nil)) (* Return an AST for the list of tokens passed in. *) fun parse tokens = let val (ast1, rest) = parseExpression tokens in if rest = [EOF] orelse rest = nil then ast1 else (error "Fatal error -- more input than expected.\n"; AST_ERROR "More input than expected.") end end; (* of structure PCFParser *) (* #CheckMatch Debug := true; -- put back in if run on Mac *) (* The final definition of the function puts the pieces together. *) fun parsefile str = PCFparser.parse (PCFlexer.lex str); fun parsestr str = PCFparser.parse (PCFlexer.lexstr str)