#
# Drools DRL Syntax definitions for Ebnf2eps
#
# V 1.0 for Drools 5.2.0

CompilationUnit = [ "package" QualifiedName [ ";" ]  ] { Definition [ ";" ] } ;

Definition =
    ( RuleAttribute
    | ImportDefinition
    | GlobalDefinition
    | FunctionDefinition
    | TypeDefinition
    | RuleDefinition
    | QueryDefinition
    );

ImportDefinition =
    "import" [ "function" | "static" ] QualifiedName [ "." "*" ] ;

GlobalDefinition = "global" Type Identifier ;

FunctionDefinition = "function" [ Type ] Identifier Parameters Block ;

Parameters = "(" [ ( Type Identifier { "[" "]" } ) / "," ] ")" ;

TypeDefinition = "declare" QualifiedName TypeOptions { Field } "end" ;

TypeOptions =  [ "extends" QualifiedName ] { Annotation } ;

Annotation =
    "@" Identifier [ "(" ( Tokens | ( Identifier "=" Value ) / "," ) ")" ] ;

Value =
    ( "{" [ Value / "," ] "}"
    | ConditionalExpr
    );

Field =
    Identifier ":" QualifiedName [ "=" ConditionalExpr ]
    { Annotation } [ ";" ] ;

QueryDefinition = "query" StringId  QueryOptions { ConditionalOr } "end" ;

QueryOptions = [ Parameters | Placeholders ] { Annotation } ;

Placeholders =  "(" [ Identifier / "," ] ")" ;

RuleDefinition =
    "rule" StringId RuleOptions
    [ WhenPart ] ThenPart
    ;

RuleOptions = 
    [ "extends" StringId ]
    { Annotation } [ RuleAttributes ] 
    ;

WhenPart = "when" [ ":" ] { ConditionalOr } ;

RuleAttributes = [ "attributes" [ ":" ] ] [ RuleAttribute / [ "," ] ] ;

RuleAttribute =
      "salience" ConditionalExpr
    | "enabled" ConditionalExpr
    | ( "auto-focus"
      | "no-loop"
      | "lock-on-active" ) [ BooleanLiteral ]
    | ( "agenda-group"
      | "activation-group"
      | "date-effective"
      | "date-expires"
      | "dialect"
      | "ruleflow-group" ) StringLiteral
    | "timer"    "(" Tokens ")"
    | "calendars" StringLiteral / ","
    ;

ConditionalOr = ConditionalAnd / "or" ;

ConditionalAnd = ConditionalElement / "and" ;

ConditionalElement =
    (    ( "exists" | "not" ) ( BindingPattern | "(" ConditionalOr ")" )
    |    "eval"   "(" ConditionalExpr ")"
    |    "forall" "(" BindingPattern+ ")"
    |    "accumulate" "(" ConditionalAnd [ "," ] Accumulations ")"
    |    "(" ConditionalOr ")"
    |    BindingPattern
    ) [ ";" ]
    ;


# lhsPatternBind
BindingPattern =
    [ Identifier ":" ] ( SourcePattern | "(" SourcePattern / "or" ")" ) ;

# lhsPattern
SourcePattern =
    Pattern
    [ OverClause ]
    [ "from" ( ConditionalOrExpr
             | "collect" "(" BindingPattern ")"
             | "entry-point" StringId
             | AccumulateClause
             ) ]
    ;

# lhsPattern
Pattern = 
    [ "?" ] QualifiedName "(" [ Constraints ] ")" ;

OverClause =
    "over" Identifier ":" Identifier "(" [ ConditionalExpr / "," ] ")" ;

Accumulations =  ( Identifier ":"  AccumulateFunction ) / "," ;

AccumulateClause =
    "accumulate"
    "(" ConditionalAnd [ "," ]
    (  AccumulateSteps |  AccumulateFunction ) ")"
    ;

AccumulateSteps =
    AccumulateInit AccumulateAction [ AccumulateReverse ] AccumulateResult ;

