// FILE. . . . . d:/hak/hlt/src/hlt/fot/fuz/syntax/sources/fff-grammar-rules.grm
// EDIT BY . . . Hassan Ait-Kaci
// ON MACHINE. . Hak-Laptop
// STARTED ON. . Tue Aug 21 05:18:27 2018

// Last modified on Thu Aug 15 17:06:41 2019 by hak

%%

/**
 * Interaction
 */

Session
        : Clauses Exit
        | Exit
        ;

Clauses
        : Clause
        | Clauses Clause
        ;

Clause
        : Pragma
        {
          executePragma();
          FuzzyFOTLatticeTokenizer.prompt();
        } ';'
        | SimilarityDegree
        {
          processSimilarityDegree();
          FuzzyFOTLatticeTokenizer.prompt();
        } ';'
        | Unification
        {
          processUnification();
          FuzzyFOTLatticeTokenizer.prompt();
        } ';'
        | Generalization
        {
          processGeneralization();
          FuzzyFOTLatticeTokenizer.prompt();
        } ';'
        | error
        {
          // errorManager().reportErrors(true);
          FuzzyFOTLatticeTokenizer.prompt();
        } ';'
        ;

Exit
        : 'exit'
        {
          out.println();
	  out.println("------------------------------------------------------------------------");
	  out.println("*** Ending FFF session on "+ (new Date()));
	  out.println("------------------------------------------------------------------------");
	  // out.println("*** ");
          // out.println("*** So long - and thanks for using FFF...");
          // out.println("*** Come back soon for some more Fun Fuzzy Fiddling! 8^D");
          out.println();
          System.exit(0);
        } ';'
        ;

/**
 * Pragmas
 */

Pragma
        : InfoPragma
        | FunPragma
        | SigPragma
        | SimPragma
        | ClosePragma
        | ShowPragma
        | FunclassPragma
        | TermclassPragma
        | FunrepPragma
        | TermrepPragma
        | MapPragma // not yet done
        | CompPragma // not yet done
        | LoadPragma
        | TracePragma
        | ResetPragma
        ;

/* ******************************************************************** */

// InfoPragma

InfoPragma
        : INFO PragmaName_opt
        ;

PragmaName_opt
        : /* empty */
        {
          infoPragmaName = "";
          inputClause = "";
        }
        | PragmaName
        {
          infoPragmaName = $1.svalue();
          // System.err.println("&&& reading infoPragmaName = "+infoPragmaName);
          inputClause += " "+infoPragmaName;
	  // System.err.println("&&& READ "+infoPragmaName+" setting inputClause = "+inputClause);
        }
        ;

PragmaName
        : INFO
        | FUN
        | SIG
        | SIM
        | CLOSE
        | SHOW
        | FUNCLASS
        | TERMCLASS
        | FUNREP
        | TERMREP
        | MAP
        | COMP
        | LOAD
        | TRACE
        | RESET
        ;  

/* ******************************************************************** */

// FunPragma

FunPragma
        : FUN
        {
          inputClause = "";
        }
          FunctorsArities_opt
        ;

FunctorsArities_opt
        : /* empty */
        | FunctorsArities
        ;

FunctorsArities
        : FunctorArity
        | FunctorsArities FunctorArity
        ;

FunctorArity
        : FUNCTOR SlashOpt NATURAL
        {
          inputClause += " "+$1.svalue()+"/"+(int)$3.nvalue();
          try
            {
              // if one is already registered under this name but not with this
              // arity the following will raise a BadFunctorArityException;
              // otherwise, it will register it and check need to recompute similarity:
              registerFunctor($1.svalue(),signature.functor($1.svalue(),(int)$3.nvalue()));
            }
          catch (Exception e)
            { // we need to report whether this functor was already
              // declared with a different arity
              err.println("!!! "+e.getMessage()+
                          " (declaration "+$1.svalue()+"/"+(int)$3.nvalue()+" ignored)");
            }
        }
        ;

SlashOpt
        : /* empty */
        | '/'
        ;

/* ******************************************************************** */

// SigPragma

SigPragma
        : SIG
        ;

SimPragma
        : SIM
        {
          inputClause = "";
        }
          FuzzyPairs_Opt
        ;

FuzzyPairs_Opt
        : /* empty */
        | FuzzyPairs
        ;

FuzzyPairs
        : FuzzyPair
        | FuzzyPairs FuzzyPair
        ;

FuzzyPair
        : FUNCTOR FUNCTOR FUZZYVAL
        {
          inputClause += " "+$1.svalue()+" "+$2.svalue()+" "+$3.nvalue();
          declareSimilarPair($1.svalue(),$2.svalue(),$3.nvalue());
	  $$.left = $1.svalue();
	  $$.right = $2.svalue();
	  $$.degree = $3.nvalue();
        }
        ;

/* ******************************************************************** */

// ClosePragma

ClosePragma
        : CLOSE
        ;

/* ******************************************************************** */

// ShowPragma

ShowPragma
        : SHOW
        ;

/* ******************************************************************** */

// FunclassPragma

FunclassPragma
        : FUNCLASS FUNCTOR FUZZYVAL
        {
          $$.setSvalue($1.svalue());
          functorName = $2.svalue();
          classDegree = $3.nvalue();
        }
        ;

/* ******************************************************************** */

// TermclassPragma

