package GenRGenS.ratexpr;

import java_cup.runtime.*;
import java.util.*;
import java.math.*;
import GenRGenS.*;

/*********************************************************
 *         Fichiers de descriptions "RATIONAL"           *
 *********************************************************/

/* Declaration de variables et methodes utilitaires ... */
/** On effectue un premier passage dans le fichier de description afin de régler
 *  des conflits ingérable lors de l'interprétation effective du fichier
 */
parser code
{:

  private boolean _parseError = false;
  
  String getTexte() { return action_obj.getTexte(); }
  
  public void report_error(String message, Object info) {
    _parseError = true;
    if (info instanceof Symbol) {
      Symbol cur_token = (Symbol) info;
      if (cur_token.left != -1) {
      
        int[] coord_left = ((GenRGenSScanner) getScanner()).getRelativePos(
        	cur_token.left);
        int[] coord_right = ((GenRGenSScanner) getScanner()).getRelativePos(
        	cur_token.right);
        if (coord_left[0] == coord_right[0])
          GenRGenS.err.println("Syntax Error at line "+coord_right[0]+" chars "+
          coord_left[1] +"-" + coord_right[1]);
        else
          GenRGenS.err.println("Syntax Error from line "+coord_left[0]+" char "+
          coord_left[1] + " to line "+coord_right[0]+" char " + coord_right[1]);
      }
      else
        GenRGenS.err.println(
        	"Syntax Error, possibly because of a malformed clause !");
    }
    else
        GenRGenS.err.println(message);
  }
  public void report_fatal_error(String message, Object info) 
  	throws java.lang.Exception {
    _parseError = true;
    
   if (info instanceof Symbol) {
      Symbol cur_token = (Symbol) info;
      if (cur_token.left != -1) {
        int[] coord_left = ((GenRGenSScanner) getScanner()).getRelativePos(
        	cur_token.left);
        int[] coord_right = ((GenRGenSScanner) getScanner()).getRelativePos(
        	cur_token.right);
        if (coord_left[0] == coord_right[0])
          GenRGenS.err.println("Couldn't repair and continue parse at line "+
          coord_right[0]+".");
        else
          GenRGenS.err.println("Couldn't repair and continue parse at line "+
          coord_right[0]+".");
      }
      else
        GenRGenS.err.println("Couldn't repair and continue parse.");
    }
    else {
      Symbol current_token = cur_token;
      int[] coord_right = ((GenRGenSScanner) getScanner()).getRelativePos(
      	current_token.right);
      GenRGenS.err.println("Couldn't repair and continue parse at line "+
      coord_right[0]+".");
    }
    throw new Exception("Can't recover from previous error(s)");
  }

  public void syntax_error(Symbol cur_token) {
    report_error("Syntax error", cur_token);  
  }
  public void unrecovered_syntax_error(Symbol cur_token)
  	throws java.lang.Exception {
    report_fatal_error("Couldn't repair and continue parse", cur_token);  
  }
:}

action code
{:
  /** fichier recopié avec les modifications nécessaires */
  String _tmpFichier = "";
  boolean _isWord;
  
  String getTexte() { return _tmpFichier; }
  
  String ident(String s,String separ) {
	if (_isWord)
		return s;
	String res = "";
	for (int i = 0; i < s.length() ; i++) {
		res += s.charAt(i);
		if (i != s.length()-1)
			res += separ;
	}
	return res;
  }
:}


/* Declaration des  terminaux */

/* Tokens associés ?des mots-clés */

  /* Mots-clés généraux */
    terminal           TYPE,LANGUAGE,GRAMMAR,MARKOV,RATIONAL,PROSITE,MASTERFILE;
    terminal           SYMBOLS, WORDS, LETTERS;
    terminal           EQUALS, SEMI, VIRG, DBLPOINT, ARROW, ALIASES;
    /* ARROW est le mot cl?de sémantique : "est dériv?en ..." */

  /* Mot clés spécifiques de la génération "rationelle"" */
    terminal           OU, POINT, TIRET, PLUS, ETOILE, PUISS, EXPRESSION,
                       PARG, PARD, ACCG, ACCD, CROG, CROD;
    
  /* Mot clés spécifiques de la génération "grammaire"" */
    terminal           RULES, WEIGHTS;

  /* Mots-clés spécifiques aux fichiers de description de Markov */
    terminal           START, FREQUENCIES;
    terminal           ORDER, PHASE;

  /* Mots-clés spécifiques aux fichiers "maitres" */
    terminal           QUOTES, EXACT, POISSON;

/* Token "porteurs d'information" */
  terminal  Integer  ENTIER;
  terminal  Float    REEL;
  terminal  String   IDENT;
  terminal  String   STRING;



/* Non-terminals */
non terminal         RationalDescription, RationalDescriptionSuite;
non terminal         TypeDeclaration, LangageRationalDeclaration,
                     LangagePrositeDeclaration, SymbolTypeDeclaration;
non terminal         RationalDeclaration, PrositeDeclaration;
non terminal         WeightsDeclaration, WeightsList;
non terminal         AliasesDeclaration, AliasesList;

non terminal BigDecimal   Real;
non terminal String Expression, ExpressionProsite;


precedence left OU;
precedence left POINT, TIRET;
precedence nonassoc PLUS;
precedence nonassoc ETOILE;

precedence left PUISS;
precedence nonassoc PARG,PARD;
precedence left IDENT,REEL,ENTIER;




/* The grammar */

start with RationalDescription;