AccumulateInit = "init" "(" { Statement } ")" [ "," ] ;
AccumulateAction = "action" "(" { Statement } ")" [ "," ] ;
AccumulateReverse = "reverse" "(" { Statement } ")" [ "," ] ;
AccumulateResult =  "result" "(" ConditionalExpr ")" ;

AccumulateFunction = Identifier "(" { ConditionalExpr / "," } ")" ;

### Snippets for manual

ConditionalElementEval = "eval"   "(" ConditionalExpr ")" ;
ConditionalElementExists = "exists" ( BindingPattern | "(" ConditionalOr ")" ) ;
ConditionalElementNot = "not" ( BindingPattern | "(" ConditionalOr ")" ) ;
ConditionalElementForall = "forall" "(" BindingPattern+ ")" ;
ConditionalElementAccumulate =
    "accumulate" "(" ConditionalAnd [ "," ] Accumulations  ")" ;

FromClause = "from" ConditionalOrExpr ;
FromCollectClause = "from" "collect" "(" SourcePattern ")" ;
FromAccumulateClause = "from" AccumulateClause ;
###

Constraints =
    [ ( ConditionalOrExpr / "," ) ";" ]
    [ ConditionalOrExpr / "," ] ;

ThenPart = "then" { RhsStatement } "end" ;

RhsStatement = 
      ModifyStatement
    | Statement
    ;

ModifyStatement =
    "modify" "(" ConditionalExpr ")"
    "{" { ConditionalExpr / "," } "}"
    ;

Block =  "{" { Statement } "}" ;

QualifiedName = Identifier / "." ;


Expression = ConditionalExpr [ AssignmentOperator Expression ] ;

ConditionalExpr =
    ConditionalOrExpr [ "?" Expression ":" Expression ];

ConditionalOrExpr =
   (((( (InstanceOfExpr / ( "==" | "!=" ) ) / "&" ) / "^" ) / "|" ) / "&&" ) / "||" ;

# ConditionalOrExpr = ConditionalAndExpr / "||" ;
# ConditionalAndExpr = InclusiveOrExpr / "&&" ;
# InclusiveOrExpr = ExclusiveOrExpr / "|" ;
# ExclusiveOrExpr = AndExpr / "^" ;
# AndExpr = EqualityExpr / "&" ;
# EqualityExpr = InstanceOfExpr / ( "==" | "!=" ) ;

InstanceOfExpr = InExpr [ "instanceof" Type ] ;

InExpr = RelationalExpr [ "not" ] "in" "(" Expression / "," ")" ;

RelationalExpr = ShiftExpr { OrRestriction } ;

OrRestriction = ( SingleRestriction / "&&" ) / "||" ;

# OrRestriction = AndRestriction / "||" ;
# AndRestriction = SingleRestriction / "&&" ;

SingleRestriction =
    ( RelationalOperator ShiftExpr
    | "(" OrRestriction ")"
    );

ShiftExpr = AdditiveExpr / ( "<<" | ">>" | ">>>" ) ;

AdditiveExpr =
    ( UnaryExpr / ( "*" | "/" | "%" ) ) / ( "+" | "-" ) ;

# AdditiveExpr = MultiplicativeExpr / ( "+" | "-" ) ;
# MultiplicativeExpr = UnaryExpr / ( "*" | "/" | "%" ) ;

UnaryExpr = 
    ( ( "+"  | "-"  ) UnaryExpr
    | ( "++" | "--" ) Primary
    | UnaryExprNotPlusMinus
    );

UnaryExprNotPlusMinus =
    ( ( "~" 
      |  "!" 
      | "(" ( PrimitiveType | Type ) ")" 
      ) UnaryExpr
    | [ Identifier ( ":" | ":=" ) ] Primary [ "++" | "--" ]
    );

PrimitiveType =
    ( "boolean"
    | "char"
    | "byte"
    | "short"
    | "int"
    | "long"
    | "float"
    | "double"
    );

