Does anyone know why these nodes have -1 for alternative numbers? Here are the salient definitions (none of the productions upstream of here have rule alternative tags defined):
All of these issues do appear to be related - the two productions that are messed up in my case are the only left-recursive ones in the grammar. I guess I can always go back to recognizing the rule alternative for those two productions by analyzing the structure of the context.
What's the track record in the ANTLR world of getting something like this fixed?
Many times I had to manually fix the grammar. I wonder if there is some program which can for example automatically remove left recursion from the grammar. I know that it is not so hard to do manually but as grammar getting bigger and deeper...
Is there at least a simple tool which can detect or even fix ambiguity? (I know it is a hard problem) For example the standard grammar for VHDL 2008 is full of ambiguities in complex rules so it is very hard to see and very hard to fix manually.
I am looking also for some tool which can "profile" the grammar.
(I am thinking about writing such a tool, if there is none, because I need performance and reliability of the grammar, which I am not able to achieve otherwise.)
expression : expressionTerm { $ctx.setAltNumber(1) } #termExpression | retrieve { $ctx.setAltNumber(2) } #retrieveExpression | query { $ctx.setAltNumber(3) } #queryExpression | expression 'is' 'not'? ('null' | 'true' | 'false') { $ctx.setAltNumber(4) } #booleanExpression | expression ('is' | 'as') typeSpecifier { $ctx.setAltNumber(5) } #typeExpression | 'cast' expression 'as' typeSpecifier { $ctx.setAltNumber(6) } #castExpression | 'not' expression { $ctx.setAltNumber(7) } #notExpression | 'exists' expression { $ctx.setAltNumber(8) } #existenceExpression | expression 'properly'? 'between' expressionTerm 'and' expressionTerm { $ctx.setAltNumber(9) } #betweenExpression | ('duration' 'in')? pluralDateTimePrecision 'between' expressionTerm 'and' expressionTerm { $ctx.setAltNumber(10) } #durationBetweenExpression | 'difference' 'in' pluralDateTimePrecision 'between' expressionTerm 'and' expressionTerm { $ctx.setAltNumber(11) } #differenceBetweenExpression | expression ('<=' | '<' | '>' | '>=') expression { $ctx.setAltNumber(12) } #inequalityExpression | expression intervalOperatorPhrase expression { $ctx.setAltNumber(13) } #timingExpression | expression ('=' | '!=' | '~' | '!~') expression { $ctx.setAltNumber(14) } #equalityExpression | expression ('in' | 'contains') dateTimePrecisionSpecifier? expression { $ctx.setAltNumber(15) } #membershipExpression | expression 'and' expression { $ctx.setAltNumber(16) } #andExpression | expression ('or' | 'xor') expression { $ctx.setAltNumber(17) } #orExpression | expression 'implies' expression { $ctx.setAltNumber(18) } #impliesExpression | expression ('|' | 'union' | 'intersect' | 'except') expression { $ctx.setAltNumber(19) } #inFixSetExpression ;
This allows you to write a visitor for the production like this:
cqlVisitor.prototype.visitExpression = function(ctx) {var altNum = ctx.getAltNumber()var visitors = [function() { return this.visitTermExpression(ctx) },function() { return this.visitRetrieveExpression(ctx) },function() { return this.visitQueryExpression(ctx) },function() { return this.visitBooleanExpression(ctx) },function() { return this.visitTypeExpression(ctx) }function() { return this.visitCastExpression(ctx) },function() { return this.visitNotExpression(ctx) },function() { return this.visitExistenceExpression(ctx) },function() { return this.visitBetweenExpression(ctx) },function() { return this.visitDurationBetweenExpression(ctx) },function() { return this.visitDifferenceBetweenExpression(ctx) },function() { return this.visitInequalityExpression(ctx) },function() { return this.visitTimingExpression(ctx) },function() { return this.visitEqualityExpression(ctx) },function() { return this.visitMembershipExpression(ctx) },function() { return this.visitAndExpression(ctx) },function() { return this.visitorExpression(ctx) },function() { return this.visitImpliesExpression(ctx) },function() { return this.visitInFixSetExpression(ctx) }]if (altNum && altNum > 0 && altNum <= visitors.length) return visitors[altNum-1]()return null}