/**
 * This is a JACC grammar for the IRL language.
 *
 * @version     Last modified on Tue May 31 19:44:53 2005 by hak
 * @author      <a href="mailto:hak@ilog.fr">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; 2004 <a href="http://www.ilog.com/">ILOG, Inc.</a>
 *
 */

%package Ilog.Irl;

%nodeprefix "IRL_"
%nodesuffix ""

%dynamic // to allow ambiguous tokens and actions

%token INTEGER_LITERAL FLOATING_POINT_LITERAL CHARACTER_LITERAL STRING_LITERAL
%token IDENTIFIER VARIABLE
%right    '&'
%nonassoc '=' '+=' '-=' '*=' '/=' '%=' '&=' '|='
%right    '||'
%right    '&&'
%nonassoc 'instanceof' 'as'
%left     '==' '!='
%nonassoc 'equals'
%nonassoc 'in'
%nonassoc '<' '<=' '>' '>='
%left     '+'  '-'
%left     '*' '/' '%'
%right    '!'
%token    '(' ')' LOCEXP
%nonassoc '++' '--'
%token    '['
%left     '.'
%token    'else'
%token    ';'
%right UNOP     // for S/R conflict in unary operator rule

// Note that using the above precedences will not report the resolved
// conflicts. Presumably, all such resolutions are safe and may not
// create any wrong parses (they were arrived at after careful
// examination of the conflicts and made explicit after ascertaining
// that they were correct). All other remaining unresolved conflicts are
// caused by inherent ambiguities in the grammar. These cannot be
// resolved statically and must be (and are) handled dynamically using
// the -amb option provided by Jacc that enables ambiguous parse actions.

// Grammar start symbol:

%start IrlProgram

// Independently parsable units:
  
%root  RulesetDefinition
%root  RuleDefinition
%root  TaskDefinition
%root  ActionStatement
%root  Expression

%import System
%import System.IO
%import Ilog.Language.Tools

%{
  DateTime start;
  bool quiet = true;
  TextWriter OUT = Console.Out;

  internal void SetStart ()
    {
      start = DateTime.Now;
    }

  internal void SetQuiet (bool flag)
    {
      quiet = flag;
    }

  internal void SetOutputStream (TextWriter stream)
    {
      OUT = stream;
    }

  /*
   * A function to show what happened.
   */
  private void ShowResult ()
    {
      OUT.WriteLine("*** Total parsing time = "
		    + (DateTime.Now-start)
		    + " ms");

      if (!quiet)
        {
          ErrorManager.TallyErrors();
          if (Misc.AskYesNo("*** Do you want to see the parse tree"))
            {
              OUT.WriteLine("*** Displaying the parse tree...");
//               CurrentNode.Display(FileName);
	      CurrentNode.Show();
            }
        }
    }
%}

%%

IrlProgram
  : RulesetDefinition { ShowResult(); }
  ;

RulesetDefinition
  : Preamble RulesetElementDefinitions_opt
  ;

Preamble
  : ImportDefinitions_opt PropertyDefinition_opt SetupDefinition_opt
  ;

ImportDefinitions_opt
  : /* empty */
  | ImportDefinitions
  ;

ImportDefinitions
  : ImportDefinition
  | ImportDefinitions ImportDefinition
  ;

ImportDefinition
  : 'import' ExtendedIdentifier DotStar_opt Semicolon
  ;

DotStar_opt
  : /* empty */
  | '.' '*'
  ;

PropertyDefinition_opt
  : /* empty */
  | PropertyDefinition
  ;

PropertyDefinition
  : 'ruleset' ExtendedIdentifier PropertyBody
  ;

PropertyBody
  : Semicolon
  | '{' RulesetDeclarations_opt '}' Semicolon_opt
  ;

RulesetDeclarations_opt
  : /* empty */
  | RulesetDeclarations
  ;

RulesetDeclarations
  : RulesetDeclaration
  | RulesetDeclarations RulesetDeclaration
  ;

RulesetDeclaration
  : HasherDeclaration
  | ClassInstancesDeclaration
  | PropertyDeclaration
  | VariableSpecification
  ;

