@@ -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 afunction 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 alist 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);