我正在開發一個項目,將用Second Life的LSL語言編寫的腳本轉換爲Lua。我正在學這個項目的flex和btyacc。事實上,這是一個更大的項目,這只是其中的一部分。 http://www.sqlite.org/cgi/src 作爲第一步,我想確保我生成的AST是輸入的準確反映。所以我的想法是從AST生成一個新文件,然後比較它們。這意味着我需要在AST中包含空格和註釋,以便當我使用它來激發結果文件時,它包含完全相同的空格和註釋。驗證您的flex和yacc代碼是否通過生成源代碼來與原始代碼進行比較
我一直有處理空白的問題。搜索和試驗幾天而沒有獲得任何地方。我看到的每個示例都只是忽略了空白區域,並未將其存儲以供以後使用。我想我會對評論有完全相同的問題,因爲它們基本上只是另一種被忽略的空間形式。
我原以爲這是一個標準的事情,但我找不到任何例子。任何人都知道類似的事情的例子?
源代碼在github上,如果有人想看看它並提出一種方法。
https://github.com/onefang/SledjHamr/blob/experimental/LuaSL/srcLuaSL_yaccer.l
,LuaSL_yaccer.y
,LuaSL_LSL_tree.h
和LuaSL_LSL_tree.c
識別空間柔性線有它的作用註釋掉。如果我取消註釋,我會得到一個解析錯誤。
SOLUTION
我利用bdonlan的解決方案,但我調到這個項目交給執行它的中間用檸檬代替btyacc。這就是我所做的。下面的源代碼被簡化了。
用檸檬創建一個調用詞法分析器的循環,然後您將詞法分析器調用的結果傳遞給解析器。我的循環每次都會分配一個新的yylval結構,該結構包含一個用於空格或註釋的char指針。我也使用這個yylval作爲我的AST節點結構,因爲它已經包含了我需要的大部分內容,並且不必花費時間重新分配內存或複製東西。
struct AST_node
{
struct AST_node *left;
struct AST_node *right;
char *white_space;
struct AST_token *token; /* common() stashes a pointer to a token structure here. */
int line, column;
union
{
/* The various types of symbols are stored here as per usual, including this one - */
int operationValue;
} value;
}
struct AST_node *lval = calloc(1, sizeof(struct AST_node);
while((yv = yylex(lval)) != 0)
{
Parse(pParser, yv, lval);
lval = calloc(1, sizeof(struct AST_node));
}
在詞法分析器中,我有一個從每個正則表達式操作部分調用的common()函數。除此之外,如果它是註釋或空白區域,我將文本保存到靜態累加器。如果它不是註釋或空格,那麼我將存儲器(如果存在)存儲在yylval結構中,並清除累加器。這個累加器將空白和註釋聚集在一起,因此yylval中的任何給定的一個都可以包含兩者。
詞法分析器如果只是空白/註釋,它不會返回符號,因此它會積累它們,直到發現一個實際的符號。
在檸檬中,所有終端和非終端都是yylval使用的類型,所以我可以將它傳遞給操作部分中的C代碼。例如 -
expr(A) ::= expr(B) LSL_ADD(D) expr(C). { A = addOperation(D, LSL_ADD, B, C); }
LSL_ADD是從詞法分析器發射的符號,並且d是它的價值,這是我在主循環中創建的的yylval傳遞給詞法分析器。在這種情況下,addOperation()將指向左右AST節點(B和C)的指針添加到AST結構(D)中,並將其中的符號集合到(以便後來我知道這個特定操作是一個加法) 。
struct AST_node *addOperation(struct AST_node *lval, int type, struct AST_node *left, struct AST_node *right)
{
lval->left = left;
lval->right = right;
lval->value.operationValue = type;
return lval;
}
後來,當我從AST重建原始的源代碼,我只輸出白色的空間/在同AST節點輸出符號之前的評論。
是的,我知道在上面的代碼中有一些重複,不需要存儲在令牌成員和聯合中的類型。我稍後會清理掉我的代碼。但現在,它用服務器來說明發生了什麼。
我是這個網站的新手,不確定Sangeeth編輯的內容是什麼。我喜歡我的空間,就像他們在哪裏一樣,添加連字符來「取消註釋」,對我來說似乎過於迂腐。聳聳肩 – 2012-01-09 11:21:55
是啊,如果你問我的一切,但文件名標記是過度的。這是'建議編輯'功能的缺點 - 相對較新的用戶進行了過度的編輯,只要他們不直接看到_wrong_他們往往會經歷...:/如果您不喜歡編輯,總是隨時回滾你自己的帖子。 – bdonlan 2012-01-10 00:34:59
查看我的回答,瞭解如何從AST重新生成源文本。它討論了你必須捕獲的內容,並提供了一些如何實現的想法。請參閱http://stackoverflow.com/a/5834775/120163 – 2016-05-07 20:48:41