ClassInstancesDeclaration
  : 'instances' '(' ExtendedIdentifier ')' '=' InstancesSpecification
  ;

InstancesSpecification
  : Expression Semicolon
  | '{' Expressions_opt '}' Semicolon_opt
  ;

HasherDeclaration
  : 'hasher' '('  TypedObjectVariable ')' '=' Expression Semicolon
  ;

VariableSpecification
  : InOut TypedVariable Semicolon
  | Out_opt VariableDeclaration Semicolon
  ;

InOut
  : 'in'
  | 'inout'
  ;

Out_opt
  : /* empty */
  | 'out'
  ;

PropertyDeclaration
  : 'property' ExtendedIdentifier '=' PropertyValue Semicolon
  ;

PropertyValue
  : Literal
  | ExtendedIdentifier ParenthesizedString_opt
  ;

ParenthesizedString_opt
  : /* empty */
  | '(' STRING_LITERAL ')'
  ;

Expression_opt
  : /* empty */
  | Expression
  ;

Expression
  : Literal
  | Location                                            %prec LOCEXP
  | FunctionCall
  | IncDecExpression
  | AllocationExpression
  | ClassExpression
  | UnaryOperatorExpression
  | BinaryOperatorExpression
  | '(' Type ')' Expression
  | '(' Expression ')'
  ;

Literal
  : 'true'
  | 'false'
  | 'null'
  | INTEGER_LITERAL
  | FLOATING_POINT_LITERAL
  | CHARACTER_LITERAL
  | STRING_LITERAL
  ;

Location
  : Variable
  | ObjectField
  | ArrayElement
  ;

ExtendedIdentifier
  : IDENTIFIER
  | ExtendedIdentifier '.' IDENTIFIER
  ;

ObjectField
  : Expression '.' Variable
  ;

Variable_opt
  : /* empty */
  | Variable
  ;

Variable
  : IDENTIFIER
  | VARIABLE
  ;

ArrayElement
  : Expression '[' Expressions ']'
  ;

FunctionCall
  : IDENTIFIER Arguments
  | ObjectField Arguments
  ;

Arguments
  : '(' Expressions_opt ')'
  ;

ClassExpression
  : ExtendedIdentifier '.' 'class'
  ;

IncDecExpression
  : IncDecOperator Location
  | IncDecOperator '(' Location ')'
  | Location IncDecOperator
  | '(' Location ')' IncDecOperator
  ;

AllocationExpression
  : 'new' AllocatedObject
  ;

AllocatedObject
  : ExtendedIdentifier Arguments
  | SimpleType ArrayDimensions ListExpression_opt
  ;

ArrayDimensions
  : ArrayDimension
  | ArrayDimensions ArrayDimension
  ;

ArrayDimension
  : '[' Expression_opt ']'
  ;

ListExpression_opt
  : /* empty */
  | ListExpression
  ;

BinaryOperatorExpression
  : Expression BinaryOperator Expression
  | Expression PartialRelationalExpression
  ;

PartialRelationalExpression
  : 'instanceof' ExtendedIdentifier
  | 'as' ExtendedIdentifier
  | 'in' InitializationExpression
  | RelationalOperator Expression
  ;

TestExpression
  : ReferentExpression RelativeTestExpression_opt
  | '!' TestExpression
  | '(' TestExpression ')'
  ;

ReferentExpression
  : Expression 
  | Variable ':' Expression
  ;

RelativeTestExpression
  : 'isknown'
  | 'isunknown'
  | PartialRelationalExpression
  | TemporalTestExpression
  | RelativeTestExpression '&' RelativeTestExpression
  | '&' RelativeTestExpression
  ;

RelativeTestExpression_opt
  : /* empty */
  | RelativeTestExpression
  ;

InitializationExpression
  : Expression
  | ListExpression
  ;

ListExpression
  : '{' InitializationExpressions '}'
  ;

InitializationExpressions
  : InitializationExpression
  | InitializationExpressions ',' InitializationExpression
  ;

IncDecOperator
  : '++'
  | '--'
  ;

UnaryOperatorExpression
  : '!' Expression
  | '+' Expression                                              %prec UNOP
  | '-' Expression                                              %prec UNOP
  ;

