@@ -14,6 +14,7 @@ package scala
14
14
package util .parsing .combinator
15
15
16
16
import scala .util .parsing .input ._
17
+ import scala .util .{Either ,Left ,Right }
17
18
import scala .collection .mutable .ListBuffer
18
19
import scala .annotation .tailrec
19
20
import scala .language .implicitConversions
@@ -1047,8 +1048,6 @@ trait Parsers {
1047
1048
= OnceParser { (for (a <- this ; _ <- commit(p)) yield a).named(" <~" ) }
1048
1049
}
1049
1050
1050
- import Associativity ._
1051
-
1052
1051
/** A parser that respects operator the precedence and associativity
1053
1052
* conventions specified in its constructor.
1054
1053
*
@@ -1067,62 +1066,65 @@ trait Parsers {
1067
1066
*/
1068
1067
class PrecedenceParser [Exp ,Op ,E <: Exp ](primary : Parser [E ],
1069
1068
binop : Parser [Op ],
1070
- prec_table : List [(Associativity , List [Op ])],
1069
+ prec_table : List [(Associativity . Associativity , List [Op ])],
1071
1070
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)
1071
+ val empty = Map .empty [Op , ( Int , Associativity . Associativity )];
1072
+ val opData = prec_table.reverse.zipWithIndex.foldLeft( empty)({
1073
+ (map, data) =>
1074
+ val ((assoc, ops), index) = data;
1075
+ val bindings = for (op <- ops) yield (op, (index + 1 , assoc));
1076
+ map ++ bindings
1077
+ } )
1078
+ def precedence ( op : Op ) : Int = {
1079
+ val (level, _) = opData(op);
1080
+ level
1082
1081
}
1083
- val (precedence, associativity) = decodePrecedence
1084
- private class ExpandLeftParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1085
- def apply (input : Input ): ParseResult [Exp ] = {
1086
- (binop ~ primary)(input) match {
1087
- case Success (op ~ rhs, next) if precedence(op) >= minLevel => {
1088
- new ExpandRightParser (rhs, precedence(op), minLevel)(next) match {
1089
- case Success (r, nextInput) => new ExpandLeftParser (makeBinop(lhs, op, r), minLevel)(nextInput);
1090
- case ns => ns // dead code
1082
+
1083
+ type Expansion = Either [Success [Exp ], Success [Exp ]];
1084
+
1085
+ private def expandRight (rhs : Exp , input : Reader [Elem ], current : Int ): Expansion = {
1086
+ binop(input) match {
1087
+ case Success (op, _) => {
1088
+ val nextLevel = opData(op) match {
1089
+ case (l, _) if l > current => Some (current + 1 )
1090
+ case (l, Associativity .Right ) if l == current => Some (current)
1091
+ case _ => None
1092
+ };
1093
+ nextLevel match {
1094
+ case Some (nl) => {
1095
+ expandLeft(rhs, input, nl) match {
1096
+ case Right (Success (r, rnext)) => expandRight(r, rnext, current)
1097
+ case result => result
1098
+ }
1091
1099
}
1092
- }
1093
- case _ => {
1094
- Success (lhs, input);
1100
+ case None => Right (Success (rhs, input))
1095
1101
}
1096
1102
}
1103
+ case _ => Left (Success (rhs, input))
1097
1104
}
1098
1105
}
1099
1106
1100
- private class ExpandRightParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1101
- private def nextLevel (nextBinop : Op ): Option [Int ] = {
1102
- if (precedence(nextBinop) > currentLevel) {
1103
- Some (minLevel + 1 )
1104
- } else if (precedence(nextBinop) == currentLevel && associativity(nextBinop) == Associativity .Right ) {
1105
- Some (minLevel)
1106
- } else {
1107
- None
1108
- }
1109
- }
1110
- def apply (input : Input ): ParseResult [Exp ] = {
1111
- def done : ParseResult [Exp ] = Success (rhs, input)
1112
- binop(input) match {
1113
- case Success (nextBinop,_) => {
1114
- nextLevel(nextBinop) match {
1115
- case Some (level) => {
1116
- new ExpandLeftParser (rhs, level)(input) match {
1117
- case Success (r, next) => new ExpandRightParser (r, currentLevel, minLevel)(next)
1118
- case ns => ns // dead code
1107
+ private def expandLeft (lhs : Exp , input : Reader [Elem ], minLevel : Int ): Expansion = {
1108
+ binop(input) match {
1109
+ case Success (op, binInput) => {
1110
+ val prec = precedence(op);
1111
+ if (prec >= minLevel) {
1112
+ primary(binInput) match {
1113
+ case Success (rhs, next) => {
1114
+ expandRight(rhs, next, prec) match {
1115
+ case Right (Success (r, rnext)) => {
1116
+ expandLeft(makeBinop(lhs, op, r), rnext, minLevel)
1117
+ }
1118
+ case Left (Success (r, rnext)) => Left (Success (makeBinop(lhs, op, r), rnext))
1119
1119
}
1120
1120
}
1121
- case None => done
1121
+ case _ => Left ( Success (lhs, input))
1122
1122
}
1123
+ } else {
1124
+ Left (Success (lhs, input))
1123
1125
}
1124
- case _ => done
1125
1126
}
1127
+ case _ => Left (Success (lhs, input))
1126
1128
}
1127
1129
}
1128
1130
@@ -1131,7 +1133,10 @@ trait Parsers {
1131
1133
def apply (input : Input ): ParseResult [Exp ] = {
1132
1134
primary(input) match {
1133
1135
case Success (lhs, next) => {
1134
- new ExpandLeftParser (lhs,0 )(next)
1136
+ expandLeft(lhs, next, 0 ) match {
1137
+ case Left (result) => result
1138
+ case Right (result) => result
1139
+ }
1135
1140
}
1136
1141
case noSuccess => noSuccess
1137
1142
}
0 commit comments