// FILE. . . . . /home/hak/hlt/src/hlt/osf/v0/sources/rules.grm
// EDIT BY . . . Hassan Ait-Kaci
// ON MACHINE. . Hp-Dv7
// STARTED ON. . Fri Nov 02 03:59:19 2012

/**
 * 
 * @version     Last modified on Sat Jan 19 12:54:52 2013 by hak
 * @author      <a href="mailto:hak@acm.org">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; <a href="http://www.hassan-ait-kaci.net/">by the author</a>
 */

/* ************************************************************************ */
/* **************************** GRAMMAR RULES ***************************** */
/* ************************************************************************ */

%%

/**
 * $OsvV0Program$ is the grammar's start symbol. It denotes an
 * OSF V0 program, which consists in a sequence of $Statement$ constructs.
 */
OsfV0Program
  : Statements_opt 
  ;

/**
 * A <tt>Statements_opt</tt> is a possibly empty sequence of $Statement$ constructs.
 */
Statements_opt
  : // Empty programs are ok. */
  | Statements_opt Statement
  ;

/**
 * A <tt>Statement</tt> is $StatementType$ followed by an end of statement
 * marker.
 */
Statement
  : StatementType EndOfStatement
  ;

/**
 * <tt>EndOfStatement</tt> denotes the end of a statement. Upon the end of
 * statement marker <tt>EOS</tt> the statement is processed and errors
 * that may have occurred are reported. In interactive mode, it also
 * triggers a prompt for additional statements. In case of syntax error,
 * error recovery skips all input until the next end-of-statement marker
 * <tt>EOS</tt>.
 */
EndOfStatement
  : {
      commitParse();
    }
    EOS
  ;

/**
 * A <tt>StatementType</tt> is the main language unit, an element of the
 * sequence of statements that make up an OSF V0 program.  It can be one
 * of the following:
 *
 * <ul>
 * <li>A <b>Pragma statement:</b><br>
 *     Extra-language commands for user interaction conveniences.
 * </li>
 * <p>
 * <li>A <b>Sort declaration statement:</b>)<br>
 *     To declare how sorts are related in the concept taxonomy.
 * </li>
 * <p>
 * <li>An <b>OSF Expression evaluation statement:</b><br>
 *     To enter an expression to evaluate and print the result.
 * </li>
 * <p>
 * <li>An <b>Empty statement:</b><br>
 *     This has no effect: it is simply skipped.
 * </li>
 * <p>
 * <li><b>Error statement:</b><br> To enable error recovery <i>&agrave;
 *     la</i> yacc. This rule is needed to enable error recovery
 *     <i>&agrave; la</i> yacc.  This is what makes $Statement$ a unit
 *     of parsing for OSF V0: in case of syntax error, OSF V0's parser
 *     ignores everything past the last successfully parsed $Statement$
 *     and up to the next end-of-statement marker: a period ('$.$'- also
 *     known as the terminal symbol $EOS$).
 *
 * </ul>
 */
StatementType
  : // Empty statements are ok. */
  | Pragma PragmaArguments_opt
    {
      processPragma($1.svalue().intern(),$2.args);
    }
  | SortDeclarationStatement
  | OsfExpression
  | error
  ;

SortDeclarationStatement
  : IsaDeclarationStatement
    {
      setLocation();
      processIsaDeclaration($1.lhs,$1.rhs);
    }
  // | SortNameDeclarationStatement
  //   {
  //     setLocation();
  //     processtSortNameDeclaration($1.symbols);
  //   }
  ;

IsaDeclarationStatement
  : SortSymbols ISA SortSymbols
    {
      $$.lhs = $1.symbols;
      $$.rhs = $3.symbols;
    }
  ; 

// SortNameDeclarationStatement
//   : DECLARESORTS SortSymbols
//     {
//       $$.symbols = $2.symbols;
//     }      
//   ;

SortSymbol
  : IDENTIFIER
  ;

SortSymbols
  : SortSymbol
    {
      $$.symbols = new Stack();
      $$.symbols.push($1.svalue());
    }
  | SortSymbol ',' SortSymbols
    {
      ($$.symbols = $3.symbols).push($1.svalue());
    }
  ;

OsfExpression
  : // SortExpression
  //   {
  //     processSortExpression($1.expression);
  //   }
  // | 
    PsiTerm
    {
      processPsiTerm($1.tag,$1.sort,$1.keys,$1.subterms);
    }
  ;

