Shift reduce problem - again :) - example included

Oct 15, 2012 at 6:41 AM

Hi,

First off - love Irony.NET, pretty cool :)

I'm having issue with "shift reduct conflict" with the following rules setup:


Expressions.Rule =          MakeStarRule(Expressions, Expression);
Expression.Rule =           ValueExpression | FunctionCall;
ValueExpression.Rule =      "@" + Identifier |
			    "@" + Identifier + Expression;
FunctionCall.Rule =	    "$" + Identifier + "(" + ")"

 

What I'm trying to achieve is to be able to have the following construct:

 

@SomeIdentifier$SomeMethodCall()@SomeOtherIdentifier

and

@SomeIdentifier

and

@$SomeMethodCall

and

@SomeIdentifier$SomeMethodCall()@SomeOtherIdentifier$SomeOtherMethodCall()

etc....

 

Would appreciate if someone could help me out on how to setup the language rules for this.

 

Thank you

/Peter

Oct 15, 2012 at 9:13 AM
Edited Oct 15, 2012 at 9:14 AM

Assuming that @$SomeMethodCall is a typo and should read $SomeMethodCall(), then the following grammar seems to suit:

var identifier		= new RegexBasedTerminal("identifier", @"[a-zA-Z_][a-zA-Z_0-9]*");
var Expression		= new NonTerminal("Expression");
var Expressions		= new NonTerminal("Expressions");
var ValueExpression	= new NonTerminal("ValueExpression");
var FunctionCall	= new NonTerminal("FunctionCall");

Root			= Expressions;

Expressions.Rule	=  MakeStarRule(Expressions, Expression);
Expression.Rule		= ValueExpression | FunctionCall;
ValueExpression.Rule	= "@" + identifier ;
FunctionCall.Rule	= "$" + identifier + "(" + ")";

Oct 15, 2012 at 11:44 AM

Hi, thank you for the help :)

- however I realized I oversimplified the example when posting it here :/ - how would I solve the following problem? :) (this is exactly as I in code):

 

            GrammarComments = "Slick scripts interpreter.";
            

            // Terminals
            var Number = new NumberLiteral("Number");
            Number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32 };            
            Number.Options |= NumberOptions.IntOnly;

            var CharLiteral = new StringLiteral("Char", "'", StringOptions.AllowsAllEscapes);
            var StringLiteral = new StringLiteral("String", "\"", StringOptions.AllowsAllEscapes);
            var Identifier = new IdentifierTerminal("Identifier", "_-", "");
            var TextLiteral = new RegexBasedTerminal("identifier", @"[a-zA-Z_][a-zA-Z_0-9]*");

            var LineComment = new CommentTerminal("LineComment", "//", "\n", "\r");            
            NonGrammarTerminals.Add(LineComment);

            var BlockComment = new CommentTerminal("BlockComment", "/*", "*/");            
            NonGrammarTerminals.Add(BlockComment);

            //Keywords
            var TrueKeyword = ToTerm("true", "true");
            var FalseKeyword = ToTerm("false", "false");
            var comma = ToTerm(",");            

            //Non terminals
            //Simple
            var SimpleValue = new NonTerminal("SimpleValue", typeof(SimpleValue));
            var StringValue = new NonTerminal("StringValue", typeof(StringValue));
            var NumberValue = new NonTerminal("NumberValue", typeof(NumberValue));
            var BoolValue = new NonTerminal("BoolValue", typeof(BoolValue));

            //Complex
            var Program = new NonTerminal("Program", typeof(Program));
            var Function = new NonTerminal("Function", typeof(Function));
            var FunctionArgs = new NonTerminal("FunctionArgs", typeof(FunctionArgs));
            var FunctionArg = new NonTerminal("FunctionArg", typeof(FunctionArg));
            var FunctionBody = new NonTerminal("FunctionBody", typeof(FunctionBody));
            var Expressions = new NonTerminal("Expressions", typeof(Expressions));
            var Expression = new NonTerminal("Expression", typeof(Expression));
            var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCall));
            var FunctionCallArgs = new NonTerminal("FunctionCallArgs", typeof(FunctionCallArgs));
            var FunctionCallArg = new NonTerminal("FunctionCallArg", typeof(FunctionCallArg));
            var FunctionCallAgValue = new NonTerminal("FunctionCallArgValue", typeof(FunctionCallAgValue));
            var InlineFunction = new NonTerminal("InlineFunction", typeof(InlineFunction));
            var DefaultFunctionArg = new NonTerminal("DefaultFunctionArg", typeof(DefaultFunctionArg));
            var ValueExpression = new NonTerminal("ValueExpression", typeof(ValueExpression));
            
            //Rules
            //Simple
            StringValue.Rule =              StringLiteral;
            NumberValue.Rule =              Number;
            BoolValue.Rule =                TrueKeyword | FalseKeyword;
            SimpleValue.Rule =              StringValue | NumberValue | BoolValue;

            //Complex
            Program.Rule =                  Function;
            Function.Rule =                 Identifier + "(" + FunctionArgs + ")" + FunctionBody;
            FunctionArgs.Rule =             MakeStarRule(FunctionArgs, comma, FunctionArg);
            FunctionArg.Rule =              DefaultFunctionArg | Identifier;
            DefaultFunctionArg.Rule =       Identifier + "=" + SimpleValue;
            FunctionBody.Rule =             "{" + Expressions + "}";

