/
CharParsers.scala
97 lines (82 loc) · 2.4 KB
/
CharParsers.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package stagedparsec
import scala.lms.common._
import lms._
import lms.util._
/**
* This trait contains basic parsers for characters
* as input elements
*
* @see http://manojo.github.io/2015/09/02/staged-parser-combinators/ for more
* information.
*/
trait CharParsers
extends StagedParsers
with CharOps
with StringReaderOps {
/**
* Some primitive parsers
*/
/**
* The elementary parser. Accepts a character if it passes
* the given predicate
* NOTE: we should technically be able to write
* !in.atEnd && p(in.first)
* Because we are using a staged struct representation though,
* literally writing that would generate code from computing
* in.first *before* evaluating the atEnd part, and this can
* cause issues (IndexOutOfBounds etc.)
*/
def acceptIf(p: Rep[Elem] => Rep[Boolean]) = Parser[Elem] { in =>
conditional(
in.atEnd,
ParseResultCPS.Failure[Elem](in),
conditional(
p(in.first),
ParseResultCPS.Success(in.first, in.rest),
ParseResultCPS.Failure[Elem](in)
)
)
}
def accept(e: Rep[Elem]): Parser[Elem] = acceptIf(_ == e)
/**
* elementary recognisers. Parse a character, simply return
* the next index to be processed from
*/
def acceptIdx(e: Rep[Elem]): Parser[Int] = acceptIfIdx(_ == e)
def acceptIfIdx(p: Rep[Elem] => Rep[Boolean]) = Parser[Int] { in =>
conditional(
in.atEnd,
ParseResultCPS.Failure[Int](in),
conditional(
p(in.first),
ParseResultCPS.Success(in.offset, in.rest),
ParseResultCPS.Failure[Int](in)
)
)
}
def isLetter(c: Rep[Char]): Rep[Boolean] =
(c >= unit('a') && c <= unit('z')) ||
(c >= unit('A') && c <= unit('Z'))
def letter: Parser[Char] = acceptIf(isLetter)
def letterIdx = acceptIfIdx(isLetter)
def isDigit(c: Rep[Char]): Rep[Boolean] =
c >= unit('0') && c <= unit('9')
def digit: Parser[Char] = acceptIf(isDigit)
def digit2Int: Parser[Int] = digit map (c => (c - unit('0')).toInt)
def digitIdx = acceptIfIdx(isDigit)
}
trait CharParsersExp
extends CharParsers
with StagedParsersExp
with CharOpsExp
with StringReaderOpsExp
trait CharParsersExpOpt
extends CharParsersExp
with StagedParsersExpOpt
with StringReaderOpsExpOpt
trait ScalaGenCharParsers
extends ScalaGenStagedParsers
with ScalaGenCharOps
with ScalaGenStringReaderOps {
val IR: CharParsersExp
}