@@ -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
@@ -1025,18 +1028,34 @@ trait Parsers {
10251028
10261029 import Associativity ._
10271030
1028- class PrecedenceParser [Exp ,Op ](primary : Parser [Exp ],
1029- binop : Parser [Op ],
1030- precedence : Op => Int ,
1031- associativity : Op => Associativity ,
1032- makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1033- class PrecedenceSuffixParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
1031+ /** A parser that respects operator the precedence and associativity
1032+ * conventions specified in its constructor.
1033+ *
1034+ * @param primary a parser that matches atomic expressions (the atomicity is
1035+ * from the perspective of binary operators). May include
1036+ * unary operators or parentheses.
1037+ * @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.
1042+ * @param makeBinop a function that combines two operands and an operator
1043+ * into a new expression. The result must have the same type
1044+ * as the operands because intermediate results become
1045+ * operands to other operators.
1046+ */
1047+ class PrecedenceParser [Exp ,Op ,E <: Exp ](primary : Parser [E ],
1048+ binop : Parser [Op ],
1049+ precedence : Op => Int ,
1050+ associativity : Op => Associativity ,
1051+ makeBinop : (Exp , Op , Exp ) => Exp ) extends Parser [Exp ] {
1052+ private class ExpandLeftParser (lhs : Exp , minLevel : Int ) extends Parser [Exp ] {
10341053 val opPrimary = binop ~ primary;
1035- def parse (input : Input ): ParseResult [Exp ] = {
1054+ def apply (input : Input ): ParseResult [Exp ] = {
10361055 opPrimary(input) match {
10371056 case Success (op ~ rhs, next) if precedence(op) >= minLevel => {
1038- new PrecedenceRhsSuffixParser (rhs, precedence(op), minLevel)(next) match {
1039- case Success (r, nextInput) => new PrecedenceSuffixParser (makeBinop(lhs, op, r), minLevel)(nextInput);
1057+ new ExpandRightParser (rhs, precedence(op), minLevel)(next) match {
1058+ case Success (r, nextInput) => new ExpandLeftParser (makeBinop(lhs, op, r), minLevel)(nextInput);
10401059 case ns => ns // dead code
10411060 }
10421061 }
@@ -1047,7 +1066,7 @@ trait Parsers {
10471066 }
10481067 }
10491068
1050- class PrecedenceRhsSuffixParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1069+ private class ExpandRightParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
10511070 private def nextLevel (nextBinop : Op ): Option [Int ] = {
10521071 if (precedence(nextBinop) > currentLevel) {
10531072 Some (minLevel + 1 )
@@ -1057,14 +1076,14 @@ trait Parsers {
10571076 None
10581077 }
10591078 }
1060- def parse (input : Input ): ParseResult [Exp ] = {
1079+ def apply (input : Input ): ParseResult [Exp ] = {
10611080 def done : ParseResult [Exp ] = Success (rhs, input)
10621081 binop(input) match {
10631082 case Success (nextBinop,_) => {
10641083 nextLevel(nextBinop) match {
10651084 case Some (level) => {
1066- new PrecedenceSuffixParser (rhs, level)(input) match {
1067- case Success (r, next) => new PrecedenceRhsSuffixParser (r, currentLevel, minLevel)(next)
1085+ new ExpandLeftParser (rhs, level)(input) match {
1086+ case Success (r, next) => new ExpandRightParser (r, currentLevel, minLevel)(next)
10681087 case ns => ns // dead code
10691088 }
10701089 }
@@ -1076,10 +1095,12 @@ trait Parsers {
10761095 }
10771096 }
10781097
1079- def parse (input : Input ): ParseResult [Exp ] = {
1098+ /** Parse an expression.
1099+ */
1100+ def apply (input : Input ): ParseResult [Exp ] = {
10801101 primary(input) match {
10811102 case Success (lhs, next) => {
1082- new PrecedenceSuffixParser (lhs,0 )(next)
1103+ new ExpandLeftParser (lhs,0 )(next)
10831104 }
10841105 case noSuccess => noSuccess
10851106 }
0 commit comments