/*
 [The "BSD license"]
 Copyright (c) 2005-2011 Terence Parr
 All rights reserved.

 Grammar conversion to ANTLR v3:
 Copyright (c) 2011 Sam Harwell
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
 1. Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
	notice, this list of conditions and the following disclaimer in the
	documentation and/or other materials provided with the distribution.
 3. The name of the author may not be used to endorse or promote products
	derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/** Build an NFA from a tree representing an ANTLR grammar. */
tree grammar TreeToNFAConverter;

options {
	language=Java;
	tokenVocab = ANTLR;
	ASTLabelType = GrammarAST;
}

@header {
package org.antlr.grammar.v3;

import org.antlr.analysis.*;
import org.antlr.misc.*;
import org.antlr.tool.*;

import org.antlr.runtime.BitSet;
import org.antlr.runtime.DFA;
}

@members {
/** Factory used to create nodes and submachines */
protected NFAFactory factory = null;

/** Which NFA object are we filling in? */
protected NFA nfa = null;

/** Which grammar are we converting an NFA for? */
protected Grammar grammar = null;

protected String currentRuleName = null;

protected int outerAltNum = 0;
protected int blockLevel = 0;

protected int inTest = 0;

public TreeToNFAConverter(TreeNodeStream input, Grammar g, NFA nfa, NFAFactory factory) {
    this(input);
    this.grammar = g;
    this.nfa = nfa;
    this.factory = factory;
}

public final IntSet setRule(GrammarAST t) throws RecognitionException {
    TreeToNFAConverter other = new TreeToNFAConverter( new CommonTreeNodeStream( t ), grammar, nfa, factory );

    other.currentRuleName = currentRuleName;
    other.outerAltNum = outerAltNum;
    other.blockLevel = blockLevel;

    return other.setRule();
}

public final int testBlockAsSet( GrammarAST t ) throws RecognitionException {
    Rule r = grammar.getLocallyDefinedRule( currentRuleName );
    if ( r.hasRewrite( outerAltNum ) )
        return -1;

    TreeToNFAConverter other = new TreeToNFAConverter( new CommonTreeNodeStream( t ), grammar, nfa, factory );

    other.state.backtracking++;
    other.currentRuleName = currentRuleName;
    other.outerAltNum = outerAltNum;
    other.blockLevel = blockLevel;

    int result = other.testBlockAsSet();
    if ( other.state.failed )
        return -1;

    return result;
}

public final int testSetRule( GrammarAST t ) throws RecognitionException {
    TreeToNFAConverter other = new TreeToNFAConverter( new CommonTreeNodeStream( t ), grammar, nfa, factory );

    other.state.backtracking++;
    other.currentRuleName = currentRuleName;
    other.outerAltNum = outerAltNum;
    other.blockLevel = blockLevel;

    int result = other.testSetRule();
    if ( other.state.failed )
        state.failed = true;

    return result;
}

protected void addFollowTransition( String ruleName, NFAState following ) {
    //System.Console.Out.WriteLine( "adding follow link to rule " + ruleName );
    // find last link in FOLLOW chain emanating from rule
    Rule r = grammar.getRule( ruleName );
    NFAState end = r.stopState;
    while ( end.transition( 1 ) != null )
    {
        end = (NFAState)end.transition( 1 ).target;
    }
    if ( end.transition( 0 ) != null )
    {
        // already points to a following node
        // gotta add another node to keep edges to a max of 2
        NFAState n = factory.newState();
        Transition e = new Transition( Label.EPSILON, n );
        end.addTransition( e );
        end = n;
    }
    Transition followEdge = new Transition( Label.EPSILON, following );
    end.addTransition( followEdge );
}

protected void finish() {
    int numEntryPoints = factory.build_EOFStates( grammar.getRules() );
    if ( numEntryPoints == 0 )
    {
        ErrorManager.grammarWarning( ErrorManager.MSG_NO_GRAMMAR_START_RULE,
                                   grammar,
                                   null,
                                   grammar.name );
    }
}

@Override
public void reportError(RecognitionException ex) {
    if ( inTest > 0 )
        throw new IllegalStateException(ex);

    Token token = null;
    if ( ex instanceof MismatchedTokenException )
    {
        token = ( (MismatchedTokenException)ex ).token;
    }
    else if ( ex instanceof NoViableAltException )
    {
        token = ( (NoViableAltException)ex ).token;
    }

    ErrorManager.syntaxError(
        ErrorManager.MSG_SYNTAX_ERROR,
        grammar,
        token,
        "buildnfa: " + ex.toString(),
        ex );
}

private boolean hasElementOptions(GrammarAST node) {
    if (node == null)
        throw new NullPointerException("node");
    return node.terminalOptions != null && node.terminalOptions.size() > 0;
}
}

