simplify a canmatch function

SyntaxEditor for WPF Forum

Posted 5 years ago by Aurore
Version: 14.1.0602
Avatar

I have the following grammar :

root ::= block | logExpr

block ::= assigt | block_if | ...

assigt ::= (sphVar | activeVar | tmpVar) + @"=" + logExpr

logEpr ::= arithmExpr + [(@"=" | @"<>") + logExpr]

 

you'll see that the "=" character can be used twice : in assignement and in logicalexpression for equality test.

When i write "V1 = 123", the expression is an assignment.

But in some particular context, i'd like this expression be a logical Expression.

 

My first issue is to add a canmatch callback on the root node. It works but to do that i need to recode the "(sphVar | activeVar | tmpVar)" choice in the callback function.

Is there exist a way not to recode what it is naturally done if we don't add canmatch callback ?

Comments (8)

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

I'm not sure that I'm seeing the ambiguity here based on what you have above.  It seems like the "logExpr" always happens within the "assigt" so there isn't anything ambiguous there.  Also a "logExpr" wouldn't occur as a normal statement, would it?  Woudln't it need to be within an 'if' or 'while' sort of test expression area?  Can you show exactly where the ambiguity is in the grammar (the two productions and related sub-productions) that cause an ambiguity error?  Thanks!


Actipro Software Support

Posted 5 years ago by Aurore
Avatar

Hello,

The grammar is good. What we need to do is to give priority for the root production between block and logexpr.

In our language, it is possible to use logexpr also as normal statement, if the expression contains only this statement.

V1 = 12 : should be considered as assignment until a certain context property is setted, that switches the semantic and then "V1 = 12" must be considered as a logexpr.

That's why we would add a canmatch callback for block, to return false when these property is setted. And then, should return true if it is a assignment or a block, but stay return false for "6 = 3" which is not an assignement but a right logical expression.

Thanks for your time.

The ambiguitie comes from the logexpr expression. The terminals associated for this non-terminal are :  "sphVar  | tmpVar | intorreal |..." 

=> then a block (through his assignment rule), and a logical expression have same terminals.

[Modified 5 years ago]

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello, I still really would need to see some code examples showing the two ambiguous scenarios to help more.  But based on what you said, this idea might help...

In your grammar class, in the root production, you can assign an .OnInitialize handler like:

this.Root.Production = (
	...
	).OnInitialize(CompilationUnitInitialize);

Then in that method, set up a custom data object that has a property on it you can use to track that special semantic state:

private void CompilationUnitInitialize(IParserState state) {
	// Initialize the state's custom data with a parser context
	state.CustomData = new YourParserContext();
}

Wherever that semantic scenario occurs, you can put an .OnInitialize and .OnComplete calls on the production again like what we did above and in the .OnInitialize handler, assign a property on the YourParserContext property.  Then in the .OnCompleted handler, clear that property.

Finally, in your can-match callback, you can look at that property on the object in state.CustomData to see if you are in this scenario or not.

I hope that helps!


Actipro Software Support

Posted 5 years ago by Aurore
Avatar

Hello,

Instead of using CustonData property, we've added a property directly to the grammar class, and i think the issue is the same.

 our grammar looks like :

this.Root.Production = @lineTerminator.ZeroOrMore() + (blockStatement | logicalExpr) + @lineTerminator.ZeroOrMore() ;
blockStatement.Production = (lineStatement + (@lineTerminator.OneOrMore() + lineStatement.Optional()).ZeroOrMore();
lineStatement.Production = assignment | blockIfThenElse	| blockSwitch | blockFor | blockDo;
assignment.Production = (sphVarExpr | activeVarExpr | tmpVarExpr) + @equalityEQ + logicalExpr);
logicalExpr.Production = stringCompExpr + ((@logicalAnd  | @logicalOr  | @logicalXor )+ logicalExpr).Optional();
stringCompExpr.Production = equalityExpr + ((@containing  | @like  | @in  | @with  | @withWords) + stringCompExpr).Optional();
equalityExpr.Production = relationalExpr + ((@equalityEQ|@equalityNE) + equalityExpr).Optional()
relationalExpr.Production = additionExpr + ((@relationalLE | @relationalGE  |@relationalLT| @relationalGT) + relationalExpr).Optional();
additionExpr.Production = multiplExpr + ((@addition|@substraction | @stringAnd) + additionExpr).Optional() ;
multiplExpr.Production = unaryExpr + ((@multiplication  |@division | @divInt | @modulo )+ multiplExpr).Optional();
unaryExpr.Production = factorExpr| (@substraction | @logicalNot ) + factorExpr;
factorExpr.Production = sphVarExpr | @identifier | numericValue | ...; //sphVarExpr as in assignment.Production
numericValue.Production = @integer | @real;
sphVarExpr.Production = SphVarNExpr  | SphVarFExpr | ...;			
SphVarNExpr .Production = sphVar.ToTerm().ToProduction();

 

I will thinking of your proposal tomorrow.

Thanks

[Modified 5 years ago]

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Keep in mind that the parser might get used by multiple threads.  Using a property on the parser could cause a problem.  By doing what I suggested, you would avoid any of those problems since that would be parsing session specific.


Actipro Software Support

Posted 5 years ago by Aurore
Avatar

my question is, in other words :

  - is it possible in an user canmatch callback, to call the default canmatch (those which is applied when no user callback is defined) ?*

Thanks

Answer - Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello, if I understand you correctly, that isn't a problem.  The can-match logic methods are all just regular .NET methods, so you can call them from other can-match methods or any other .NET code.


Actipro Software Support

Posted 5 years ago by Aurore
Avatar

Thanks for your discussion.

You're right, we do so :

public bool OnCanMatchLineStatement(IParserState state)
{
    if (this._oOptions.IsSampleContext) return false;
	return _assignment.CanMatch(state) || _blockDo.CanMatch(state) || _blockFor.CanMatch(state) || _blockIfThenElse.CanMatch(state) || _blockSwitch.CanMatch(state);
}

 

We still think about use customdata property instead of parser property.

Thanks.

[Modified 5 years ago]

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.