@@ -20,6 +20,9 @@ import scala.language.implicitConversions
20
20
21
21
// TODO: better error handling (labelling like parsec's <?>)
22
22
23
+ /** An enumeration of operator associativity values: `Left`, `Right`, and
24
+ * `Non`.
25
+ */
23
26
object Associativity extends Enumeration {
24
27
type Associativity = Value
25
28
@@ -1025,18 +1028,34 @@ trait Parsers {
1025
1028
1026
1029
import Associativity ._
1027
1030
1028
- class PrecedenceParser [Exp ,Op ](primary : Parser [Exp ],
1029
- binop : Parser [Op ],
1030
- precedence : Op => Int ,
1031
- associativity : Op => Associativity ,
1032
- makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1033
- class PrecedenceSuffixParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1031
+ /** A parser that respects operator the precedence and associativity
1032
+ * conventions specified in its constructor.
1033
+ *
1034
+ * @param primary a parser that matches atomic expressions (the atomicity is
1035
+ * from the perspective of binary operators). May include
1036
+ * unary operators or parentheses.
1037
+ * @param binop a parser that matches binary operators.
1038
+ * @param precedence a function from operators to their precedence levels.
1039
+ * Operators with higher precedence values bind more
1040
+ * tightly than those with lower values.
1041
+ * @param associativity a function from operators to their associativity.
1042
+ * @param makeBinop a function that combines two operands and an operator
1043
+ * into a new expression. The result must have the same type
1044
+ * as the operands because intermediate results become
1045
+ * operands to other operators.
1046
+ */
1047
+ class PrecedenceParser [Exp ,Op ,E <: Exp ](primary : Parser [E ],
1048
+ binop : Parser [Op ],
1049
+ precedence : Op => Int ,
1050
+ associativity : Op => Associativity ,
1051
+ makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1052
+ private class ExpandLeftParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1034
1053
val opPrimary = binop ~ primary;
1035
- def parse (input : Input ): ParseResult [Exp ] = {
1054
+ def apply (input : Input ): ParseResult [Exp ] = {
1036
1055
opPrimary(input) match {
1037
1056
case Success (op ~ rhs, next) if precedence(op) >= minLevel => {
1038
- new PrecedenceRhsSuffixParser (rhs, precedence(op), minLevel)(next) match {
1039
- case Success (r, nextInput) => new PrecedenceSuffixParser (makeBinop(lhs, op, r), minLevel)(nextInput);
1057
+ new ExpandRightParser (rhs, precedence(op), minLevel)(next) match {
1058
+ case Success (r, nextInput) => new ExpandLeftParser (makeBinop(lhs, op, r), minLevel)(nextInput);
1040
1059
case ns => ns // dead code
1041
1060
}
1042
1061
}
@@ -1047,7 +1066,7 @@ trait Parsers {
1047
1066
}
1048
1067
}
1049
1068
1050
- class PrecedenceRhsSuffixParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1069
+ private class ExpandRightParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1051
1070
private def nextLevel (nextBinop : Op ): Option [Int ] = {
1052
1071
if (precedence(nextBinop) > currentLevel) {
1053
1072
Some (minLevel + 1 )
@@ -1057,14 +1076,14 @@ trait Parsers {
1057
1076
None
1058
1077
}
1059
1078
}
1060
- def parse (input : Input ): ParseResult [Exp ] = {
1079
+ def apply (input : Input ): ParseResult [Exp ] = {
1061
1080
def done : ParseResult [Exp ] = Success (rhs, input)
1062
1081
binop(input) match {
1063
1082
case Success (nextBinop,_) => {
1064
1083
nextLevel(nextBinop) match {
1065
1084
case Some (level) => {
1066
- new PrecedenceSuffixParser (rhs, level)(input) match {
1067
- case Success (r, next) => new PrecedenceRhsSuffixParser (r, currentLevel, minLevel)(next)
1085
+ new ExpandLeftParser (rhs, level)(input) match {
1086
+ case Success (r, next) => new ExpandRightParser (r, currentLevel, minLevel)(next)
1068
1087
case ns => ns // dead code
1069
1088
}
1070
1089
}
@@ -1076,10 +1095,12 @@ trait Parsers {
1076
1095
}
1077
1096
}
1078
1097
1079
- def parse (input : Input ): ParseResult [Exp ] = {
1098
+ /** Parse an expression.
1099
+ */
1100
+ def apply (input : Input ): ParseResult [Exp ] = {
1080
1101
primary(input) match {
1081
1102
case Success (lhs, next) => {
1082
- new PrecedenceSuffixParser (lhs,0 )(next)
1103
+ new ExpandLeftParser (lhs,0 )(next)
1083
1104
}
1084
1105
case noSuccess => noSuccess
1085
1106
}
0 commit comments