Skip to content

Commit b155896

Browse files
committed
New interface for specifying precedence that doesn't allow mixed associativity on a level
1 parent 6cc44aa commit b155896

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala

+18-8
Original file line numberDiff line numberDiff line change
@@ -1056,24 +1056,34 @@ trait Parsers {
10561056
* from the perspective of binary operators). May include
10571057
* unary operators or parentheses.
10581058
* @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.
10631063
* @param makeBinop a function that combines two operands and an operator
10641064
* into a new expression. The result must have the same type
10651065
* as the operands because intermediate results become
10661066
* operands to other operators.
10671067
*/
10681068
class PrecedenceParser[Exp,Op,E <: Exp](primary: Parser[E],
10691069
binop: Parser[Op],
1070-
precedence: Op => Int,
1071-
associativity: Op => Associativity,
1070+
prec_table: List[(Associativity, List[Op])],
10721071
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
10731084
private class ExpandLeftParser(lhs: Exp, minLevel: Int) extends Parser[Exp] {
1074-
val opPrimary = binop ~ primary;
10751085
def apply(input: Input): ParseResult[Exp] = {
1076-
opPrimary(input) match {
1086+
(binop ~ primary)(input) match {
10771087
case Success(op ~ rhs, next) if precedence(op) >= minLevel => {
10781088
new ExpandRightParser(rhs, precedence(op), minLevel)(next) match {
10791089
case Success(r, nextInput) => new ExpandLeftParser(makeBinop(lhs, op, r), minLevel)(nextInput);

0 commit comments

Comments
 (0)