TermclassPragma
        : TERMCLASS Term NaturalOrFuzzyval
        {
          $$.setSvalue($1.svalue());
          functorName = $2.svalue();
          classDegree = $3.nvalue();

          temp = (SyntacticTerm)termStack.pop();
          try
            { // we need to report if a functor is used with
              // inconsistent arities converting the parsed
              // SyntacticTerm temp into its FirstOrderTerm object's
              // canonical form
              term = temp.canonical(signature,functorTable);
            }
          catch (Exception e)
            {
              err.println("!!! "+e.getMessage());
              // recoverFromError();
              // FuzzyFOTLatticeTokenizer.prompt();
            }
        }
        ;

NaturalOrFuzzyval
        : NATURAL
        | FUZZYVAL
        ;

/* ******************************************************************** */

// FunrepPragma

FunrepPragma
        : FUNREP FUNCTOR FUZZYVAL
        {
          $$.setSvalue($1.svalue());
          functorName = $2.svalue();
          classDegree = $3.nvalue();
        }
        ;

/* ******************************************************************** */

// TermrepPragma

TermrepPragma
        : TERMREP Term FUZZYVAL
        {
          $$.setSvalue($1.svalue());
          functorName = $2.svalue();
          classDegree = $3.nvalue();

          try
            { // we need to report if a functor is used with
              // inconsistent arities converting the parsed
              // SyntacticTerm into its FirstOrderTerm object's
              // canonical form
              term = ((SyntacticTerm)termStack.pop()).canonical(signature,functorTable);
            }
          catch (Exception e)
            {
              err.println("!!! "+e.getMessage());
              recoverFromError();
              FuzzyFOTLatticeTokenizer.prompt();
            }
        }
        ;

/* ******************************************************************** */

// MapPragma

MapPragma
        : MAP
        {
          inputClause = "";
        }
          MapPragmaData_opt
        ;

MapPragmaData_opt
        : /* empty */
        | MapPragmaData
        ;

MapPragmaData
        : FuzzyPair MapPairs_opt
        {
          inputClause += " "+ArgumentMappingData.pairsToString(declaredPairMapList);
	  // record the argument-position map for the fuzzy pair:
	  declaredMaps.add(new ArgumentMappingData(signature.functor($1.left),
						   signature.functor($1.right),
						   $1.degree,
						   declaredPairMapList));
	  // reset declared pairs to a new empty list to record the next set of pairs:
	  declaredPairMapList = new IntArrayList();
        }
        ;

MapPairs_opt
        : /* empty */
        | MapPairs
        ;

MapPairs
        : MapPair MapPairs_opt
        ;

MapPair
        : NATURAL ':' NATURAL
        {
          declaredPairMapList.add((int)$1.nvalue());
          declaredPairMapList.add((int)$3.nvalue());
        }
        ;

/* ******************************************************************** */

// CompPragma

CompPragma
        : COMP
        ;

/* ******************************************************************** */

// LoadPragma

LoadPragma
        : LOAD STRING
        {
          fileStack.push($2.svalue());
          // out.println(">>> fileStack = "+fileStack);
          $$.setSvalue($1.svalue());
        }
        ;

/* ******************************************************************** */

// TracePragma

TracePragma
        : TRACE LevelOpt
        ;

LevelOpt
        : /* empty */
        | NATURAL
        {
          SignatureSimilarity.setTracingVerbosity(tracingVerbosity = (int)$1.nvalue());
        }  
        ;

/* ******************************************************************** */

// ResetPragma

ResetPragma
        : RESET
        ;

/* ******************************************************************** */

// FOT operations and FOTs

SimilarityDegree
        : LhsTerm EQS RhsTerm
        ;

Unification
        : LhsTerm INF RhsTerm
        ;

Generalization
        : LhsTerm SUP RhsTerm
        ;

LhsTerm
        :
        {
          termStack.clear();
          Variable.resetRegisteredVariables();
        }
          Term
        {
          try
            { // we need to report if a functor is used with
              // inconsistent arities converting the parsed
              // SyntacticTerm object into its FirstOrderTerm object's
              // canonical form
              lhs = ((SyntacticTerm)termStack.pop()).canonical(signature,functorTable);
            }
          catch (Exception e)
            {
              err.println("!!! "+e.getMessage());
              recoverFromError();
              FuzzyFOTLatticeTokenizer.prompt();
            }
        }
        ;

RhsTerm
        :
        {
          termStack.clear();
        }
          Term
        {
          try
            { // we need to report if a functor is used with
              // inconsistent arities converting the parsed
              // SyntacticTerm object into its FirstOrderTerm object's
              // canonical form
              rhs = ((SyntacticTerm)termStack.pop()).canonical(signature,functorTable);
            }
          catch (Exception e)
            {
              err.println("!!! "+e.getMessage());
              // recoverFromError();
              // FuzzyFOTLatticeTokenizer.prompt();
            }
        }
        ;

Term
        : VARIABLE
        { 
          termStack.push(new SyntacticTerm($1.svalue()).markAsVariable());
        }
        | Structure
        | '(' Term ')'
        ;

Structure
        : FUNCTOR
        { 
          termStack.push(new SyntacticTerm($1.svalue()));
        }
        | FUNCTOR '('
        { 
          termStack.push(new SyntacticTerm($1.svalue(),new Vector()));
        }
          Body ')'
        ;

Body
        : Term
        { 
          temp = (SyntacticTerm)termStack.pop();
          ((SyntacticTerm)termStack.peek()).body.add(temp);
        }
        | Body ',' Term
        { 
          temp = (SyntacticTerm)termStack.pop();
          ((SyntacticTerm)termStack.peek()).body.add(temp);
        }
        ;

/* ************************************************************************ */
