package grammar;

import java_cup.runtime.*;
import node.*;
import node.exprNode.*;
import node.exprNode.binaryNode.*;
import node.exprNode.postfixNode.*;
import node.exprNode.simpleNode.*;
import node.setComponentNode.*;
import java.io.*;

parser code
	{:

	private Yylex lexer;
	private String text;
	private Reader sourceReader;

	public parser( String text ) {
		this();
		this.text = text;
		sourceReader = new StringReader( text );
		lexer = new Yylex( sourceReader );
		}

	public String terminal_name( int id ) {
		return sym.terminal_name( id );
		}

	public String non_terminal_name( int id ) {
		return sym.non_terminal_name( id );
		}

	public String rule_name( int id ) {
		return sym.rule_name( id );
		}

	public void report_error( String message, Object info ) {
		System.err.println( message );
		if ( info instanceof Symbol ) {
			Symbol symbol = ( Symbol ) info;
			System.err.println( text );
			for ( int i = 0; i < symbol.left; i++ )
				System.err.print( " " );
			for ( int i = symbol.left; i < symbol.right; i++ )
				System.err.print( "^" );
			System.err.println();
			}
		else
			System.err.println();
		}

	:};

scan with
	{:
	return lexer.yylex();
	:};

/* Terminal Symbols */
terminal Character
	CHAR;
terminal String 
	STRING; 
terminal 
	CARET, LEFT, RIGHT, OR, QUEST, PLUS, STAR, DOT, 
	LEFTSQ, RIGHTSQ, MINUS, ERROR;

/* Nonterminals */

non terminal ExprNode
	RegularExpr, OrExpr, ConcatExpr, SequenceExpr, SimpleExpr;
non terminal SetComponentNode
	Set, Element;

start with RegularExpr;

RegularExpr::=
		OrExpr:expr
		{:
		RESULT = expr;
		:}
	;

OrExpr::=
		OrExpr:expr1 OR ConcatExpr:expr2
		{:
		RESULT = new OrNode( expr1, expr2 );
		:}
	|
		ConcatExpr:expr
		{:
		RESULT = expr;
		:}
	;

ConcatExpr::=
		ConcatExpr:expr1 SequenceExpr:expr2
		{:
		RESULT = new ConcatNode( expr1, expr2 );
		:}
	|
		{:
		RESULT = null;
		:}
	;

SequenceExpr::=
		SimpleExpr:expr QUEST
		{:
		RESULT = new OptNode( expr );
		:}
	|
		SimpleExpr:expr STAR
		{:
		RESULT = new OptSeqNode( expr );
		:}
	|
		SimpleExpr:expr PLUS
		{:
		RESULT = new SeqNode( expr );
		:}
	|
		SimpleExpr:expr
		{:
		RESULT = expr;
		:}
	;

SimpleExpr::=
		DOT
		{:
		RESULT = new DotNode();
		:}
	|
		CHAR:chr
		{:
		RESULT = new CharNode( chr.charValue() );
		:}
	|
		STRING:string
		{:
		RESULT = new StringNode( string );
		:}
	|
		LEFTSQ Set:set RIGHTSQ
		{:
		RESULT = new SetNode( set );
		:}
	|
		LEFTSQ CARET Set:set RIGHTSQ
		{:
		RESULT = new NotSetNode( set );
		:}
	|
		LEFT OrExpr:expr RIGHT
		{:
		RESULT = expr;
		:}
	;

Set::=
		Element:element
		{:
		RESULT = element;
		:}
	|
		Element:element Set:set
		{:
		RESULT = new SetComponentSeqNode( element, set );
		:}
	;

Element::=
		CHAR:chr
		{:
		RESULT = new SetElementNode( chr.charValue() );
		:}
	|
		CHAR:chr1 MINUS CHAR:chr2
		{:
		RESULT = new SetRangeNode( chr1.charValue(), chr2.charValue() );
		:}
	;