public
grammar_
@after
{
	finish();
}
	:	(	^( LEXER_GRAMMAR grammarSpec )
		|	^( PARSER_GRAMMAR grammarSpec )
		|	^( TREE_GRAMMAR grammarSpec )
		|	^( COMBINED_GRAMMAR grammarSpec )
		)
	;

attrScope
	:	^( 'scope' ID ( ^(AMPERSAND .*) )* ACTION )
	;

grammarSpec
	:	ID
		(cmt=DOC_COMMENT)?
		( ^(OPTIONS .*) )?
		( ^(IMPORT .*) )?
		( ^(TOKENS .*) )?
		(attrScope)*
		( ^(AMPERSAND .*) )* // skip actions
		rules
	;

rules
	:	(rule | ^(PREC_RULE .*))+
	;

rule
	:	^(	RULE id=ID
			{
				currentRuleName = $id.text;
				factory.setCurrentRule(grammar.getLocallyDefinedRule(currentRuleName));
			}
			(modifier)?
			^(ARG (ARG_ACTION)?)
			^(RET (ARG_ACTION)?)
			(throwsSpec)?
			( ^(OPTIONS .*) )?
			( ruleScopeSpec )?
			( ^(AMPERSAND .*) )*
			b=block
			(exceptionGroup)?
			EOR
			{
				StateCluster g = $b.g;
				if ($b.start.getSetValue() != null)
				{
					// if block comes back as a set not BLOCK, make it
					// a single ALT block
					g = factory.build_AlternativeBlockFromSet(g);
				}
				if (Rule.getRuleType(currentRuleName) == Grammar.PARSER || grammar.type==Grammar.LEXER)
				{
					// attach start node to block for this rule
					Rule thisR = grammar.getLocallyDefinedRule(currentRuleName);
					NFAState start = thisR.startState;
					start.associatedASTNode = $id;
					start.addTransition(new Transition(Label.EPSILON, g.left));

					// track decision if > 1 alts
					if ( grammar.getNumberOfAltsForDecisionNFA(g.left)>1 )
					{
						g.left.setDescription(grammar.grammarTreeToString($start, false));
						g.left.setDecisionASTNode($b.start);
						int d = grammar.assignDecisionNumber( g.left );
						grammar.setDecisionNFA( d, g.left );
						grammar.setDecisionBlockAST(d, $b.start);
					}

					// hook to end of rule node
					NFAState end = thisR.stopState;
					g.right.addTransition(new Transition(Label.EPSILON,end));
				}
			}
		)
	;

modifier
	:	'protected'
	|	'public'
	|	'private'
	|	'fragment'
	;

throwsSpec
	:	^('throws' ID+)
	;

ruleScopeSpec
	:	^( 'scope' ( ^(AMPERSAND .*) )* (ACTION)? ( ID )* )
	;

block returns [StateCluster g = null]
@init
{
	List<StateCluster> alts = new ArrayList<StateCluster>();
	this.blockLevel++;
	if ( this.blockLevel==1 )
		this.outerAltNum=1;
}
	:	{grammar.isValidSet(this,$start) &&
		 !currentRuleName.equals(Grammar.ARTIFICIAL_TOKENS_RULENAME)}? =>
		set {$g = $set.g;}

	|	^(	BLOCK ( ^(OPTIONS .*) )?
			(	a=alternative rewrite
				{
					alts.add($a.g);
				}
				{{
					if ( blockLevel == 1 )
						outerAltNum++;
				}}
			)+
			EOB
		)
		{$g = factory.build_AlternativeBlock(alts);}
	;
finally { blockLevel--; }

alternative returns [StateCluster g=null]
	:	^( ALT (e=element {$g = factory.build_AB($g,$e.g);} )+ EOA )
		{
			if ($g==null) { // if alt was a list of actions or whatever
				$g = factory.build_Epsilon();
			}
			else {
				factory.optimizeAlternative($g);
			}
		}
	;

exceptionGroup
	:	( exceptionHandler )+ (finallyClause)?
	|	finallyClause
	;

