2015-12-05 44 views
1

我有一個符號表,它包含一個變量/符號的名稱,它的數據和它的數據類型(存儲爲char)。我喜歡它,所以符號被看作是一個iexpr,如果它是一個整數,或者是一個rexpr,如果它是一個實數。這些是規則,我現在他們:Bison多規則符號

iexpr: INT_TOKEN 
    | iexpr PLUS iexpr { $$ = $1 + $3; } 
    | iexpr MINUS iexpr { $$ = $1 - $3; } 
    | iexpr DIVIDE iexpr {$$ = $1/$3;} 
    | iexpr MOD iexpr{$$ = $1 % $3;} 
    | LPARENT iexpr RPARENT{$$=$2;} 
    | SYMBOL { symrec *s; 
       s = getsym($1); 
       if(s!=0){ 
        if(s->type == 'i'){ 
         $$ = atoi(s->data); 
        } 
       } 
      } 
; 
rexpr: REAL_TOKEN 
    | rexpr PLUS rexpr { $$ = $1 + $3; } 
    | rexpr MINUS rexpr { $$ = $1 - $3; } 
    | iexpr PLUS rexpr { $$ = (double) $1 + $3; } 
    | iexpr MINUS rexpr { $$ = (double) $1 - $3; } 
    | rexpr PLUS iexpr { $$ = $1 + (double) $3; } 
    | rexpr MINUS iexpr { $$ = $1 - (double) $3; } 
    | rexpr DIVIDE rexpr {$$ = $1/$3;} 
    | rexpr MULTIPLY rexpr{$$ = $1 * $3;} 
    | rexpr DIVIDE iexpr {$$ = $1/(double) $3;} 
    | rexpr MULTIPLY iexpr {$$= $1 * (double) $3;} 
    | iexpr DIVIDE rexpr {$$ = (double) $1/$3;} 
    | iexpr MULTIPLY rexpr {$$ = (double) $1 * $3;} 
    | rexpr MOD rexpr {$$ = (int)$1 % (int)$3;} 
    | rexpr MOD iexpr {$$ = (int)$1 % $3;} 
    | iexpr MOD rexpr {$$ = $1 % (int)$3;} 
    | LPARENT rexpr RPARENT{$$ =$2;} 
    | SYMBOL { symrec *s; 
       s = getsym($1); 
       if(s!=0){ 
        if(s->type == 'r'){ 
         $$ = atof(s->data); 
        } 
       } 
      } 
; 

然而在rexpr分別規則永遠不會使用,因爲它永遠只能看到它作爲一個iexpr。我怎樣才能使它取決於類型描述符它被視爲該類型,而不僅僅是一個整數?

編輯:所以我試圖改變我的lex文件,這樣它會返回一個不同的令牌每種類型。爲此,我需要包含可符號化的頭文件,以便我可以檢查該名稱並根據其類型返回不同的符號。下面是該代碼:

[a-zA-Z]+ { yylval.string = strdup(yytext); 
      symrec *s; 
      s = getsym(yylval.string); 
      if(s!=0){ 
       if(s->type == 'r'){ 
        return RSYMBOL; 
       }else if(s->type == 'i'){ 
        return ISYMBOL; 
       } 
      }else{ 
      return SYMBOL; 
      } 
      } 

但現在我有一個錯誤說,我有我的頭功能的多個定義,因爲我包含在這兩個文件。

回答

2

如果你想令牌類型取決於符號的聲明類型不同,你需要查找的符號了在詞法分析器(因爲這是生成令牌類型)。

你實際上需要返回三個不同的令牌類型之一:

  • INT_SYMBOL
  • REAL_SYMBOL
  • UNDECLARED_SYMBOL

一般來說,最好是做類型檢查解析完成後在AST上單獨傳遞。 (或者,如果您沒有生成AST,您可以在語義操作中進行語義操作)。這可以讓您生成更好的錯誤消息,並且使得在類型錯誤之後繼續解析更容易。

+0

謝謝!你能看看我的編輯?我認爲這是我應該做的,但我會遇到更多的問題。 – cage479

+0

@ cage479:你沒有在頭文件中定義函數;你只聲明他們。如果你要定義函數,你顯然會遇到重複的定義錯誤,以及全局變量的重複定義。順便說一句,如果詞法分析器可以訪問符號表,它可以返回符號表條目而不是符號名稱的副本。這是一種減少內存分配的經典技術,即使詞法分析器不會根據符號表信息修改其行爲。 – rici

+0

如果它不是很明顯,我沒有太多經驗創建我自己的頭文件。所以如果我只聲明的功能(即時通訊假設只是「symrec * getsym()」)我在哪裏實際定義它們?我是否需要在我的bison和flex文件中定義它們或者只是其中的一個? – cage479

1

如果你想做到這一點,你需要有詞法分析器ISYMBOLRSYMBOL返回不同的令牌,否則你會得到降低/減少兩個減之間的衝突爲SYMBOL因爲分析器不知道它是。這意味着您需要在詞法分析器操作中執行符號表查找,而不是在解析器操作中進行查找。

一般來說,試圖做的類型檢查像這樣的解析器是一個壞主意,因爲它使語法更爲複雜,並導致許多難以解決的矛盾。