BinaryOperator
  : '||'
  | '&&'
  | '+'
  | '-'
  | '*'
  | '/'
  | '%'
  ;

RelationalOperator
  : '=='
  | 'equals'
  | '!='
  | '<'
  | '<='
  | '>'
  | '>='
  ;

TemporalTestExpression
  : 'occursin' TimeInterval
  | BeforeAfter TimeInterval_opt Expression
  ;

BeforeAfter
  : 'before'
  | 'after'
  ;

TimeInterval_opt
  : /* empty */
  | TimeInterval
  ;

TimeInterval
  : '[' TimeBound ',' TimeBound ']'
  ;

TimeBound
  : '$'
  | Expression
  ;

VariableDeclaration
  : TypedVariable Initialization_opt
  ;

Initialization_opt
  : /* empty */
  | Initialization
  ;

Initialization
  : '=' InitializationExpression
  ;

SetupDefinition_opt
  : /* empty */
  | SetupDefinition
  ;

SetupDefinition
  : 'setup' ActionStatement
  ;

ActionStatements_opt
  : /* empty */
  | ActionStatements
  ;

ActionStatements
  : ActionStatement
  | ActionStatements ActionStatement
  ;

ActionStatement
  : ActionStatementBlock Semicolon_opt
  | AssignmentStatement
  | BindStatement
  | CallStatement
  | AssertStatement
  | RetractStatement
  | UpdateStatement
  | ModifyStatement
  | ApplyStatement
  | IfStatement
  | ExecuteStatement
  | WhileStatement
  | ForeachStatement
  | ForStatement
  | ReturnStatement
  | BreakStatement
  | ContinueStatement
  | ThrowStatement
  | TryStatement
  | Error
  ;

ActionStatementBlock
  : '{' ActionStatements_opt '}'
  ;

AssignmentStatement
  : AssignmentForm Semicolon
  ;

AssignmentForm
  : IncDecExpression
  | Location AssignmentOperator Expression
  ;

AssignmentOperator
  : '='
  | '+='
  | '-='
  | '*='
  | '/='
  | '%='
  | '&='
  | '|='
  ;  

BindStatement
  : BindingForm Semicolon
  ;

BindingForm
  : VariableBinding
  | VariableDeclaration
  ;

VariableBinding
  : BindVar Variable Initialization
  ;

BindVar
  : 'bind'
  | 'var'
  ;

CallStatement
  : FunctionCall Semicolon
  ;

Expressions_opt
  : /* empty */
  | Expressions
  ;

Expressions
  : Expression
  | Expressions ',' Expression
  ;

AssertStatement
  : AssertCommand AssertableExpression
  ;

AssertCommand
  : 'assert'
  | 'insert'
  ;

AssertableExpression
  : Logical_opt AssertionValueSettings
  | Logical_opt 'event' AssertedEvent
  ;

Logical_opt
  : /* empty */
  | 'logical'
  ;

AssertionValueSettings
  : Expression ValueSettings
  ;

AssertedEvent
  : ExtendedIdentifier ValueSettings
  | ExtendedIdentifier Arguments ValueSettings
  | '(' Expression ')' AssertedEventInitialization
  ;

AssertedEventInitialization
  : ValueSettings
  | AssertionValueSettings
  ;

ValueSettings
  : Semicolon
  | SettingStatementsBlock Semicolon_opt
  ;

SettingStatementsBlock
  : '{' SettingStatements_opt '}'
  ;

SettingStatements_opt
  : /* empty */
  | SettingStatements
  ;

SettingStatements
  : SettingStatement
  | SettingStatements SettingStatement
  ;

SettingStatement
  : SettingForm Semicolon
  ;

SettingForm
  : AssignmentForm
  | BindingForm
  | FunctionCall
  ;

RetractStatement
  : 'retract' Expression Semicolon
  ;

UpdateStatement
  : 'update' Refresh_opt Expression Semicolon
  ;

ModifyStatement
  : 'modify' Refresh_opt Expression ValueSettings
  ;

Refresh_opt
  : /* empty */
  | 'refresh'
  ;

ApplyStatement
  : 'apply' Expression ValueSettings
  ;

