Как управлять семантическим правилом объявления переменных в зубрах - PullRequest
0 голосов
/ 29 августа 2018

Мне нужно построить компилятор, который переводит язык Java в Pyhton. Я использую инструменты Flex и Bison. Я создал гибкий файл и определил синтаксическую грамматику в Bison для некоторых ограничений, которые я должен реализовать (например, массив, управление циклами, управление классом, управление логико-арифметическими операторами и т. Д.). У меня проблемы с пониманием, как обращаться с семантическими правилами. Например, я должен обработать семантику для оператора импорта и объявления переменной, добавить переменную в таблицу символов и затем обработать перевод. Это структура таблицы символов в модуле symboltable.h:

struct symtable{

  char *scopename;            // key 
  struct symtable2 *subtable; // symble table secondary
  UT_hash_handle hh;          // to make the structure hash

}

struct symtable2            // secondary symbol structure
{

  char *name;               // Name of the symbol (key)
  char *element;            // it can be a variable or an array
  char *type;               // Indicates the type assumed by the token 
  (int, float, char, bool)
  char *value;              // value assigned to the variable
  int dim;                  // Array size, it is zero in the case of a variable.
  UT_hash_handle hh;        // to make the structure hash

};

И это функция добавления символа:

void add_symbol( char *name, char *current_scopename, char *element, char *current_type, char *current_value, int dim, int nr) {    //Function to add a new symbol in the symbol table

  struct symtable *s;
  HASH_FIND_PTR(symbols, current_scopename, s);
  if (s == NULL) {
     s = (struct symtable *)malloc(sizeof *s);
     s->scopename =current_scopename;
     s->subtable=NULL;
     s->scopename =current_scopename;
     HASH_ADD_KEYPTR(hh,symbols,s->scopename,strlen(s->scopename),s);
  }
  struct symtable2 *s2;
  HASH_FIND_PTR(symbols2, name, s2);
  if (s2==NULL) {
     s2 = (struct symtable2 *)malloc(sizeof *s2);
     s2->name = name;
     s2->element = element;
     s2->type = current_type;
     s2->value = current_value;
     s2->dim = dim;
     HASH_ADD_KEYPTR(hh,s->subtable,s2->name,strlen(s2->name),s2);
  } else {
     if (strcmp( s2->type,current_type) == 0){
        s2->value =current_value;
     } else {
      printf("\033[01;31mRiga %i. [FATALE] SEMANTIC ERROR: assignment violates the primitive type of the variable.\033[00m\n", nr);
      printf("\n\n\033[01;31mParsing failed.\033[00m\n");
     }
  }
}

Это часть файла зубра с грамматикой для обработки оператора импорта и объявления переменной:

%{
  #include <stdio.h>;
  #include <ctype.h>;
  #include <symboltable.h>;
  file *f_ptr;
%}

%start program
%token NUMBER
%token ID
%token INT
%token FLOAT
%token DOUBLE
%token CHAR
%token IMPORT

%right ASSIGNOP
%left SCOR
%left  SCAND
%left  EQ NE
%left  LT GT LE GE
%left ADD SUB
%left MULT DIV MOD
%right NOT
%left '(' ')' '[' ']'

%%

program
        : ImportStatement GlobalVariableDeclarations
        ;

ImportStatement
               :  IMPORT LibraryName ';'  { delete_file (); f_ptr = open_file (); fprintf(fptr, "import array \n"); }
               ;

LibraryName
           : 'java.util.*'
           ;

GlobalVariableFieldDeclarations
                               : type GlobalVariableDeclarations ';' 
                               ;


GlobalVariableDeclarations
                          : GlobalVariableDeclaration
                          | GlobalVariableDeclarations ',' GlobalVariableDeclaration
                          ;

GlobalVariableDeclaration
                         : VariableName 
                         | VariableName ASSIGNOP VariableInitializer {if (typeChecking($1,$3)== 0) {$1= $3; $$=$1;}}
                         ;

VariableName
            : ID {$$ = $1 ;}
            ;