RationalDescription ::=
    TypeDeclaration RationalDescriptionSuite {: :}
;
  
TypeDeclaration ::=
    TYPE EQUALS RATIONAL   {: _tmpFichier += "TYPE = RATIONAL\n"; :}

  ;
  
RationalDescriptionSuite ::=
    LangageRationalDeclaration SymbolTypeDeclaration RationalDeclaration
    WeightsDeclaration AliasesDeclaration {: :}
   
   |LangagePrositeDeclaration SymbolTypeDeclaration PrositeDeclaration
    WeightsDeclaration AliasesDeclaration {: :}

  ;


LangageRationalDeclaration ::=
    LANGUAGE EQUALS RATIONAL  {: _tmpFichier += "LANGUAGE = RATIONAL\n"; :}

  ;

LangagePrositeDeclaration ::=
    LANGUAGE EQUALS PROSITE  {: _tmpFichier += "LANGUAGE = PROSITE\n"; :}

  ;

SymbolTypeDeclaration ::=
    SYMBOLS EQUALS WORDS   {:_tmpFichier+="SYMBOLS = WORDS\n";_isWord=true;   :}
  | SYMBOLS EQUALS LETTERS {:_tmpFichier+="SYMBOLS = LETTERS\n";_isWord=false;:}
  |                        {:_tmpFichier+="SYMBOLS = WORDS\n";_isWord=true;   :}
  ;

RationalDeclaration ::=
    EXPRESSION EQUALS Expression:e {:_tmpFichier += "EXPRESSION = "+e+"\n"; :}
  | EXPRESSION EQUALS {:
             parser.done_parsing();
             parser.report_error("You must define a rational expression !","");
                      :}
  |                   {:
             parser.done_parsing();
             parser.report_error("You must define a rational expression !","");
                      :}
  ;


Expression ::=
    Expression:e1 OU Expression:e2            {: RESULT = e1 + "|" + e2 ;     :}
  | Expression:e1 POINT Expression:e2         {: RESULT = e1 + "." + e2;      :}
  | Expression:e ETOILE                       {: RESULT = e + "*";            :}
  | Expression:e PLUS                         {: RESULT = e + "+";            :}
  | Expression:e PUISS Real:b                 {: RESULT = e + "^(" + b + ")"; :}
  | Expression:e PUISS PARG Real:b PARD       {: RESULT = e + "^(" + b + ")"; :}
  | Expression:e1 PUISS Real:b Expression:e2  {: RESULT = e1+"^("+b+")."+e2;  :}
  | Expression:e PUISS PARG Real:b1 VIRG Real:b2 PARD
  							                  {: RESULT =e+"^("+b1+","+b2+")";:}
  | PARG Expression:e PARD                    {: RESULT = "(" + e + ")";      :}
  | IDENT:s                                   {: RESULT = ident(s,".");           :}

  ;

PrositeDeclaration ::=
    EXPRESSION EQUALS ExpressionProsite:e {:_tmpFichier+="EXPRESSION = "+e+"\n";
                                          :}
  | EXPRESSION EQUALS {:
              parser.done_parsing();
              parser.report_error("You must define a rational expression !","");
                      :}
  |                   {:
              parser.done_parsing();
              parser.report_error("You must define a prosite expression !","");
                      :}
  ;


ExpressionProsite ::=
    IDENT:s 	                             {: RESULT = ident(s,"-");        :}  
  | CROG IDENT:s CROD                        {: RESULT = "[" + s + "]";       :}
  | ACCG IDENT:s ACCD                        {: RESULT = "{" + s + "}";       :}
  | ExpressionProsite:e PARG Real:b PARD     {: RESULT = e + "(" + b + ")";   :}
  | ExpressionProsite:e PARG Real:b1 VIRG Real:b2 PARD
                                             {: RESULT = e+"("+b1+","+b2+")"; :}

  | ExpressionProsite:e1 TIRET ExpressionProsite:e2
                                             {: RESULT = e1 + "-" + e2;       :}
  | PARG ExpressionProsite:e PARD            {: RESULT = "(" + e + ")";       :}
;


Real ::=
    REEL:f                {: RESULT = new BigDecimal(f.floatValue()); :}
  | ENTIER:n              {: RESULT = new BigDecimal(n.intValue());   :}
  ;

WeightsDeclaration ::=
    WEIGHTS EQUALS WeightsList:poids {: _tmpFichier += "WEIGHTS = "+poids+"\n";:}
  |                                  {: :}
  ;

WeightsList ::=
    IDENT:s Real:b WeightsList:p          {: RESULT = s + " " + b + "\n" + p; :}
  |                                       {: RESULT = ""; :}
  ;

AliasesDeclaration ::=
    ALIASES EQUALS AliasesList:aliases 
                    {: _tmpFichier += "ALIASES = " + aliases + "\n"; :}
  |                 {:  :}
  ;

AliasesList ::=
    AliasesList:aliases IDENT:i_src EQUALS IDENT:i_dest
                    {: RESULT = aliases + i_src + " = " + i_dest +"\n"; :}
  | IDENT:i_src EQUALS IDENT:i_dest
                    {: RESULT = i_src + " = " + i_dest +"\n"; :}
  | AliasesList:aliases IDENT:i_src EQUALS STRING:i_dest
                    {: RESULT = aliases + i_src + " = \"" + i_dest +"\"\n"; :}
  | IDENT:i_src EQUALS STRING:i_dest
                    {: RESULT = i_src + " = \"" + i_dest +"\"\n"; :}
  ;

