2016-11-16 31 views
1

我有一種語言,其中的一切的語義是一個字符數組或數組數組。所以,我有以下YYSTYPE:是不是有一個好的野牛實踐沒有語義價值,但使用行動的副作用?

typedef struct _array { 
    union { 
     char *chars; // start of string 
     void *base; // start of array 
    }; 
    unsigned n;  // number of valid elements in above 
    unsigned allocated; // number of allocated elements for above 
} array; 

#define YYSTYPE array 

和我可以附加字符數組到數組的數組與

void append(YYSTYPE *parray, YYSTYPE *string); 

假設語法(SSCCE)爲:

%token WORD 
%% 
array  :  WORD  
      | array WORD  
      ; 

所以我接受一連串的單詞。對於每個單詞,語義值都變成了這個字符數組,然後我想將這些每一個都附加到數組的數組中,以用於整個序列。

有設計的動作幾種可能的方式:

  1. array符號有array類型的語義值。如果我這樣做,那麼array WORD的行動將不得不復制$1$$這是緩慢的,所以我不喜歡這一點。

  2. array符號具有類型array *的語義值。現在的動作爲array WORD,我可以加入數組*$1,然後設置$$等於$1。但我不喜歡這個有兩個原因。首先,語義不是指向array的指針,而是array。其次,對於規則array : WORD的行動,我將不得不以malloc的結構,這是緩慢的。是的,'append'有時會做malloc,但是如果我分配的不夠頻繁,出於性能原因,我想避免任何不必要的malloc

  3. 忘掉試圖對符號array語義價值可言,並使用全局變量:

    static YYSTYPE g_array;

    YYSTYPE *g_parray = &g_array;

,然後,該操作將只使用

append(g_parray, word_array) 

整個語法的工作方式,我不需要多於一個g_array。以上是我能想到的最快的。但它是非常糟糕的設計 - 大量的全局變量,沒有語義值,相反,所有事情都是通過對全局變量的副作用發生的。

所以,我個人不喜歡他們中的任何一個。野牛通常被接受的最佳做法是什麼?

回答

1

在大多數情況下,使用全局變量沒有意義。或多或少的現代版本的野牛有%parse-param指令,它允許你有一種「解析上下文」。上下文可能會照顧所有內存分配等。

它可能反映當前的解析狀態 - 我。即有'當前array'等概念在這種情況下,你的語義行爲可以依賴於上下文知道你在哪裏。

%{ 
    typedef struct tagContext Context; 
    typedef struct tagCharString CharString; 

    void start_words(Context* ctx); 
    void add_word(Context* ctx, CharString* word); 
%} 

%union { 
    CharString* word; 
} 
%parse-param {Context* ctx} 

%token<word> WORD 
%start words 

%% 

words 
    : { start_words(ctx); } word 
    | words     word 
    ; 

word 
    : WORD { add_word(ctx, $1); } 
    ; 

如果你只解析話,別無其他的列表,你可以讓您的上下文。這兩種方法之間

​​

性能差異似乎可以忽略不計:

然而,在一個簡單的語法,它如果通過YYSTYPE信息傳遞更清晰。

內存清理

如果輸入文本沒有錯誤解析,你總是負責清理所有動態內存。但是,如果您的輸入文本導致解析錯誤,解析器將不得不丟棄一些令牌。在這種情況下可能有兩種清理方法。

首先,您可以跟蹤上下文中的所有內存分配,並在銷燬上下文時釋放所有內存分配。

其次,你可以依靠野牛析構函數:

%{ 
    void free_word_list(WordList* word_list); 
%} 

%destructor { free_word_list($$); } <word_list> 
+0

你的第一種方法是像我的第三個辦法,只是沒有全局,我會採取我的答案,謝謝。你的第二種方法與我的第二種方法非常相似。 –

相關問題