exceptionHandler
	:    ^('catch' ARG_ACTION ACTION)
	;

finallyClause
	:    ^('finally' ACTION)
	;

rewrite
	:	^(	REWRITES
			(
				{
					if ( grammar.getOption("output")==null )
					{
						ErrorManager.grammarError(ErrorManager.MSG_REWRITE_OR_OP_WITH_NO_OUTPUT_OPTION,
												  grammar, $start.getToken(), currentRuleName);
					}
				}
				^(REWRITE .*)
			)*
		)
	|
	;

element returns [StateCluster g=null]
	:   ^(ROOT e=element {$g = $e.g;})
	|   ^(BANG e=element {$g = $e.g;})
	|	^(ASSIGN ID e=element {$g = $e.g;})
	|	^(PLUS_ASSIGN ID e=element {$g = $e.g;})
	|   ^(RANGE a=atom[null] b=atom[null])
		{$g = factory.build_Range(grammar.getTokenType($a.text),
								 grammar.getTokenType($b.text));}
	|   ^(CHAR_RANGE c1=CHAR_LITERAL c2=CHAR_LITERAL)
		{
		if ( grammar.type==Grammar.LEXER ) {
			$g = factory.build_CharRange($c1.text, $c2.text);
		}
		}
	|   atom_or_notatom {$g = $atom_or_notatom.g;}
	|   ebnf {$g = $ebnf.g;}
	|   tree_ {$g = $tree_.g;}
	|   ^( SYNPRED block )
	|   ACTION {$g = factory.build_Action($ACTION);}
	|   FORCED_ACTION {$g = factory.build_Action($FORCED_ACTION);}
	|   pred=SEMPRED {$g = factory.build_SemanticPredicate($pred);}
	|   spred=SYN_SEMPRED {$g = factory.build_SemanticPredicate($spred);}
	|   ^(bpred=BACKTRACK_SEMPRED .*) {$g = factory.build_SemanticPredicate($bpred);}
	|   gpred=GATED_SEMPRED {$g = factory.build_SemanticPredicate($gpred);}
	|   EPSILON {$g = factory.build_Epsilon();}
	;

ebnf returns [StateCluster g=null]
@init
{
	GrammarAST blk = $start;
	if (blk.getType() != BLOCK) {
		blk = (GrammarAST)blk.getChild(0);
	}
	GrammarAST eob = blk.getLastChild();
}
	:	{grammar.isValidSet(this,$start)}? => set {$g = $set.g;}

	|	b=block
		{
			// track decision if > 1 alts
			if ( grammar.getNumberOfAltsForDecisionNFA($b.g.left)>1 )
			{
				$b.g.left.setDescription(grammar.grammarTreeToString(blk, false));
				$b.g.left.setDecisionASTNode(blk);
				int d = grammar.assignDecisionNumber( $b.g.left );
				grammar.setDecisionNFA( d, $b.g.left );
				grammar.setDecisionBlockAST(d, blk);
			}
			$g = $b.g;
		}
	|	^( OPTIONAL b=block )
		{
			StateCluster bg = $b.g;
			if ( blk.getSetValue()!=null )
			{
				// if block comes back SET not BLOCK, make it
				// a single ALT block
				bg = factory.build_AlternativeBlockFromSet(bg);
			}
			$g = factory.build_Aoptional(bg);
			$g.left.setDescription(grammar.grammarTreeToString($start, false));
			// there is always at least one alt even if block has just 1 alt
			int d = grammar.assignDecisionNumber( $g.left );
			grammar.setDecisionNFA(d, $g.left);
			grammar.setDecisionBlockAST(d, blk);
			$g.left.setDecisionASTNode($start);
		}
	|	^( CLOSURE b=block )
		{
			StateCluster bg = $b.g;
			if ( blk.getSetValue()!=null )
			{
				bg = factory.build_AlternativeBlockFromSet(bg);
			}
			$g = factory.build_Astar(bg);
			// track the loop back / exit decision point
			bg.right.setDescription("()* loopback of "+grammar.grammarTreeToString($start, false));
			int d = grammar.assignDecisionNumber( bg.right );
			grammar.setDecisionNFA(d, bg.right);
			grammar.setDecisionBlockAST(d, blk);
			bg.right.setDecisionASTNode(eob);
			// make block entry state also have same decision for interpreting grammar
			NFAState altBlockState = (NFAState)$g.left.transition(0).target;
			altBlockState.setDecisionASTNode($start);
			altBlockState.setDecisionNumber(d);
			$g.left.setDecisionNumber(d); // this is the bypass decision (2 alts)
			$g.left.setDecisionASTNode($start);
		}
	|	^( POSITIVE_CLOSURE b=block )
		{
			StateCluster bg = $b.g;
			if ( blk.getSetValue()!=null )
			{
				bg = factory.build_AlternativeBlockFromSet(bg);
			}
			$g = factory.build_Aplus(bg);
			// don't make a decision on left edge, can reuse loop end decision
			// track the loop back / exit decision point
			bg.right.setDescription("()+ loopback of "+grammar.grammarTreeToString($start, false));
			int d = grammar.assignDecisionNumber( bg.right );
			grammar.setDecisionNFA(d, bg.right);
			grammar.setDecisionBlockAST(d, blk);
			bg.right.setDecisionASTNode(eob);
			// make block entry state also have same decision for interpreting grammar
			NFAState altBlockState = (NFAState)$g.left.transition(0).target;
			altBlockState.setDecisionASTNode($start);
			altBlockState.setDecisionNumber(d);
		}
	;