//These are the "troublesome rules" that I'm having problems with
 Expressions.Rule = MakeStarRule(Expressions, Expression); Expression.Rule = ValueExpression | FunctionCall; ValueExpression.Rule = "@" + Identifier | "@" + Identifier + FunctionCall | "@" + Identifier + FunctionCall + Expression; FunctionCall.Rule = "$" + Identifier + "(" + FunctionCallArgs + ")";

 FunctionCallArgs.Rule = MakeStarRule(FunctionCallArgs, comma, FunctionCallArg); FunctionCallArg.Rule = FunctionCallAgValue | InlineFunction | Expression; FunctionCallAgValue.Rule = Identifier | SimpleValue; InlineFunction.Rule = FunctionBody; // Punctuation, braces, transient terms, options RegisterOperators(1, "+", "-"); RegisterOperators(2, "*", "/"); RegisterOperators(3, Associativity.Right, "**"); MarkPunctuation("(", ")"); MarkPunctuation("{", "}"); MarkPunctuation("=", ",", "&", "|", ";"); RegisterBracePair("(", ")"); RegisterBracePair("{", "}"); MarkTransient(Expression, FunctionArg, FunctionCallArg, SimpleValue, BoolValue, NumberValue, StringValue); Root = Program; LanguageFlags = LanguageFlags.CreateAst;

 

 

Now the expression that I want to allow is the following:

 

 

TestFuncDeclaration(DefaultTestArg=true) {
	$StartTestMethodCall()
	@SimpleTextOutput
	@TextOutputWith$SimpleMethodCall()
	@TextOutputWith$SimpleMethodCall()AndAdditionalOutput
	@TextOutputWith$SimpleMethodCall()AndAdditionalOutput$AndAnotherMethodCall()Etc
	$EndTestMethodCall()
}

 

Dark Red = Text output start, initialized with "@"

Blue = Method call expression

Green = Text output, same as the "Dark Red" except that it's not initialized with A "@"

Red = Method call...

 

The point is to be able to continue recursively like this:

Text / MethodCall / MethodCall / MethodCall / Text / Text etc...

 

The problem I'm having is to allow the "recursion" of

@SomeText in combination with $MethodCall

 

As you can see - it's "important" that I can initialize the statement with "@" and then continue typing text until I hit "$" (which means there is a method call) ... once method call is completed, text follows again.

 

Thanks a lot for the help :)

 

 

Oct 15, 2012 at 2:55 PM
Edited Oct 15, 2012 at 3:00 PM

This seems to work fine:

  ValueExpression.Rule	= "@" + Identifier;
  FunctionCall.Rule	= "$" + Identifier + "(" + FunctionCallArgs + ")"
			| "$" + Identifier + "(" + FunctionCallArgs + ")" + Identifier;

In your ValueExpression rule, FunctionCall is also an Expression, causing the ambiguity.

Oct 16, 2012 at 3:33 PM

Ahaa, I see :)

 

Thanks a bunch! :)

 

See you,

/Bilsa