@@ -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
@@ -1016,4 +1022,67 @@ trait Parsers {
1016
1022
override def <~ [U ](p : => Parser [U ]): Parser [T ]
1017
1023
= OnceParser { (for (a <- this ; b <- commit(p)) yield a).named(" <~" ) }
1018
1024
}
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
+ }
1019
1088
}
0 commit comments