package examples.parsing.lambda import scala.util.parsing.input.Reader import scala.util.parsing.combinator.lexical.StdLexical import scala.util.parsing.combinator.syntactical.StdTokenParsers import scala.util.parsing.combinator.ImplicitConversions /** * Parser for an untyped lambda calculus * * @author Miles Sabin (adapted slightly by Adriaan Moors) */ trait TestParser extends StdTokenParsers with ImplicitConversions with TestSyntax { type Tokens = StdLexical val lexical = new StdLexical lexical.reserved ++= List("unit", "let", "in", "if", "then", "else") lexical.delimiters ++= List("=>", "->", "==", "(", ")", "=", "\\", "+", "-", "*", "/") def name : Parser[Name] = ident ^^ Name // meaning of the argumens to the closure during subsequent iterations // (...(expr2 op1 expr1) ... op1 expr1) // ^a^^^ ^o^ ^b^^^ // ^^^^^^^a^^^^^^^ ^o^ ^^b^^ def expr1 : Parser[Term] = chainl1(expr2, expr1, op1 ^^ {o => (a: Term, b: Term) => App(App(o, a), b)}) def expr2 : Parser[Term] = chainl1(expr3, expr2, op2 ^^ {o => (a: Term, b: Term) => App(App(o, a), b)}) def expr3 : Parser[Term] = chainl1(expr4, expr3, op3 ^^ {o => (a: Term, b: Term) => App(App(o, a), b)}) def expr4 : Parser[Term] = ( "\\" ~ lambdas | "let" ~ name ~ "=" ~ expr1 ~ "in" ~ expr1 ^^ flatten3(Let) | "if" ~ expr1 ~ "then" ~ expr1 ~ "else" ~ expr1 ^^ flatten3(If) | chainl1(aexpr, success(App(_: Term, _: Term))) ) def lambdas : Parser[Term] = name ~ ("->" ~ expr1 | lambdas) ^^ flatten2(Lam) def aexpr : Parser[Term] = ( numericLit ^^ (_.toInt) ^^ Lit | name ^^ Ref | "unit" ^^ Unit | "(" ~ expr1 ~ ")" ) def op1 : Parser[Term] = "==" ^^ Ref(Name("==")) def op2 : Parser[Term] = ( "+" ^^ Ref(Name("+")) | "-" ^^ Ref(Name("-")) ) def op3 : Parser[Term] = ( "*" ^^ Ref(Name("*")) | "/" ^^ Ref(Name("/")) ) def parse(r: Reader[char]) : ParseResult[Term] = phrase(expr1)(new lexical.Scanner(r)) }