tree_ returns [StateCluster g=null]
@init
{
	StateCluster down=null, up=null;
}
	:	^(	TREE_BEGIN
			e=element { $g = $e.g; }
			{
				down = factory.build_Atom(Label.DOWN, $e.start);
				// TODO set following states for imaginary nodes?
				//el.followingNFAState = down.right;
				$g = factory.build_AB($g,down);
			}
			( e=element {$g = factory.build_AB($g,$e.g);} )*
			{
				up = factory.build_Atom(Label.UP, $e.start);
				//el.followingNFAState = up.right;
				$g = factory.build_AB($g,up);
				// tree roots point at right edge of DOWN for LOOK computation later
				$start.NFATreeDownState = down.left;
			}
		)
	;

atom_or_notatom returns [StateCluster g=null]
	:	atom[null] {$g = $atom.g;}
	|	^(	n=NOT
			(	c=CHAR_LITERAL (ast1=ast_suffix)?
				{
					int ttype=0;
					if ( grammar.type==Grammar.LEXER )
					{
						ttype = Grammar.getCharValueFromGrammarCharLiteral($c.text);
					}
					else
					{
						ttype = grammar.getTokenType($c.text);
					}
					IntSet notAtom = grammar.complement(ttype);
					if ( notAtom.isNil() )
					{
						ErrorManager.grammarError(
							ErrorManager.MSG_EMPTY_COMPLEMENT,
							grammar,
							$c.getToken(),
							$c.text);
					}
					$g=factory.build_Set(notAtom,$n);
				}
			|	t=TOKEN_REF (ast3=ast_suffix)?
				{
					int ttype=0;
					IntSet notAtom = null;
					if ( grammar.type==Grammar.LEXER )
					{
						notAtom = grammar.getSetFromRule(this,$t.text);
						if ( notAtom==null )
						{
							ErrorManager.grammarError(
								ErrorManager.MSG_RULE_INVALID_SET,
								grammar,
								$t.getToken(),
								$t.text);
						}
						else
						{
							notAtom = grammar.complement(notAtom);
						}
					}
					else
					{
						ttype = grammar.getTokenType($t.text);
						notAtom = grammar.complement(ttype);
					}
					if ( notAtom==null || notAtom.isNil() )
					{
						ErrorManager.grammarError(
							ErrorManager.MSG_EMPTY_COMPLEMENT,
							grammar,
							$t.getToken(),
							$t.text);
					}
					$g=factory.build_Set(notAtom,$n);
				}
			|	set {$g = $set.g;}
				{
					GrammarAST stNode = (GrammarAST)$n.getChild(0);
					//IntSet notSet = grammar.complement(stNode.getSetValue());
					// let code generator complement the sets
					IntSet s = stNode.getSetValue();
					stNode.setSetValue(s);
					// let code gen do the complement again; here we compute
					// for NFA construction
					s = grammar.complement(s);
					if ( s.isNil() )
					{
						ErrorManager.grammarError(
							ErrorManager.MSG_EMPTY_COMPLEMENT,
							grammar,
							$n.getToken());
					}
					$g=factory.build_Set(s,$n);
				}
			)
			{$n.followingNFAState = $g.right;}
		)
	;

