@@ -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
@@ -1046,18 +1049,34 @@ trait Parsers {
1046
1049
1047
1050
import Associativity ._
1048
1051
1049
- class PrecedenceParser [Exp ,Op ](primary : Parser [Exp ],
1050
- binop : Parser [Op ],
1051
- precedence : Op => Int ,
1052
- associativity : Op => Associativity ,
1053
- makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1054
- class PrecedenceSuffixParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1052
+ /** A parser that respects operator the precedence and associativity
1053
+ * conventions specified in its constructor.
1054
+ *
1055
+ * @param primary a parser that matches atomic expressions (the atomicity is
1056
+ * from the perspective of binary operators). May include
1057
+ * unary operators or parentheses.
1058
+ * @param binop a parser that matches binary operators.
1059
+ * @param precedence a function from operators to their precedence levels.
1060
+ * Operators with higher precedence values bind more
1061
+ * tightly than those with lower values.
1062
+ * @param associativity a function from operators to their associativity.
1063
+ * @param makeBinop a function that combines two operands and an operator
1064
+ * into a new expression. The result must have the same type
1065
+ * as the operands because intermediate results become
1066
+ * operands to other operators.
1067
+ */
1068
+ class PrecedenceParser [Exp ,Op ,E <: Exp ](primary : Parser [E ],
1069
+ binop : Parser [Op ],
1070
+ precedence : Op => Int ,
1071
+ associativity : Op => Associativity ,
1072
+ makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1073
+ private class ExpandLeftParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1055
1074
val opPrimary = binop ~ primary;
1056
- def parse (input : Input ): ParseResult [Exp ] = {
1075
+ def apply (input : Input ): ParseResult [Exp ] = {
1057
1076
opPrimary(input) match {
1058
1077
case Success (op ~ rhs, next) if precedence(op) >= minLevel => {
1059
- new PrecedenceRhsSuffixParser (rhs, precedence(op), minLevel)(next) match {
1060
- case Success (r, nextInput) => new PrecedenceSuffixParser (makeBinop(lhs, op, r), minLevel)(nextInput);
1078
+ new ExpandRightParser (rhs, precedence(op), minLevel)(next) match {
1079
+ case Success (r, nextInput) => new ExpandLeftParser (makeBinop(lhs, op, r), minLevel)(nextInput);
1061
1080
case ns => ns // dead code
1062
1081
}
1063
1082
}
@@ -1068,7 +1087,7 @@ trait Parsers {
1068
1087
}
1069
1088
}
1070
1089
1071
- class PrecedenceRhsSuffixParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1090
+ private class ExpandRightParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1072
1091
private def nextLevel (nextBinop : Op ): Option [Int ] = {
1073
1092
if (precedence(nextBinop) > currentLevel) {
1074
1093
Some (minLevel + 1 )
@@ -1078,14 +1097,14 @@ trait Parsers {
1078
1097
None
1079
1098
}
1080
1099
}
1081
- def parse (input : Input ): ParseResult [Exp ] = {
1100
+ def apply (input : Input ): ParseResult [Exp ] = {
1082
1101
def done : ParseResult [Exp ] = Success (rhs, input)
1083
1102
binop(input) match {
1084
1103
case Success (nextBinop,_) => {
1085
1104
nextLevel(nextBinop) match {
1086
1105
case Some (level) => {
1087
- new PrecedenceSuffixParser (rhs, level)(input) match {
1088
- case Success (r, next) => new PrecedenceRhsSuffixParser (r, currentLevel, minLevel)(next)
1106
+ new ExpandLeftParser (rhs, level)(input) match {
1107
+ case Success (r, next) => new ExpandRightParser (r, currentLevel, minLevel)(next)
1089
1108
case ns => ns // dead code
1090
1109
}
1091
1110
}
@@ -1097,10 +1116,12 @@ trait Parsers {
1097
1116
}
1098
1117
}
1099
1118
1100
- def parse (input : Input ): ParseResult [Exp ] = {
1119
+ /** Parse an expression.
1120
+ */
1121
+ def apply (input : Input ): ParseResult [Exp ] = {
1101
1122
primary(input) match {
1102
1123
case Success (lhs, next) => {
1103
- new PrecedenceSuffixParser (lhs,0 )(next)
1124
+ new ExpandLeftParser (lhs,0 )(next)
1104
1125
}
1105
1126
case noSuccess => noSuccess
1106
1127
}
0 commit comments