@@ -133,6 +133,35 @@ class PackratParsersTest {
133133 assertFailure(" end of input" , " a a a a b b b b c c c" )
134134 }
135135
136+ @ Test
137+ def test4 : Unit = {
138+ import grammars4 ._
139+ import grammars4 .parser ._
140+
141+ def extractResult (r : ParseResult [Res ]): Res = r match {
142+ case Success (a,_) => a
143+ case NoSuccess (a,_) => sys.error(a)
144+ case Failure (a, _) => sys.error(a)
145+ case Error (a, _) => sys.error(a)
146+ }
147+ def check (expected : Term , input : String , ctx : Ctx ): Unit = {
148+ val parseResult = phraseTerm(new lexical.Scanner (input))
149+ val result = extractResult(parseResult)
150+ val term = result(ctx)
151+ assertEquals(expected, term)
152+ }
153+
154+ check(Var (- 1 , 0 ), " x" , Nil )
155+ check(Var (0 , 3 ), " x" , List (" x" , " y" , " z" ))
156+ check(Var (1 , 3 ), " y" , List (" x" , " y" , " z" ))
157+ check(Var (2 , 3 ), " z" , List (" x" , " y" , " z" ))
158+
159+ check(App (Var (0 , 2 ), Var (1 , 2 )), " x y" , List (" x" , " y" ))
160+ check(App (App (Var (0 , 2 ), Var (1 , 2 )), Var (0 , 2 )), " x y x" , List (" x" , " y" ))
161+ check(App (App (Var (0 , 2 ), Var (1 , 2 )), Var (0 , 2 )), " (x y) x" , List (" x" , " y" ))
162+ check(Abs (App (App (Var (0 , 1 ), Var (0 , 1 )), Var (0 , 1 ))), """ \x. x x x""" , List ())
163+ }
164+
136165}
137166
138167private object grammars1 extends StandardTokenParsers with PackratParsers {
@@ -195,3 +224,26 @@ private object grammars3 extends StandardTokenParsers with PackratParsers {
195224 p~ opt(repMany(p,q))~ q ^^ {case x~ Some (xs)~ y => x:: xs::: (y:: Nil )}
196225
197226}
227+
228+ private object grammars4 {
229+ // untyped lambda calculus with named vars -> de brujin indices conversion on the fly
230+ // Adapted from https://github.com/ilya-klyuchnikov/tapl-scala/blob/master/src/main/scala/tapl/untyped/parser.scala
231+ sealed trait Term
232+ case class Var (i : Int , cl : Int ) extends Term
233+ case class Abs (t : Term ) extends Term
234+ case class App (t1 : Term , t2 : Term ) extends Term
235+
236+ object parser extends StandardTokenParsers with PackratParsers {
237+ lexical.delimiters ++= List (" (" , " )" , " ." , " \\ " )
238+
239+ type Res = Ctx => Term
240+ type Ctx = List [String ]
241+
242+ private val term : PackratParser [Res ] = app | atom | abs
243+ private val atom : PackratParser [Res ] = " (" ~> term <~ " )" | id
244+ private val id : PackratParser [Res ] = ident ^^ { n => (c : Ctx ) => Var (c.indexOf(n), c.length) }
245+ private val app : PackratParser [Res ] = (app ~ atom) ^^ {case t1 ~ t2 => (c : Ctx ) => App (t1(c), t2(c)) } | atom
246+ private val abs : PackratParser [Res ] = " \\ " ~> ident ~ (" ." ~> term) ^^ {case v ~ t => (c : Ctx ) => Abs (t(v:: c))}
247+ val phraseTerm : PackratParser [Res ] = phrase(term)
248+ }
249+ }
0 commit comments