/*////////////////////////////////////////////////////////////////////
//
//  file: asmyaccbase.yy
//
//
//  Project Lissom
//  
//  FIT VUT Brno 
//
//  basic part of parser
//    contains rules for constant numbers and
//  another things from the assembler language
//  needs to be combined with bison source generated by parser
//  generator   
//
//  
//  author:  Adam Husar, xhusar01@stud.fit.vutbr.cz
//  created: 24.03.2005
//  last change: 28.11.2005
//
//  changelist:
//    15.3.2006 Libor Vasicek, xvasic15@stud.fit.vutbr.cz
//    * section and label support
//
/////////////////////////////////////////////////////////////////////
*/

/*
 warning: nonterminals names must not begin with YNT_  
          this prefix is used for generated nonterminal names
*/
  
%{
// definition of isac types  
#include "isacctypes.h"

// specify other type of yychar
#define YYSTYPE isaccpointer

#include <stdlib.h>
#include <string.h>  

// we provide own scanner
#include "opschedull.h"

// the bisson needs the tokens' definitions
#include "asmscanner.cpp"

#include "codegen.h"
#include "asmknittingalg.h"

extern CCodeGen* codegen;

void yyerror(const char* s);

isaccpointer yychar_tmp;		// store the value of yychar

%} 

%start start 

%output="asmparser.cpp"
%error-verbose

%defines 

%token EXTERN
%token PUBLIC
%token SECTION
%token SECTION_TYPE_TEXT
%token SECTION_TYPE_DATA
%token SECTION_NAME
%token SECTION_NAME_DELIM
%token SECTION_ORG
%token LABEL_DELIM

%token SYMBOL
%token STRING
          
%token DEC_CONST
%token HEX_CONST
%token BIN_CONST
%token NEWLINE


%%

start
	:  start isac_instr 
	{
		if (is_first_codingrootnonterm)
		{
			is_first_codingrootnonterm=false;
			opschedull_setmode(OPSCHEDINSTR);
			yychar_tmp = YYLEX;
		}

		if (yychar_tmp==0)
		{
			return EOF;
		}
		
		if (opschedull_oplistempty())
		{
			opschedull_inc_cycle();
			opschedull_putop(MAIN);
		}
		opschedull_setmode(OPSCHEDOP);

		// GRAMMAR HACK
		if(yychar==0)
		{
			yychar=YYLEX;
		}				
	}
	| 
	{
		if (is_first_codingrootnonterm)
		{
			is_first_codingrootnonterm=false;
			opschedull_setmode(OPSCHEDINSTR);
			yychar_tmp = YYLEX;
		}
		
		if (yychar_tmp==0)
		{
			return EOF;
		}

		if (opschedull_oplistempty())
		{
			opschedull_inc_cycle();	
			opschedull_putop(MAIN);
		}
		opschedull_setmode(OPSCHEDOP);

		// GRAMMAR HACK
		if(yychar==0)
		{
			yychar=YYLEX;
		}				
	}

S
  : declaration NEWLINE
  | section_def NEWLINE 
  | error NEWLINE /*{yyerrok;}*/
  | NEWLINE 
 	
declaration
  : EXTERN SYMBOL
    {
        codegen->SymbolDeclaration((const char *) $2, SYMBOL_EXTERN);
        codegen->StringFree((char *) $2);
        $2 = 0;
    }
  | PUBLIC SYMBOL
    {
        codegen->SymbolDeclaration((const char *) $2, SYMBOL_PUBLIC);
        codegen->StringFree((char *) $2);
        $2 = 0;
    }
;

section_def
  : SECTION section_params
;

section_params
  : section_type section_name section_org
    {
        codegen->CreateSection((int) $1,(const char *) $2, (int) $3);
    }
;

section_type
  : SECTION_TYPE_TEXT
    {
        $$ = SECTION_TEXT;
    }
  | SECTION_TYPE_DATA
    {
        $$ = SECTION_DATA;
    }
;

section_name
  : SECTION_NAME SECTION_NAME_DELIM STRING
    {
        $$ = $3;
    }
  | /*epsilon*/
    {
        $$ = 0;
    }
;

section_org
  : SECTION_ORG const_num
    {
        $$ = $2;
    }
  | /*epsilon*/
    {
        $$ = -1;
    }
;

label
  : label symbol delimiter
  {
        codegen->LabelDefinition((CCodeGen::symbol_t *) $2);
        free((void *) $2);
  }
  | label symbol delimiter NEWLINE
  {
       codegen->LabelDefinition((CCodeGen::symbol_t *) $2);
       free((void *) $2);
  }
  | /*epsilon*/
  {
  }
;

delimiter
  : LABEL_DELIM /*{ }*/
  | /*epsilon*/
    {
        printf("neni oddelovac!\n");
    }
;

symbol
  : SYMBOL
    {
        $$ = (isaccpointer) codegen->LookUpSymbol((const char *) $1);
        codegen->StringFree((char *)$1);
        $1 = 0;
     }
;

const_num /* value of inheriting attribute of this nonterminal is numerical value of read token */
  : DEC_CONST
    { 
      char* stopstr;
      $$ = (isaccpointer)strtol(yytext, &stopstr, 10);
    }
  | HEX_CONST
    {
      char* stopstr;
      $$ = (isaccpointer)strtol(yytext+2, &stopstr, 16);
    }
  | BIN_CONST
    {
      char* stopstr;
      $$ = (isaccpointer)strtol(yytext+2, &stopstr, 2);
    }
;

address
  : symbol
    {
        $$ = $1;
    }
  | const_num
    {
        $$ = (isaccpointer) codegen->SetAddress((int) $1);
    }
;

%%      
   
void yyerror(const char* s)
{
  codegen->Error("syntactic analysis: %s", s);
//  printf("Error in syntactic analysis...\n");
  return;
}