atom[String scopeName] returns [StateCluster g=null]
	:	^( r=RULE_REF (rarg=ARG_ACTION)? (as1=ast_suffix)? )
		{
			NFAState start = grammar.getRuleStartState(scopeName,$r.text);
			if ( start!=null )
			{
				Rule rr = grammar.getRule(scopeName,$r.text);
				$g = factory.build_RuleRef(rr, start);
				r.followingNFAState = $g.right;
				r.NFAStartState = $g.left;
				if ( $g.left.transition(0) instanceof RuleClosureTransition
					&& grammar.type!=Grammar.LEXER )
				{
					addFollowTransition($r.text, $g.right);
				}
				// else rule ref got inlined to a set
			}
		}

	|	^( t=TOKEN_REF  (targ=ARG_ACTION)? (as2=ast_suffix)? )
		{
			if ( grammar.type==Grammar.LEXER )
			{
				NFAState start = grammar.getRuleStartState(scopeName,$t.text);
				if ( start!=null )
				{
					Rule rr = grammar.getRule(scopeName,t.getText());
					$g = factory.build_RuleRef(rr, start);
					t.NFAStartState = $g.left;
					// don't add FOLLOW transitions in the lexer;
					// only exact context should be used.
				}
			}
			else
			{
				$g = factory.build_Atom(t);
				t.followingNFAState = $g.right;
			}
		}

	|	^( c=CHAR_LITERAL  (as3=ast_suffix)? )
		{
			if ( grammar.type==Grammar.LEXER )
			{
				$g = factory.build_CharLiteralAtom(c);
			}
			else
			{
				$g = factory.build_Atom(c);
				c.followingNFAState = $g.right;
			}
		}

	|	^( s=STRING_LITERAL  (as4=ast_suffix)? )
		{
			if ( grammar.type==Grammar.LEXER )
			{
				$g = factory.build_StringLiteralAtom(s);
			}
			else
			{
				$g = factory.build_Atom(s);
				s.followingNFAState = $g.right;
			}
		}

	|	^(	w=WILDCARD (as5=ast_suffix)? )
			{
				if ( nfa.grammar.type == Grammar.TREE_PARSER
					&& (w.getChildIndex() > 0 || w.getParent().getChild(1).getType() == EOA) )
				{
					$g = factory.build_WildcardTree( $w );
				}
				else
				{
					$g = factory.build_Wildcard( $w );
				}
			}

	|	^( DOT scope_=ID a=atom[$scope_.text] {$g = $a.g;} ) // scope override
	;

ast_suffix
	:	ROOT
	|	BANG
	;

set returns [StateCluster g=null]
@init
{
	IntSet elements=new IntervalSet();
	if ( state.backtracking == 0 )
		$start.setSetValue(elements); // track set for use by code gen
}
	:	^( b=BLOCK
		   (^(ALT ( ^(BACKTRACK_SEMPRED .*) )? setElement[elements] EOA))+
		   EOB
		 )
		{
		$g = factory.build_Set(elements,$b);
		$b.followingNFAState = $g.right;
		$b.setSetValue(elements); // track set value of this block
		}
		//{System.out.println("set elements="+elements.toString(grammar));}
	;

setRule returns [IntSet elements=new IntervalSet()]
@init
{
	IntSet s=null;
}
	:	^( RULE id=ID (modifier)? ARG RET ( ^(OPTIONS .*) )? ( ruleScopeSpec )?
			( ^(AMPERSAND .*) )*
			^( BLOCK ( ^(OPTIONS .*) )?
			   ( ^(ALT (BACKTRACK_SEMPRED)? setElement[elements] EOA) )+
			   EOB
			 )
			(exceptionGroup)?
			EOR
		 )
	;
catch[RecognitionException re] { throw re; }