ExecuteStatement
  : 'execute' ActionStatement
  ;

IfStatement
  : 'if' '(' TestExpression ')' ActionStatement ElseStatement_opt
  ;

ElseStatement_opt
  : /* empty */
  | 'else' ActionStatement
  ;

WhileStatement
  : 'while' '(' TestExpression ')' ActionStatement
  ;

ForeachStatement
  : 'foreach' '(' TypedVariable 'in' Expression ')' ActionStatement
  ;

ForStatement
  : 'for' '(' SettingForms_opt Semicolon TestExpression_opt Semicolon SettingForms_opt ')'
    ActionStatement
  ;

SettingForms_opt
  : /* empty */
  | SettingForms
  ;

SettingForms
  : SettingForm
  | SettingForms ',' SettingForm
  ;

TestExpression_opt
  : /* empty */
  | TestExpression
  ;

TryStatement
  : 'try' ActionStatementBlock ExceptionHandling
  ;

ExceptionHandling
  : CatchClauses Finally_opt
  | Finally
  ;

CatchClauses
  : CatchClause
  | CatchClauses CatchClause
  ;

CatchClause
  : 'catch' '(' TypedObjectVariable ')' ActionStatementBlock
  ;

Finally_opt
  : /* empty */
  | Finally
  ;

Finally
  : 'finally' ActionStatementBlock
  ;

ThrowStatement
  : 'throw' Expression Semicolon
  ;

ReturnStatement
  : 'return' Expression_opt Semicolon
  ;

BreakStatement
  : 'break' Semicolon
  ;

ContinueStatement
  : 'continue' Semicolon
  ;

TimeoutStatements_opt
  : /* empty */
  | TimeoutStatements
  ;

TimeoutStatements
  : TimeoutStatement
  | TimeoutStatements TimeoutStatement
  ;

TimeoutStatement
  : 'timeout' Variable ActionStatement
  ;

RulesetElementDefinitions_opt
  : /* empty */
  | RulesetElementDefinitions
  ;

RulesetElementDefinitions
  : RulesetElementDefinition
  | RulesetElementDefinitions RulesetElementDefinition
  ;

RulesetElementDefinition
  : FunctionDefinition
  | RuleDefinition
  | TaskDefinition
  | Error
  ;

FunctionDefinition
  : 'function' TypedIdentifier FunctionParameters '{' ActionStatements_opt '}' Semicolon_opt
  ;

FunctionParameters
  : '(' FormalParameters_opt ')'
  ;

FormalParameters_opt
  : /* empty */
  | FormalParameters
  ;

FormalParameters
  : TypedVariable
  | FormalParameters ',' TypedVariable
  ;  

RuleDefinition
  : 'rule' ExtendedIdentifier '{' RuleBody '}' Semicolon_opt
  ;

RuleBody
  : RuleParameters_opt  RuleCondition RuleAction
  ;

RuleParameters_opt
  : /* empty */
  | RuleParameters
  ;

RuleParameters
  : RuleParameter
  | RuleParameters RuleParameter
  ;

RuleParameter
  : PropertyDeclaration
  | 'priority' '=' Expression Semicolon
  | 'packet' '=' ExtendedIdentifier Semicolon
  ;

RuleCondition
  : 'when' '{' RulePatterns '}'
  ;

RuleAction
  : 'then' '{' ActionStatements_opt TimeoutStatements_opt '}' ElseActions_opt
  ;

ElseActions_opt
  : /* empty */
  | 'else' '{' ActionStatements_opt TimeoutStatements_opt '}'
  ;
  
RulePatterns
  : InitialPattern Patterns_opt
  ;

Patterns_opt
  : /* empty */
  | Patterns
  ;

Patterns
  : Pattern
  | Patterns Pattern
  ;

Pattern
  : InitialPattern
  | Evaluate
  | Wait
  ;

InitialPattern
  : NotPattern
  | ExistsPattern
  | TaggablePattern
  ;

TaggablePattern
  : TaggableObjectPattern
  | TaggableCollectPattern
  ;

TaggableObjectPattern
  : ObjectPattern
  | Variable ':' ObjectPattern
  ;
  
