@@ -20,6 +20,12 @@ import scala.language.implicitConversions
2020
2121// TODO: better error handling (labelling like parsec's <?>)
2222
23+ object Associativity extends Enumeration {
24+ type Associativity = Value
25+
26+ val Left, Right, Non = Value
27+ }
28+
2329/** `Parsers` is a component that ''provides'' generic parser combinators.
2430 *
2531 * There are two abstract members that must be defined in order to
@@ -1037,4 +1043,67 @@ trait Parsers {
10371043 override def <~ [U ](p : => Parser [U ]): Parser [T ]
10381044 = OnceParser { (for (a <- this ; _ <- commit(p)) yield a).named(" <~" ) }
10391045 }
1046+
1047+ import Associativity ._
1048+
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 ] {
1055+ val opPrimary = binop ~ primary;
1056+ def parse (input : Input ): ParseResult [Exp ] = {
1057+ opPrimary(input) match {
1058+ 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);
1061+ case ns => ns // dead code
1062+ }
1063+ }
1064+ case _ => {
1065+ Success (lhs, input);
1066+ }
1067+ }
1068+ }
1069+ }
1070+
1071+ class PrecedenceRhsSuffixParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1072+ private def nextLevel (nextBinop : Op ): Option [Int ] = {
1073+ if (precedence(nextBinop) > currentLevel) {
1074+ Some (minLevel + 1 )
1075+ } else if (precedence(nextBinop) == currentLevel && associativity(nextBinop) == Associativity .Right ) {
1076+ Some (minLevel)
1077+ } else {
1078+ None
1079+ }
1080+ }
1081+ def parse (input : Input ): ParseResult [Exp ] = {
1082+ def done : ParseResult [Exp ] = Success (rhs, input)
1083+ binop(input) match {
1084+ case Success (nextBinop,_) => {
1085+ nextLevel(nextBinop) match {
1086+ case Some (level) => {
1087+ new PrecedenceSuffixParser (rhs, level)(input) match {
1088+ case Success (r, next) => new PrecedenceRhsSuffixParser (r, currentLevel, minLevel)(next)
1089+ case ns => ns // dead code
1090+ }
1091+ }
1092+ case None => done
1093+ }
1094+ }
1095+ case _ => done
1096+ }
1097+ }
1098+ }
1099+
1100+ def parse (input : Input ): ParseResult [Exp ] = {
1101+ primary(input) match {
1102+ case Success (lhs, next) => {
1103+ new PrecedenceSuffixParser (lhs,0 )(next)
1104+ }
1105+ case noSuccess => noSuccess
1106+ }
1107+ }
1108+ }
10401109}
0 commit comments