@@ -133,6 +133,35 @@ class PackratParsersTest {
133
133
assertFailure(" end of input" , " a a a a b b b b c c c" )
134
134
}
135
135
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
+
136
165
}
137
166
138
167
private object grammars1 extends StandardTokenParsers with PackratParsers {
@@ -195,3 +224,26 @@ private object grammars3 extends StandardTokenParsers with PackratParsers {
195
224
p~ opt(repMany(p,q))~ q ^^ {case x~ Some (xs)~ y => x:: xs::: (y:: Nil )}
196
225
197
226
}
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