/*
 * DUDU+ codename MiniJava
 * HECHO... in Dominican Republic
 * author vns
 */
options{
  LOOKAHEAD = 1;
  STATIC = false;
  JAVA_UNICODE_ESCAPE = true;
}
PARSER_BEGIN(MiniJava)
import java.util.*;
public class MiniJava {
 public static void main(String[] args) throws ParseException, TokenMgrError {
 
 MiniJava parser;
 String file = null;
 long time = 0;
 long parseTime = 0;
 long startTime = 0;
 
 if (args.length == 0)
 {
  System.out.println("Error messages...");
  return; 
 
 } else if ( args.length == 1 ){
  file = args[0];
  System.out.println("Start parsing...");
  
  try
  {
   parser = new MiniJava(new java.io.FileInputStream(file));
  } catch ( java.io.FileNotFoundException e ) {
   System.out.println("Parser error:  Filename " + file + " not found." );
   return;
  }
 } else {
  System.out.println("Debe escribir: java MiniJava inputfile");
  return;
 }
 try
 {
  startTime = System.currentTimeMillis();
  parser.Start();
  parseTime = System.currentTimeMillis();
  time = parseTime - startTime;
  
  System.out.println(" Time of parsing: " + time + " ms");
  System.out.println(" DuDu successfully end");
 } catch ( ParseException pex) {
  System.out.println( pex.getMessage() );
  System.out.println(" ParserException during parse file" );
 }
 }/* main method*/
}
PARSER_END(MiniJava)
/* Eat white space and comment*/
SKIP : {
 " "
|  "\t"
|  "\n"
|  "\r"
|  <"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")>
|  <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
}
TOKEN : /* RESERVED WORDS AND LITERALS */
{
  < BOOLEAN: "boolean" >
| < BYTE: "byte" >
| < CHAR: "char" >
| < CLASS: "class" >
| < DOUBLE: "double" >
| < FALSE: "false" >
| < FLOAT: "float" >
| < FINAL: "final" >
| < INT: "int" >
| < LONG: "long" >
| < PUBLIC: "public" >
| < SHORT: "short" >
| < STATIC: "static" >
| < TRUE: "true" >
| < VOID: "void" >
| < NEW: "new" >
| < MAKE: "make" >
| < STACK: "stack" >
| < REPEAT: "repeat" >
| < UNTIL: "until" >
| < ADDSTACK: "addStack" >
| < ORDSTACK: "ordStack" >
| < ASCENDENTE: "ascendente" >
| < DESCENDENTE: "descendente" >
}
TOKEN : /* SEPARATORS */
{
  < LPAREN: "(" >
| < RPAREN: ")" >
| < LBRACE: "{" >
| < RBRACE: "}" >
| < LBRACKET: "[" >
| < RBRACKET: "]" >
| < SEMICOLON: ";" >
| < COMMA: "," >
}
TOKEN : /* OPERATORS */
{
  < ASSIGN: "=" >
| < INCR: "++" >
| < DECR: "--" >
| < PLUS: "+" >
| < MINUS: "-" >
| < STAR: "*" >
| < SLASH: "/" >
}
TOKEN : /* LITERALS */
{
  < INTEGER_LITERAL:
        < DECIMAL_LITERAL > (["l","L"])?
  >
  |
  < #DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])* >
  |
  < FLOATING_POINT_LITERAL:
        (["0"-"9"])+ "." (["0"-"9"])* ( < EXPONENT > )? (["f","F","d","D"])?
      | "." (["0"-"9"])+ ( < EXPONENT >)? (["f","F","d","D"])?
      | (["0"-"9"])+ < EXPONENT > (["f","F","d","D"])?
      | (["0"-"9"])+ (< EXPONENT >)? ["f","F","d","D"]
  >
  |
  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
  |
  < CHARACTER_LITERAL:
      "'"
      (   (~["'","\\","\n","\r"])
        | ("\\"
            ( ["n","t","b","r","f","\\","'","\""]
            | ["0"-"7"] ( ["0"-"7"] )?
            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
            )
          )
      )
      "'"
  >
  |
  < STRING_LITERAL:
      "\""
      (   (~["\"","\\","\n","\r"])
        | ("\\"
            ( ["n","t","b","r","f","\\","'","\""]
            | ["0"-"7"] ( ["0"-"7"] )?
            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
            )
          )
      )*
      "\""
  >
}
TOKEN : {
 < IDENTIFIER: < LETTER > ( < LETTER > | < DIGIT > )*>
|  <#LETTER: ["$","A"-"Z","_","a"-"z"]>
|  <#DIGIT: ["0"-"9"]>
}
/*********************************************
 * THE MINIJAVA LANGUAGE GRAMMAR STARTS HERE *
 *********************************************/