Primary =
    ( "(" Expression ")"
    | NonWildcardTypeArguments ( ExplicitGenericInvocationSuffix | "this" Arguments )
    | Literal
    | "super" SuperSuffix 
    | "new" Creator 
    | PrimitiveType { "[" "]" } "." "class" 
    | "void" "." "class" 
    | "this"
    | InlineMapExpr 
    | InlineListExpr
    | ( Identifier / "." ) [ IdentifierSuffix ]
    );

InlineListExpr = "[" [ ExpressionList ]  "]"  ;
    
InlineMapExpr = "[" ( ( Expression ":" Expression ) / "," )  "]"  ;

IdentifierSuffix = 
    ( ( "[" "]" )+ "." "class"
    | ( "[" Expression "]" )+
    | Arguments 
    );

Creator = 
    [ NonWildcardTypeArguments ] CreatedName
    ( ArrayCreatorRest | Arguments )
    ;

CreatedName =
    ( ( Identifier [ TypeArguments ] ) / "." 
    | PrimitiveType
    );

InnerCreator = Identifier Arguments ;

ArrayCreatorRest =  
    (   ( "[" "]" )+ ArrayInitializer
    |   ( "[" Expression "]" )+ { "[" "]" }
    )
    ;

VariableInitializer = ArrayInitializer | Expression ;

ArrayInitializer = "{" [ { VariableInitializer / "," } [ "," ] ] "}" ;

ExplicitGenericInvocation = NonWildcardTypeArguments Arguments ;

NonWildcardTypeArguments = "<" ( Type / "," ) ">" ;

ExplicitGenericInvocationSuffix =
    ( "super" SuperSuffix
    | Identifier Arguments
    );

Selector =
    ( "." "super" SuperSuffix
    | "." "new" [ NonWildcardTypeArguments ] InnerCreator
    | "." Identifier [ Arguments ]
    | "[" Expression "]"  
    );

SuperSuffix = 
    ( Arguments
    | "." Identifier [ Arguments ] 
    );

Arguments = "(" [ ExpressionList ] ")" ;

ExpressionList = Expression / "," ;

AssignmentOperator =
  ( "="
  | "+="
  | "-="
  | "*="
  | "/="
  | "&="
  | "|="
  | "^="
  | "%="
  | "<<="
  | ">>>="
  | ">>="
  );

RelationalOperator =
  ( "=="
  | "!="
  | "<="
  | ">="
  | "<"
  | ">"
  | [ "not" ] Identifier [ "[" [ ExpressionList ] "]" ]
  );


#
# Type
#

Type =
    ( PrimitiveType { "[" "]" }
    | ( ( Identifier [ TypeArguments ] ) / "." )  { "[" "]" }
    );

TypeArguments = "<" ( TypeArgument / "," ) ">" ;

TypeArgument =
    (	Type
    |	"?" [ ( "extends" | "super" ) Type ]
    );


Literal =
    ( IntLiteral
    | RealLiteral
    | BooleanLiteral
    | StringLiteral 
    );


StringId =
    ( Identifier
    | StringLiteral
    );

BooleanLiteral = "true" | "false" ;

IntLiteral = [ "+" | "-" ] ( Digit+ | "0x" ( Digit | "'a'..'f'" | "'A'..'F'" )+ ) ;

RealLiteral =  [ "+" | "-" ]
      ( ( Fraction [ Exponent ]
        | Digit+ Exponent
        ) [ RealTypeSuffix ]
      | Digit+ RealTypeSuffix
      )
    ;

Fraction = Digit+ "." { Digit } | "." Digit+  ;

Exponent = ( "e" | "E" ) [ "+" | "-" ] Digit+ ;

RealTypeSuffix = "f" | "F" | "d" | "D" ;

Digit = "'0'..'9'" ;

StringLiteral = X ;

Identifier = X ;

Statement = X ;

X = "asinjava" ;

Tokens = X ;


