Skip to content

Commit df9dd27

Browse files
committed
New interface for specifying precedence that doesn't allow mixed associativity on a level
1 parent 5a3b475 commit df9dd27

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,24 +1035,34 @@ trait Parsers {
10351035
* from the perspective of binary operators). May include
10361036
* unary operators or parentheses.
10371037
* @param binop a parser that matches binary operators.
1038-
* @param precedence a function from operators to their precedence levels.
1039-
* Operators with higher precedence values bind more
1040-
* tightly than those with lower values.
1041-
* @param associativity a function from operators to their associativity.
1038+
* @param prec_table a list of tuples, each of which encodes a level of
1039+
* precedence. Precedence is encoded highest to lowest.
1040+
* Each precedence level contains an Associativity value
1041+
* and a list of operators.
10421042
* @param makeBinop a function that combines two operands and an operator
10431043
* into a new expression. The result must have the same type
10441044
* as the operands because intermediate results become
10451045
* operands to other operators.
10461046
*/
10471047
class PrecedenceParser[Exp,Op,E <: Exp](primary: Parser[E],
10481048
binop: Parser[Op],
1049-
precedence: Op => Int,
1050-
associativity: Op => Associativity,
1049+
prec_table: List[(Associativity, List[Op])],
10511050
makeBinop: (Exp, Op, Exp) => Exp) extends Parser[Exp] {
1051+
private def decodePrecedence: (Map[Op, Int], Map[Op, Associativity]) = {
1052+
var precedence = Map.empty[Op, Int]
1053+
var associativity = Map.empty[Op, Associativity]
1054+
var level = prec_table.length
1055+
for ((assoc, ops) <- prec_table) {
1056+
precedence = precedence ++ (for (op <- ops) yield (op, level))
1057+
associativity = associativity ++ (for (op <- ops) yield (op, assoc))
1058+
level -= 1
1059+
}
1060+
(precedence, associativity)
1061+
}
1062+
val (precedence, associativity) = decodePrecedence
10521063
private class ExpandLeftParser(lhs: Exp, minLevel: Int) extends Parser[Exp] {
1053-
val opPrimary = binop ~ primary;
10541064
def apply(input: Input): ParseResult[Exp] = {
1055-
opPrimary(input) match {
1065+
(binop ~ primary)(input) match {
10561066
case Success(op ~ rhs, next) if precedence(op) >= minLevel => {
10571067
new ExpandRightParser(rhs, precedence(op), minLevel)(next) match {
10581068
case Success(r, nextInput) => new ExpandLeftParser(makeBinop(lhs, op, r), minLevel)(nextInput);

0 commit comments

Comments
 (0)