TaggableCollectPattern
  : CollectPattern
  | Variable ':' CollectPattern
  ;

ObjectPattern
  : ObjectPatternExpression Semicolon
  ;

ObjectPatternExpression
  : ObjectType ObjectQualification
  | 'event' ObjectType ObjectQualification
  ;

ObjectQualification
  : '(' TestExpressions_opt ')' Provenance_opt
  ;

TestExpressions_opt
  : /* empty */
  | TestExpressions Semicolon_opt
  ;

TestExpressions
  : TestExpression
  | TestExpressions Semicolon TestExpression
  ;

Provenance_opt
  : /* empty */
  | Provenance
  ;

Provenance
  : FromIn Expression
  ;

FromIn
  : 'from'
  | 'in'
  ;

Evaluate
  : 'evaluate' '(' TestExpressions ')' Semicolon
  ;

Wait
  : WaitCondition
  | Variable ':' WaitCondition
  ;

WaitCondition
  : 'wait' Logical_opt UntilClause_opt WaitPatterns
  ;

UntilClause_opt
  : /* empty */
  | Until_opt Expression
  ;

Until_opt
  : /* empty */
  | 'until'
  ;

WaitPatterns
  : Semicolon
  | '{' InitialPatterns_opt '}'
  ;

InitialPatterns_opt
  : /* empty */
  | InitialPatterns
  ;

InitialPatterns
  : InitialPattern
  | InitialPatterns InitialPattern
  ;

NotPattern
  : 'not' ObjectPattern
  ;

ExistsPattern
  : 'exists' ObjectPattern
  ;

CollectPattern
  : 'collect' Collector_opt ObjectPatternExpression WhereClause_opt Semicolon
  ;

Collector_opt
  : /* empty */
  | '(' Expression_opt ')'
  ;

WhereClause_opt
  : /* empty */
  | 'where' '(' TestExpressions ')'
  ;

Semicolon_opt
  : /* empty */
  | Semicolon 
  ;

Semicolon
  : ';'
  ;

TypedIdentifier
  : Type IDENTIFIER
  ;

TypedVariable
  : Type Variable
  ;

TypedObjectVariable
  : ExtendedIdentifier Variable
  ;

Type
  : SimpleType
  | ArrayType
  ;

SimpleType
  : PrimitiveType
  | ExtendedIdentifier
  ;

ObjectType
  : ExtendedIdentifier
  | ArrayType
  ;

ArrayType
  : SimpleType Brackets
  ;

PrimitiveType
  : 'int'
  | 'byte'
  | 'short'
  | 'long'
  | 'float'
  | 'double'
  | 'char'
  | 'boolean'
  | 'void'
  ;

Brackets
  : '[' ']'
  | Brackets '[' ']'
  ;

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

// All the rules above concern IRL programs that do not contain
// any taskflow constructs. Below are the additional rules for
// taskflows.

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

TaskDefinition
  : RuleTaskDefinition
  | FunctionTaskDefinition
  | FlowTaskDefinition
  ;

RuleTaskDefinition
  : 'ruletask' IDENTIFIER '{' RuleTasks_opt '}' Semicolon_opt
  ;

FunctionTaskDefinition
  : 'functiontask' IDENTIFIER '{' FunctionTasks_opt '}' Semicolon_opt
  ;

FlowTaskDefinition
  : 'flowtask' IDENTIFIER '{' FlowTasks_opt '}' Semicolon_opt
  ;

RuleTasks_opt
  : /* empty */
  | RuleTasks
  ;

FunctionTasks_opt
  : /* empty */
  | FunctionTasks
  ;

FlowTasks_opt
  : /* empty */
  | FlowTasks
  ;

RuleTasks
  : RuleTask
  | RuleTasks RuleTask
  ;

FunctionTasks
  : FunctionTask
  | FunctionTasks FunctionTask
  ;

FlowTasks
  : FlowTask
  | FlowTasks FlowTask
  ;

