Trying to influence the parser to choose one expression match over another

Nov 20, 2013 at 2:21 PM
Edited Nov 20, 2013 at 2:22 PM
My apologies if this has been answered elsewhere. I tried searching around but didn't find an answer. I have my grammar done so that is parses properly without conflicts, but I'm trying to influence how it decides to match expressions. I have a statement like the following:
2d6+12+#18
Both + and +# are valid operators. I have a binary expression that is fairly typical. I also have what I call a threshold expression that is made up of an expression on the left and a number on the right, while the operator in the middle is either # or +#. In the above example, the parser sees the threshold expression as 12+#18, where it is then the right hand value in an addition binary operation and the 2d6 is the left. My desire is for the parser to favor parsing 2d6+12 as a binary expression that is then the left hand value in the threshold expression (essentially matching the most expansive expression possible on the left hand side of the +# operator). Is there some simple application of the PreferShiftHere() or ReduceHere() methods that accomplishes this? I'm still reading/learning about lalr parsers and there is a lot I don't yet understand. Thank you for your time.
Coordinator
Nov 20, 2013 at 4:55 PM
I think all you need to do is set appropriately the operator precedence: the value for '+' should be hire than for '+#'; just like * has higher prec than +
Nov 20, 2013 at 7:45 PM
Actually I have already set the precedence in just that fashion. I had hoped doing so would fix my problem, but it did not. I have included my rather short grammar in case it helps. Thank you by the way for building such a nice community project.
         this.Root = expression;

         binOp.Rule = ToTerm("+") | "-" | "/" | "*";

         explodeDirectiveExpr.Rule = explodeOp + number | explodeOp;
         compoundDirectiveExpr.Rule = compoundOp + number | compoundOp;
         rollOptionExpr.Rule = Empty | compoundDirectiveExpr | explodeDirectiveExpr | increasedOp;
         dieCodeExpr.Rule = dieOp + number;
         diceRollExpr.Rule = number + dieCodeExpr + rollOptionExpr;
         binModExpr.Rule = MakePlusRule(binModExpr, binOp + number);
         modDiceExpr.Rule = lbrk + diceRollExpr + binModExpr + rbrk;
         dropDiceExpr.Rule = (diceRollExpr | modDiceExpr) + (dropOp | keepOp) + number;
         highDieExpr.Rule = (diceRollExpr | modDiceExpr) + highDieOp;
         lowDieExpr.Rule = (diceRollExpr | modDiceExpr) + lowDieOp;
         complexDiceRollExpr.Rule = (diceRollExpr | modDiceExpr | dropDiceExpr | highDieExpr | lowDieExpr);
         
         targetExpr.Rule = ToTerm("#") | "+#";
         thresholdExpr.Rule = expression + targetExpr + number;      

         conditionalExpr.Rule = thresholdExpr + conditionalOp + min_opt + binOp + expression;

         parExpression.Rule = lpar + expression + rpar;
         binExpr.Rule = expression + binOp + expression;
         expression.Rule = complexDiceRollExpr | parExpression | binExpr | number | thresholdExpr | conditionalExpr;

         RegisterOperators(4, "d");
         RegisterOperators(3, "*", "/");
         RegisterOperators(2, "+", "-");
         RegisterOperators(1, "+#", "#");
Coordinator
Nov 20, 2013 at 7:56 PM
try marking binOp as transient, it might be an old bug that still sits there
Marked as answer by WiredWiz on 11/20/2013 at 1:34 PM
Nov 20, 2013 at 8:34 PM
Thank you, it looks like that solved the problem :)