@@ -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
@@ -1016,4 +1022,67 @@ trait Parsers {
10161022 override def <~ [U ](p : => Parser [U ]): Parser [T ]
10171023 = OnceParser { (for (a <- this ; b <- commit(p)) yield a).named(" <~" ) }
10181024 }
1025+
1026+ import Associativity ._
1027+
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 ] {
1034+ val opPrimary = binop ~ primary;
1035+ def parse (input : Input ): ParseResult [Exp ] = {
1036+ opPrimary(input) match {
1037+ 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);
1040+ case ns => ns // dead code
1041+ }
1042+ }
1043+ case _ => {
1044+ Success (lhs, input);
1045+ }
1046+ }
1047+ }
1048+ }
1049+
1050+ class PrecedenceRhsSuffixParser (rhs : Exp , currentLevel : Int , minLevel : Int ) extends Parser [Exp ] {
1051+ private def nextLevel (nextBinop : Op ): Option [Int ] = {
1052+ if (precedence(nextBinop) > currentLevel) {
1053+ Some (minLevel + 1 )
1054+ } else if (precedence(nextBinop) == currentLevel && associativity(nextBinop) == Associativity .Right ) {
1055+ Some (minLevel)
1056+ } else {
1057+ None
1058+ }
1059+ }
1060+ def parse (input : Input ): ParseResult [Exp ] = {
1061+ def done : ParseResult [Exp ] = Success (rhs, input)
1062+ binop(input) match {
1063+ case Success (nextBinop,_) => {
1064+ nextLevel(nextBinop) match {
1065+ case Some (level) => {
1066+ new PrecedenceSuffixParser (rhs, level)(input) match {
1067+ case Success (r, next) => new PrecedenceRhsSuffixParser (r, currentLevel, minLevel)(next)
1068+ case ns => ns // dead code
1069+ }
1070+ }
1071+ case None => done
1072+ }
1073+ }
1074+ case _ => done
1075+ }
1076+ }
1077+ }
1078+
1079+ def parse (input : Input ): ParseResult [Exp ] = {
1080+ primary(input) match {
1081+ case Success (lhs, next) => {
1082+ new PrecedenceSuffixParser (lhs,0 )(next)
1083+ }
1084+ case noSuccess => noSuccess
1085+ }
1086+ }
1087+ }
10191088}
0 commit comments