PsiTerm
  : TAG
    {
      $$.tag = $1.svalue();
      $$.sort = new SymbolSortExpression("@",context);
    }
  | UntaggedPsiTerm
    {
      $$.sort = $1.sort;
      $$.keys = $1.keys;
      $$.subterms = $1.subterms;
    }
  | TAG ':' UntaggedPsiTerm
    {
      $$.tag = $1.svalue();
      $$.sort = $3.sort;
      $$.keys = $3.keys;
      $$.subterms = $3.subterms;
    }
  ;

UntaggedPsiTerm
  : SortExpression Body_opt
    {
      $$.sort = $1.expression;
      $$.keys = $2.keys;
      $$.subterms = $2.subterms;
    }
  ;

Body_opt
  : /* empty */
  | '(' SubTerms ')'
    {
      $$.keys = $2.keys;
      $$.subterms = $2.subterms;
    }
  ;

SubTerms
  : SubTerm
    {
      $$.keys = new Stack();
      $$.keys.push($1.key);
      $$.subterms = new Stack();
      $$.subterms.push($1.psiterm);
    }
  | SubTerm ',' SubTerms
    {
      ($$.keys = $3.keys).push($1.key);
      ($$.subterms = $3.subterms).push($1.psiterm);
    }
  ;

SubTerm
  : PsiTerm
    {
      $$.key = null;
      $$.psiterm = new RawPsiTerm($1.tag,$1.sort,$1.keys,$1.subterms);
    }
  | Feature ARROW PsiTerm
    {
      $$.key = $1.feature;
      $$.psiterm = new RawPsiTerm($3.tag,$3.sort,$3.keys,$3.subterms);
    }
  ;

Feature
  : INTEGER
    {
      $$.feature = new Integer((int)$1.nvalue());
    }
  | IDENTIFIER
    {
      $$.feature = $1.svalue();
    }
  ;

SortExpression
  : Sort
    {
      $$.expression = new SymbolSortExpression($1.svalue(),context);
    }
  | '{' SortList '}'
    {
      $$.expression = new DisjunctiveSortExpression($2.sortList,context);
    }
  | NOT SortExpression
    {
      $$.expression = new NotSortExpression($2.expression);
    }
  | SortExpression AND SortExpression
    {
      $$.expression = new AndSortExpression($1.expression,$3.expression);
    }
  | SortExpression OR SortExpression
    {
      $$.expression = new OrSortExpression($1.expression,$3.expression);
    }
  | SortExpression BUTNOT SortExpression
    {
      $$.expression = new ButnotSortExpression($1.expression,$3.expression);
    }
  | '(' SortExpression ')'
    {
      $$.expression = $2.expression.setParenthesized(true);
    }
  ;

Sort
  : TOP
  | BOTTOM
  | IDENTIFIER
  ;

SortList
  : Sort
    {
      $$.sortList = new Stack();
      $$.sortList.push($1.svalue());
    }
  | Sort ';' SortList
    {
      ($$.sortList = $3.sortList).push($1.svalue());
    }
  ;

// /**
//  * This non-terminal denotes statements used to define a global
//  * name associated to a &psi;-term.
//  */
// DefinitionStatement
//   : DEF '=' PsiTerm
//   {
//     processDefinition($1.name,$3.psiterm);
//   }
//   ;
   
