@@ -1056,24 +1056,34 @@ trait Parsers {
1056
1056
* from the perspective of binary operators). May include
1057
1057
* unary operators or parentheses.
1058
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 .
1059
+ * @param prec_table a list of tuples, each of which encodes a level of
1060
+ * precedence. Precedence is encoded highest to lowest.
1061
+ * Each precedence level contains an Associativity value
1062
+ * and a list of operators .
1063
1063
* @param makeBinop a function that combines two operands and an operator
1064
1064
* into a new expression. The result must have the same type
1065
1065
* as the operands because intermediate results become
1066
1066
* operands to other operators.
1067
1067
*/
1068
1068
class PrecedenceParser [Exp ,Op ,E <: Exp ](primary : Parser [E ],
1069
1069
binop : Parser [Op ],
1070
- precedence : Op => Int ,
1071
- associativity : Op => Associativity ,
1070
+ prec_table : List [(Associativity , List [Op ])],
1072
1071
makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1072
+ private def decodePrecedence : (Map [Op , Int ], Map [Op , Associativity ]) = {
1073
+ var precedence = Map .empty[Op , Int ]
1074
+ var associativity = Map .empty[Op , Associativity ]
1075
+ var level = prec_table.length
1076
+ for ((assoc, ops) <- prec_table) {
1077
+ precedence = precedence ++ (for (op <- ops) yield (op, level))
1078
+ associativity = associativity ++ (for (op <- ops) yield (op, assoc))
1079
+ level -= 1
1080
+ }
1081
+ (precedence, associativity)
1082
+ }
1083
+ val (precedence, associativity) = decodePrecedence
1073
1084
private class ExpandLeftParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1074
- val opPrimary = binop ~ primary;
1075
1085
def apply (input : Input ): ParseResult [Exp ] = {
1076
- opPrimary (input) match {
1086
+ (binop ~ primary) (input) match {
1077
1087
case Success (op ~ rhs, next) if precedence(op) >= minLevel => {
1078
1088
new ExpandRightParser (rhs, precedence(op), minLevel)(next) match {
1079
1089
case Success (r, nextInput) => new ExpandLeftParser (makeBinop(lhs, op, r), minLevel)(nextInput);
0 commit comments