/*
 * Struts.
 */
void Start() throws ParseException :
{}
{
  (TypeDeclaration() )*
}
void TypeDeclaration() :
{}
{
  ClassDeclaration()
}
/*
 * Declaracion de clases
 */
void ClassDeclaration() :
{}
{
   ( "final" | "public" | "static" )* "class" < IDENTIFIER > 
  "{" ( ClassBodyDeclaration() )* "}"
  
}
void ClassBodyDeclaration() :
{}
{
  LOOKAHEAD(2)  
  FieldDeclaration()
|
  Statement()
}
void FieldDeclaration() :
{}
{  
  ( "public" | "static" | "final" )*
  Type() VariableDeclarator() ( "," VariableDeclarator() )* ";"
  
}
void VariableDeclarator() :
{}
{
  VariableDeclaratorId() [ "=" VariableInitializer() ] 
}
void VariableDeclaratorId() :
{}
{
  < IDENTIFIER > ( "[" "]" )*
}
void VariableInitializer() :
{}
{
  ArrayInitializer()
|
  Expression()
}
void ArrayInitializer() :
{}
{
  "{" [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"
}
/*
 * Tipos, nombre y sentencias
 */
void Type() :
{}
{
  PrimitiveType()  ( "[" "]" )*
}
void PrimitiveType() :
{}
{
  "boolean"
|
  "char"
|
  "byte"
|
  "short"
|
  "int"
|
  "long"
|
  "float"
|
  "double"
}
void Name() :
{ }
{
  < IDENTIFIER >
}
/*
 * Expression syntax
 */
void Expression() :
{}
{ 
  ConditionalExpression() [ AssignmentOperator() AdditiveExpression() ] 
}
void AssignmentOperator() :
{}
{
  "="
}
void ConditionalExpression() :
{}
{
  ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression() ]
}
void ConditionalOrExpression() :
{}
{ 
  ConditionalAndExpression() ( "||" ConditionalAndExpression() )*
  
}
void ConditionalAndExpression() :
{}
{ 
  EqualityExpression() ( "&&" EqualityExpression() )*
  
}
void EqualityExpression() :
{}
{ 
  RelationalExpression() ( ( "==" | "!=" ) RelationalExpression() )*
  
}
void RelationalExpression() :
{}
{ 
  AdditiveExpression() ( ( "<" | ">" | "<=" | ">=" ) AdditiveExpression()  )*
  
}
void AdditiveExpression() :
{}
{ 
  MultiplicativeExpression() ( LOOKAHEAD(2)( "+" | "-" ) MultiplicativeExpression() )*
  
}
void MultiplicativeExpression() :
{}
{ 
  UnaryExpression() ( ( "*" | "/" ) UnaryExpression() )*
  
}
void UnaryExpression() :
{}
{
  ( "+" | "-" ) UnaryExpression()
|
  UnaryExpressionNotPlusMinus()
}
void UnaryExpressionNotPlusMinus() :
{}
{
  PostfixExpression()
}
void PostfixExpression() :
{}
{
  PrimaryExpression() [ "++" | "--" ]
}
void PrimaryExpression() :
{}
{
  PrimaryPrefix() ( PrimarySuffix() )*
}
void PrimaryPrefix() :
{}
{
  Literal()
|
  "(" Expression() ")"
|
  AllocationExpression()
|
  Name()
}
void PrimarySuffix() :
{}
{
  "[" Expression() "]"
|
  LOOKAHEAD(2)
  "." "addStack" "(" ( Name() | Literal() ) ")"
|
  "." "ordStack" "(" OrdenType() ")"
}
void OrdenType() :
{}
{
  "ascendente"
|
  "descendente"
}
void Literal() :
{}
{
  < INTEGER_LITERAL >
|
  < FLOATING_POINT_LITERAL >
|
  < CHARACTER_LITERAL >
|
  < STRING_LITERAL >
|
  BooleanLiteral()
}
void BooleanLiteral() :
{}
{ 
  "true"
|
  "false"
}
void AllocationExpression() :
{}
{ 
  "new" PrimitiveType() ArrayDimsAndInits()
|
  MakeStack()
}
void MakeStack() :
{}
{
 "make" "stack" 
}
void ArrayDimsAndInits() :
{}
{
  LOOKAHEAD(2)
  ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )*
|
  ( "[" "]" )+ ArrayInitializer()
}
void Statement() :
{}
{ 
  Expression() ";"
|
  RepeatStatement()
}
void RepeatStatement() :
{}
{ 
  "repeat" Statement() "until" "(" Expression() ")"
  
}