@@ -20,6 +20,12 @@ import scala.language.implicitConversions
20
20
21
21
// TODO: better error handling (labelling like parsec's <?>)
22
22
23
+ object Associativity extends Enumeration {
24
+ type Associativity = Value
25
+
26
+ val Left, Right, Non = Value
27
+ }
28
+
23
29
/** `Parsers` is a component that ''provides'' generic parser combinators.
24
30
*
25
31
* There are two abstract members that must be defined in order to
@@ -1037,4 +1043,67 @@ trait Parsers {
1037
1043
override def <~ [U ](p : => Parser [U ]): Parser [T ]
1038
1044
= OnceParser { (for (a <- this ; _ <- commit(p)) yield a).named(" <~" ) }
1039
1045
}
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
+ }
1040
1109
}
0 commit comments