@@ -20,6 +20,9 @@ import scala.language.implicitConversions
2020
2121// TODO: better error handling (labelling like parsec's <?>)
2222
23+ /** An enumeration of operator associativity values: `Left`, `Right`, and
24+ * `Non`.
25+ */
2326object Associativity extends Enumeration {
2427 type Associativity = Value
2528
@@ -1046,18 +1049,34 @@ trait Parsers {
10461049
10471050 import Associativity ._
10481051
1049- class PrecedenceParser [Exp ,Op ](primary : Parser [Exp ],
1050- binop : Parser [Op ],
1051- precedence : Op => Int ,
1052- associativity : Op => Associativity ,
1053- makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1054- class PrecedenceSuffixParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1052+ /** A parser that respects operator the precedence and associativity
1053+ * conventions specified in its constructor.
1054+ *
1055+ * @param primary a parser that matches atomic expressions (the atomicity is
1056+ * from the perspective of binary operators). May include
1057+ * unary operators or parentheses.
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.
1063+ * @param makeBinop a function that combines two operands and an operator
1064+ * into a new expression. The result must have the same type
1065+ * as the operands because intermediate results become
1066+ * operands to other operators.
1067+ */
1068+ class PrecedenceParser [Exp ,Op ,E <: Exp ](primary : Parser [E ],
1069+ binop : Parser [Op ],
1070+ precedence : Op => Int ,
1071+ associativity : Op => Associativity ,
1072+ makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1073+ private class ExpandLeftParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
10551074 val opPrimary = binop ~ primary;
1056- def parse (input : Input ): ParseResult [Exp ] = {
1075+ def apply (input : Input ): ParseResult [Exp ] = {
10571076 opPrimary(input) match {
10581077 case Success (op ~ rhs, next) if precedence(op) >= minLevel => {
1059- new PrecedenceRhsSuffixParser (rhs, precedence(op), minLevel)(next) match {
1060- case Success (r, nextInput) => new PrecedenceSuffixParser (makeBinop(lhs, op, r), minLevel)(nextInput);
1078+ new ExpandRightParser (rhs, precedence(op), minLevel)(next) match {
1079+ case Success (r, nextInput) => new ExpandLeftParser (makeBinop(lhs, op, r), minLevel)(nextInput);
10611080 case ns => ns // dead code
10621081 }
10631082 }
@@ -1068,7 +1087,7 @@ trait Parsers {
10681087 }
10691088 }
10701089
1071- class PrecedenceRhsSuffixParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1090+ private class ExpandRightParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
10721091 private def nextLevel (nextBinop : Op ): Option [Int ] = {
10731092 if (precedence(nextBinop) > currentLevel) {
10741093 Some (minLevel + 1 )
@@ -1078,14 +1097,14 @@ trait Parsers {
10781097 None
10791098 }
10801099 }
1081- def parse (input : Input ): ParseResult [Exp ] = {
1100+ def apply (input : Input ): ParseResult [Exp ] = {
10821101 def done : ParseResult [Exp ] = Success (rhs, input)
10831102 binop(input) match {
10841103 case Success (nextBinop,_) => {
10851104 nextLevel(nextBinop) match {
10861105 case Some (level) => {
1087- new PrecedenceSuffixParser (rhs, level)(input) match {
1088- case Success (r, next) => new PrecedenceRhsSuffixParser (r, currentLevel, minLevel)(next)
1106+ new ExpandLeftParser (rhs, level)(input) match {
1107+ case Success (r, next) => new ExpandRightParser (r, currentLevel, minLevel)(next)
10891108 case ns => ns // dead code
10901109 }
10911110 }
@@ -1097,10 +1116,12 @@ trait Parsers {
10971116 }
10981117 }
10991118
1100- def parse (input : Input ): ParseResult [Exp ] = {
1119+ /** Parse an expression.
1120+ */
1121+ def apply (input : Input ): ParseResult [Exp ] = {
11011122 primary(input) match {
11021123 case Success (lhs, next) => {
1103- new PrecedenceSuffixParser (lhs,0 )(next)
1124+ new ExpandLeftParser (lhs,0 )(next)
11041125 }
11051126 case noSuccess => noSuccess
11061127 }
0 commit comments