/**
 * This node stands for a pragma statement which allows the user to
 * query state parameters or up some options using a few built-in
 * extra-language commands of the form <font
 * color="brown"><tt>&#37;pragma;</tt></font> where <font
 * color="brown"><tt>pragma</tt></font> is an identifier.
 *
 * Pragmas to be supported eventually are:
 *
 * <p>
 * <center>
 * <table border="1" width="90&#37;" cellpadding="5">
 * <col width="25&#37;">
 * <col width="75&#37;">
 *
 * <tr><th align="left">Pragma Expression
 * </th><th align="left">Caused Effect</th></tr>
 *
 * <tr><td valign="top"><tt>&#37;exit</tt></td>
 * <td valign="top">End the session and exit OSF V0.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;load filename</tt></td>
 * <td valign="top">Read and process the contents of the file (name specified as a quoted string)</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;encode</tt></td>
 * <td valign="top">Trigger the encoding of the current sort hierarchy.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;showcodes</tt></td>
 * <td valign="top">Toggle on/off encoded sorts' display.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;automatic</tt></td>
 * <td valign="top">Toggles on/off automatic sort encoding
 *     at the first expression evaluation without prompting the user.
 *     The default is to prompt the user.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;mute</tt></td>
 * <td valign="top">Toggle on/off result displays.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;size</tt></td>
 * <td valign="top">Print the number of concepts in the sort hierarchy.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;height</tt></td> <td valign="top">Print the
 * height of the sort hierarchy; that is, the length of the longest
 * <i>is-a</i> concept chain from <tt>{}</tt> to <tt>@</tt>.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;width</tt></td>
 * <td valign="top">Print the size of the widest
 *   is-a concept cochain; that is, the size of the largest
 *   set of mutually unrelated concepts in the hierarchy.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;children s</tt></td>
 * <td valign="top">Prints the set of maximal strict
 *   lower bounds of <tt>s</tt>; in other words, the set of immediate
 *   subconcepts of <tt>s</tt>.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;descendants s</tt></td>
 * <td valign="top">Print the set of miminal 
 *   strict lower bounds of <tt>s</tt>; in other words, the set of
 *   subconcepts of <tt>s</tt> immediately above <tt>{}</tt>, or
 *   <tt>{}</tt> if <tt>s</tt> is immediately above <tt>{}</tt>.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;parents s</tt></td>
 * <td valign="top">Print the set of miminal 
 *   strict lower bounds of <tt>s</tt>; in other words, the set of
 *   subconcepts of <tt>s</tt> immediately above <tt>{}</tt>, or
 *   <tt>{}</tt> if <tt>s</tt> is immediately above <tt>{}</tt>.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;ancestors s</tt></td>
 * <td valign="top">Print the set of maximal
 *   strict upper bounds of <tt>s</tt>; in other words, the set of
 *   superconcepts of <tt>s</tt> immediately below <tt>@</tt>, or
 *   <tt>@</tt> if <tt>s</tt> is immediately below <tt>@</tt>.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;isa s t</tt></td>
 * <td valign="top">Return <tt>true</tt> if <tt>s</tt>
 *   is a subconcept of <tt>t</tt>, and <tt>false</tt> otherwise.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;refresh</tt></td>
 * <td valign="top">Erase the codes for
 *     all known sorts. After this pragma has been invoked, new sort
 *     declarations and variable definitions may then be added those
 *     previously recorded, and then the hierarchy may be reencoded.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;tree</tt></td>
 * <td valign="top">Toggle on/off display of syntax tree.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;timing</tt></td>
 * <td valign="top">Toggle on/off execution timing.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;gc</tt></td>
 * <td valign="top">Force immediate garbage collection.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;syntax</tt></td>
 * <td valign="top">Toggle on/off parser tracing.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;trace</tt></td>
 * <td valign="top">Toggle on/off evaluation tracing.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;defined</tt></td>
 * <td valign="top">List all the currently defined symbols.</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;symbols</tt></td>
 * <td valign="top">List all the known (built-in and defined) symbols</td></tr>
 *
 * <tr><td valign="top"><tt>&#37;help</tt></td>
 * <td valign="top">List this information.</td></tr>
 *
 * </table>
 * </center>
 */
Pragma
  : PRAGMA
  ;

// PragmaArguments_opt
//   : // empty */
//   | STRING
//     {
//       $$.arg1 = $1.svalue();
//     }
//   | Sort
//     {
//       $$.arg1 = $1.svalue();
//     }
//   | Sort Sort
//     {
//       $$.arg1 = $1.svalue();
//       $$.arg2 = $2.svalue();
//     }
//   ;

PragmaArguments_opt
  : // empty */
  | FileList
    {
      $$.args = $1.files;
    }
  | SortExpression
    {
      $$.args = new ArrayList(1);
      $$.args.add($1.expression);
    }
  | SortExpression SortExpression
    {
      $$.args = new ArrayList(2);
      $$.args.add($1.expression);
      $$.args.add($2.expression);
    }
  ;

FileList
  : STRING
    {
      $$.files = new Stack();
      $$.files.push($1.svalue());
    }
  | STRING FileList
    {
      ($$.files = $2.files).push($1.svalue());
    }
  ;

// Constant
//   : INTEGER
//   { $$.expression = new Int((int)$1.nvalue()); }
//   | CHAR // should check that there's exactly one character!
//   { $$.expression = new Char($1.svalue().charAt(0)); }
//   | FLOAT
//   { $$.expression = new Float($1.nvalue()); }
//   | STRING
//   { $$.expression = new StringConstant($1.svalue()); }
//   | 'true'
//   { $$.expression = Constant.TRUE(); }
//   | 'false'
//   { $$.expression = Constant.FALSE(); }
//   | 'null'
//   { $$.expression = Constant.NULL(); }
//   ;

%%

/* ************************************************************************ */
/* ************************* END OF GRAMMAR RULES ************************* */
/* ************************************************************************ */
