added another example using the combinator parsers, courtesy of Miles Sabin (slightly simplified/adapted to new combinators)
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@12358 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
fa3eae402e
commit
75bed0903b
|
@ -0,0 +1,34 @@
|
|||
package examples.parsing.lambda
|
||||
|
||||
import scala.util.parsing.combinator.Parsers
|
||||
import scala.util.parsing.input.StreamReader
|
||||
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStreamReader
|
||||
|
||||
/**
|
||||
* Parser for an untyped lambda calculus
|
||||
*
|
||||
* Usage: scala examples.parsing.lambda.Main <file>
|
||||
*
|
||||
* (example files: see test/*.kwi)
|
||||
*
|
||||
* @author Miles Sabin (adapted slightly by Adriaan Moors)
|
||||
*/
|
||||
object Main extends Application with TestParser
|
||||
{
|
||||
override def main(args: Array[String]) =
|
||||
{
|
||||
val in = StreamReader(new InputStreamReader(new FileInputStream(new File(args(0))), "ISO-8859-1"))
|
||||
parse(in) match
|
||||
{
|
||||
case Success(term, _) =>
|
||||
{
|
||||
Console.println("Term: \n"+term)
|
||||
}
|
||||
case Failure(msg, remainder) => Console.println("Failure: "+msg+"\n"+"Remainder: \n"+remainder.pos.longString)
|
||||
case Error(msg, remainder) => Console.println("Error: "+msg+"\n"+"Remainder: \n"+remainder.pos.longString)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
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))
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package examples.parsing.lambda
|
||||
|
||||
/**
|
||||
* Parser for an untyped lambda calculus: abstract syntax tree
|
||||
*
|
||||
* @author Miles Sabin (adapted slightly by Adriaan Moors)
|
||||
*/
|
||||
trait TestSyntax
|
||||
{
|
||||
trait Term
|
||||
|
||||
case class Unit extends Term
|
||||
{
|
||||
override def toString = "unit"
|
||||
}
|
||||
|
||||
case class Lit(n: int) extends Term
|
||||
{
|
||||
override def toString = n.toString
|
||||
}
|
||||
|
||||
case class Bool(b: boolean) extends Term
|
||||
{
|
||||
override def toString = b.toString
|
||||
}
|
||||
|
||||
case class Name(name: String) extends Term
|
||||
{
|
||||
override def toString = name
|
||||
}
|
||||
|
||||
case class Ref(n: Name) extends Term
|
||||
{
|
||||
def value = n
|
||||
}
|
||||
|
||||
case class Lam(n: Name, l: Term) extends Term
|
||||
{
|
||||
override def toString = "(\\ "+n+" -> "+l+")"
|
||||
}
|
||||
|
||||
case class App(t1: Term, t2: Term) extends Term
|
||||
{
|
||||
override def toString = "("+t1+" "+t2+")"
|
||||
}
|
||||
|
||||
case class Let(n: Name, t1: Term, t2: Term) extends Term
|
||||
{
|
||||
override def toString = "let "+n+" = "+t1+" in "+t2
|
||||
}
|
||||
|
||||
case class If(c: Term, t1: Term, t2: Term) extends Term
|
||||
{
|
||||
override def toString = "if "+c+" then "+t1+" else "+t2
|
||||
}
|
||||
|
||||
trait PrimTerm extends Term
|
||||
{
|
||||
def apply(n: Lit) : Term
|
||||
}
|
||||
|
||||
case class PrimPlus extends PrimTerm
|
||||
{
|
||||
def apply(x: Lit) = new PrimTerm { def apply(y: Lit) = Lit(x.n+y.n) }
|
||||
}
|
||||
|
||||
case class PrimMinus extends PrimTerm
|
||||
{
|
||||
def apply(x: Lit) = new PrimTerm { def apply(y: Lit) = Lit(x.n-y.n) }
|
||||
}
|
||||
|
||||
case class PrimMultiply extends PrimTerm
|
||||
{
|
||||
def apply(x: Lit) = new PrimTerm { def apply(y: Lit) = Lit(x.n*y.n) }
|
||||
}
|
||||
|
||||
case class PrimDivide extends PrimTerm
|
||||
{
|
||||
def apply(x: Lit) = new PrimTerm { def apply(y: Lit) = Lit(x.n/y.n) }
|
||||
}
|
||||
|
||||
case class PrimEquals extends PrimTerm
|
||||
{
|
||||
def apply(x: Lit) = new PrimTerm { def apply(y: Lit) = Bool(x.n == y.n) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
let x = 23 in (\y z -> x+y+z) 1 2
|
|
@ -0,0 +1 @@
|
|||
let f = (\x y -> x*y) in f 2 3
|
|
@ -0,0 +1 @@
|
|||
let f = (\x y -> x*y) in f (f 1 2) 3
|
|
@ -0,0 +1 @@
|
|||
let fact = \x -> if x == 0 then 1 else x*(fact (x-1)) in unit
|
|
@ -0,0 +1 @@
|
|||
let fact = \x -> if x == 0 then 1 else x*(fact (x-1)) in fact 6
|
|
@ -0,0 +1 @@
|
|||
2*3+4*5 == 26
|
|
@ -0,0 +1 @@
|
|||
let fix = \f -> f(fix f) in unit
|
|
@ -0,0 +1 @@
|
|||
let fix = (\f -> f(fix f)) in (fix (\g n -> if n == 0 then 1 else n*(g(n-1)))) 5
|
Loading…
Reference in New Issue