setElement[IntSet elements]
@init
{
	int ttype;
	IntSet ns=null;
}
	:	c=CHAR_LITERAL
		{
			if ( grammar.type==Grammar.LEXER )
			{
				ttype = Grammar.getCharValueFromGrammarCharLiteral($c.text);
			}
			else
			{
				ttype = grammar.getTokenType($c.text);
			}
			if ( elements.member(ttype) )
			{
				ErrorManager.grammarError(
					ErrorManager.MSG_DUPLICATE_SET_ENTRY,
					grammar,
					$c.getToken(),
					$c.text);
			}
			elements.add(ttype);
		}
	|	t=TOKEN_REF
		{
			if ( grammar.type==Grammar.LEXER )
			{
				// recursively will invoke this rule to match elements in target rule ref
				IntSet ruleSet = grammar.getSetFromRule(this,$t.text);
				if ( ruleSet==null )
				{
					ErrorManager.grammarError(
						ErrorManager.MSG_RULE_INVALID_SET,
						grammar,
						$t.getToken(),
						$t.text);
				}
				else
				{
					elements.addAll(ruleSet);
				}
			}
			else
			{
				ttype = grammar.getTokenType($t.text);
				if ( elements.member(ttype) )
				{
					ErrorManager.grammarError(
						ErrorManager.MSG_DUPLICATE_SET_ENTRY,
						grammar,
						$t.getToken(),
						$t.text);
				}
				elements.add(ttype);
			}
		}

	|	s=STRING_LITERAL
		{
			ttype = grammar.getTokenType($s.text);
			if ( elements.member(ttype) )
			{
				ErrorManager.grammarError(
					ErrorManager.MSG_DUPLICATE_SET_ENTRY,
					grammar,
					$s.getToken(),
					$s.text);
			}
			elements.add(ttype);
		}
	|	^(CHAR_RANGE c1=CHAR_LITERAL c2=CHAR_LITERAL)
		{
			if ( grammar.type==Grammar.LEXER )
			{
				int a = Grammar.getCharValueFromGrammarCharLiteral($c1.text);
				int b = Grammar.getCharValueFromGrammarCharLiteral($c2.text);
				elements.addAll(IntervalSet.of(a,b));
			}
		}

	|	gset=set
		{
			Transition setTrans = $gset.g.left.transition(0);
			elements.addAll(setTrans.label.getSet());
		}

	|	^(	NOT {ns=new IntervalSet();}
			setElement[ns]
			{
				IntSet not = grammar.complement(ns);
				elements.addAll(not);
			}
		)
	;

/** Check to see if this block can be a set.  Can't have actions
 *  etc...  Also can't be in a rule with a rewrite as we need
 *  to track what's inside set for use in rewrite.
 *
 *  This should only be called from the helper function in TreeToNFAConverterHelper.cs
 *  and from the rule testSetElement below.
 */
testBlockAsSet returns [int alts=0]
options { backtrack = true; }
@init
{
	inTest++;
}
	:	^(	BLOCK
			(	^(ALT (BACKTRACK_SEMPRED)? testSetElement {{$alts += $testSetElement.alts;}} EOA)
			)+
			EOB
		)
	;
catch[RecognitionException re] { throw re; }
finally { inTest--; }

testSetRule returns [int alts=0]
@init
{
	inTest++;
}
	:	^(	RULE id=ID (modifier)? ARG RET ( ^(OPTIONS .*) )? ( ruleScopeSpec )?
			( ^(AMPERSAND .*) )*
			^(	BLOCK
				(	^(ALT (BACKTRACK_SEMPRED)? testSetElement {{$alts += $testSetElement.alts;}} EOA)
				)+
				EOB
			)
			(exceptionGroup)?
			EOR
		)
	;
catch[RecognitionException re] { throw re; }
finally { inTest--; }

/** Match just an element; no ast suffix etc.. */
testSetElement returns [int alts=1]
	:	c=CHAR_LITERAL {!hasElementOptions($c)}?
	|	t=TOKEN_REF {!hasElementOptions($t)}?
		{{
			if ( grammar.type==Grammar.LEXER )
			{
				Rule rule = grammar.getRule($t.text);
				if ( rule==null )
				{
					//throw new RecognitionException("invalid rule");
					throw new RecognitionException();
				}
				// recursively will invoke this rule to match elements in target rule ref
				$alts += testSetRule(rule.tree);
			}
		}}
	|   {grammar.type!=Grammar.LEXER}? => s=STRING_LITERAL
	|	^(CHAR_RANGE c1=CHAR_LITERAL c2=CHAR_LITERAL)
		{{ $alts = IntervalSet.of( Grammar.getCharValueFromGrammarCharLiteral($c1.text), Grammar.getCharValueFromGrammarCharLiteral($c2.text) ).size(); }}
	|   testBlockAsSet
		{{ $alts = $testBlockAsSet.alts; }}
	|   ^( NOT tse=testSetElement )
		{{ $alts = grammar.getTokenTypes().size() - $tse.alts; }}
	;
catch[RecognitionException re] { throw re; }
