-
Notifications
You must be signed in to change notification settings - Fork 0
/
LispParser.scala
29 lines (22 loc) · 1.29 KB
/
LispParser.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package net.parser
import org.parboiled2._
object LispParser {
val lower: String = ('a' to 'z').toList.foldRight("")(_ + _)
val upper: String = ('A' to 'Z').toList.foldRight("")(_ + _)
val numbers: String = (0 to 9).toList.map(_.toString.head.toString).mkString
}
class LispParser(val input: ParserInput) extends Parser {
import LispParser._
def SExprs: Rule1[Seq[AST.SExpr]] = rule { oneOrMore(SExpr).separatedBy(Spaces) ~ Spaces ~ EOI }
def OneSExpr: Rule1[AST.SExpr] = rule { SExpr ~ Spaces ~ EOI }
def SExpr: Rule1[AST.SExpr] = rule { Atom | '(' ~ oneOrMore(Comb).separatedBy(Spaces) ~ ')' ~> (_.toList) ~> (AST.Comb(_)) }
def Comb: Rule1[AST.SExpr] = rule { Spaces ~ SExpr ~ Spaces }
def Atom: Rule1[AST.Atom] = rule { Num | Ident }
def Num: Rule1[AST.Number] = rule { capture(Digits) ~> (_.toInt) ~> (AST.Number(_)) }
def Ident: Rule1[AST.Ident] = rule { capture(AnyString) ~> (_.toString) ~> (AST.Ident(_)) }
def AnyString = rule { ("\"" ~ StringVal ~ "\"") | StringVal}
def StringVal = rule { oneOrMore( anyOf(lower) | anyOf(upper) | anyOf(numbers) | "!") | MathOps }
def MathOps = rule { "+" | "-" | ">" | "<" | "=" }
def Digits = rule { oneOrMore(CharPredicate.Digit) }
def Spaces = rule { zeroOrMore(' ') }
}