type
    : INT
    | CHAR
    | FLOAT
    | DOUBLE
    | BOOLEAN
    ;

VariableInitializers
                    : VariableInitializer
                    | VariableInitializers ',' VariableInitializer
                    ;
VariableInitializer
                    : ExpressionStatement
                    ;

ExpressionStatement
                   : VariableName
                   | NUMBER
                   | ArithmeticExpression
                   | RelationalExpression
                   | BooleanExpression
                   ; 
ArithmeticExpression
                    : ExpressionStatement ADD ExpressionStatement
                    | ExpressionStatement SUB ExpressionStatement
                    | ExpressionStatement MULT ExpressionStatement
                    | ExpressionStatement DIV ExpressionStatement
                    | ExpressionStatement MOD ExpressionStatement
                    ;

RelationalExpression
                    : ExpressionStatement GT ExpressionStatement
                    | ExpressionStatement LT ExpressionStatement
                    | ExpressionStatement GE ExpressionStatement
                    | ExpressionStatement LE ExpressionStatement
                    | ExpressionStatement EQ ExpressionStatement
                    | ExpressionStatement NE ExpressionStatement
                    ;

BooleanExpression
                 : ExpressionStatement SCAND ExpressionStatement
                 | ExpressionStatement SCOR ExpressionStatement
                 | NOT ExpressionStatement
                 ;

%%

int yyerror (char *s)
{
  printf ("%s \n",s);
}

int main (void) {
  return yyparse();
}

int typeChecking (variable1, variable2) {
   struct symtable2 *s2;

   s2=find_symbol (scopename, variable1);
   if (s2!=NULL) {
       int type1= s2->type;
       char element1 = s2->element;
   }
   else{
       printf("\n\n\033[01;31mVariable 1 not defined.\033[00m\n");
       return -1;
   }

   s2=find_symbol (scopename, variable2);
   if (s2!=NULL) {
       int type2= s2->type;
       char element2 = s2->element;
   }
   else{
       printf("\n\n\033[01;31mVariable 2 not defined.\033[00m\n");
       return -1;
   }

   if(element1=='variable' && element2=='variable'){

       if (type1 == type2){
          return 0;
       }
       else {
          return 1;
       }
   }

   else {
       printf("\n\n\033[01;31m Different elements.\033[00m\n");
       return -1;
   }
}

Я новичок с синтаксисом бизона для управления семантикой, в следующих постановках у меня есть сомнения по поводу относительного семантического правила:

  GlobalVariableFieldDeclarations
                               : type GlobalVariableDeclarations ';' 
                               ;


  GlobalVariableDeclarations
                          : GlobalVariableDeclaration
                          | GlobalVariableDeclarations ',' GlobalVariableDeclaration
                          ;

  GlobalVariableDeclaration
                          : VariableName 
                          | VariableName ASSIGNOP VariableInitializer {if (typeChecking($1,$3)== 0) {$1= $3; $$=$1;}}
                         ;

  VariableName
             : ID {$$ = $1 ;}
             ;

Правильно ли управлять семантикой таким образом для производства GlobalVariableDeclaration? И как я могу вставить требуемые значения параметров в таблицу символов через функцию add_symbol? (Или лучше, как я могу получить необходимые параметры, начиная с производств, чтобы вставить их в реализованную мной функцию add_symbol?) Простите, но я новичок, и многие вещи о семантике мне не ясны. Надеюсь, у вас хватит терпения помочь мне, заранее благодарю.

1 Ответ

0 голосов
/ 30 августа 2018

Вы должны использовать Bison для построения AST, а затем выполнять грамматический семантический анализ дерева, а не грамматики. Построение AST позволяет выполнять анализ более сложных структур данных, чем те грамматические правила, которые вы создали в Bison.

Если у вас есть AST для ввода, вы можете создать правила для преобразования этого AST в программу на языке Python с тем же синтаксисом.

Вот пример компилятора Bison / Flex для языка Decaf, который может дать вам некоторые идеи https://github.com/davidcox143/Decaf-Compiler

...