RuleTask
  : 'body' RuleTaskBody
  | 'ordering' '=' IDENTIFIER Semicolon
  | 'firing' '=' IDENTIFIER Semicolon
  | 'firinglimit' '=' INTEGER_LITERAL Semicolon
  | 'agendafilter' '=' AgendaFilter
  | 'iterator' '=' Expression Semicolon
  | 'algorithm' '=' IDENTIFIER Semicolon
  | 'matchedclasses' MatchingSpecification
  | TaskConfiguration
  ;

FunctionTask
  : 'body' Eq_opt ActionStatementBlock Semicolon_opt
  | TaskConfiguration
  ;

FlowTask
  : 'body' Eq_opt FlowStatementBlock Semicolon_opt
  | TaskConfiguration
  ;

RuleTaskBody
  : '=' SelectOperator '(' Variable_opt ')'
    ActionStatementBlock Semicolon_opt Selection_opt Semicolon_opt
  | Eq_opt '{' RuleList_opt '}' Semicolon_opt
  ;

SelectOperator
  : 'select'
  | 'dynamicselect'
  ;

Selection_opt
  : /* empty */
  | 'in' Expression
  ;

RuleList_opt
  : /* empty */
  | ExtendedIdentifierList
  ;

ExtendedIdentifierList
  : ExtendedIdentifier
  | ExtendedIdentifierList ',' ExtendedIdentifier
  ;

AgendaFilter
  : 'filter' '(' Variable ')' ActionStatementBlock Semicolon_opt
  | Expression Semicolon
  ;

MatchingSpecification
  : '=' Expression Semicolon
  | Eq_opt '{' ExtendedIdentifierList '}' Semicolon_opt
  ;

Eq_opt
  : /* empty */
  | '='
  ;

FlowStatementBlock
  : '{' FlowStatements_opt '}'
  ;

FlowStatements_opt
  : /* empty */
  | FlowStatements
  ;

FlowStatements
  : FlowStatement
  | FlowStatements FlowStatement
  ;

FlowStatement
  : IDENTIFIER Semicolon
  | FlowStatementBlock
  | TaskStatement
  | WhileFlowStatement
  | SwitchFlowStatement
  | IfFlowStatement
  | ForkFlowStatement
  | GotoStatement
  | BreakStatement
  | ContinueStatement
  | Error
  ;

TaskStatement
  : IDENTIFIER ':' ExtendedIdentifier Semicolon
  ;

WhileFlowStatement
  : 'while' '(' TestExpression ')' FlowStatement
  | IDENTIFIER ':' 'while' '(' TestExpression ')' FlowStatement
  ;

SwitchFlowStatement
  : 'switch' '(' Expression ')' '{' Cases_opt '}'
  | IDENTIFIER ':' 'switch' '(' Expression ')' '{' Cases_opt '}'
  ;

Cases_opt
  : /* empty */
  | Cases
  ;

Cases
  : Case
  | Cases Case
  ;

Case
  : CaseTag ':' FlowStatement
  ;

CaseTag
  : 'case' INTEGER_LITERAL
  | 'default'
  ;

IfFlowStatement
  : 'if' '(' TestExpression ')' FlowStatement ElseFlowStatement_opt
  | IDENTIFIER ':' 'if' '(' TestExpression ')' FlowStatement ElseFlowStatement_opt
  ;

ElseFlowStatement_opt
  : /* empty */
  | ElseFlowStatement
  ;

ElseFlowStatement
  : 'else' FlowStatement
  ;

ForkFlowStatement
  : 'fork' Branches Semicolon_opt
  | IDENTIFIER ':' 'fork' Branches Semicolon_opt
  ;

Branches
  : FlowStatementBlock
  | Branches '&&' FlowStatementBlock
  ;

GotoStatement
  : 'goto' IDENTIFIER Semicolon
  ;

TaskConfiguration
  : PropertyDeclaration
  | InitialFinal Eq_opt ActionStatementBlock Semicolon_opt
  | 'completionflag' '=' Expression Semicolon
  ;

InitialFinal
  : 'initialaction'
  | 'finalaction'
  ;

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

// Error recovery rules

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

Error
  : error { ErrorManager.ReportErrors(true); } ErrorRecoverySymbol
  ;
    
ErrorRecoverySymbol
  : Semicolon
  | '}'
  ;

%%
