2014-06-12 61 views
0

我正在爲包含特殊預處理器部分中的預處理器指令的語言(由{}包含)構建解析器。其中之一與C#define類似。如何在兩個單獨的詞法分析模式中使用詞法分析器規則?

我想在一次運行中使用針對預處理器部件的孤島語法來分析文件。 當我點擊#define指令時,我想包含另一個孤島語法,其中包含「常規」部分的所有標記(大約200個),除了預處理區域開始標記並在不同通道上發出標記以及當然有一個停止令牌返回到預處理器島語法。由於我解析的文件是有效的,所以預處理器區域起始令牌{真的被刪除並不是非常重要,但會很好。

有沒有辦法爲兩種模式「重複使用」詞法分析器規則(我可以發射到命名的非const通道,該值可以在進入/離開島時改變)?

這是一些示例源文件:

int a = 42; 

{ // start preprocessor section 

// simple single line #define 
#define ABC 42 

// will be fix "2 * 42" even if ABS is changed later on 
#define DEF 2 * ABC 

// multiple line define (all but last line needs to have a "\" before the newline 
#define GHI 3 \ 
       + 4 

// the definition can contain (almost) arbitrary code, except line comments, preprocessor sections and preprocessor statements 
#define JKL if (a > 23) then b = c + d; str = "} <- this must not be the end of the preprocessor section"; end_if;    

} // end preprocessor section 

回答

1

您當前無法重用/導入在一個模式定義爲另一個詞法規則。我通常做類似以下的事情。

LBRACE : '{'; 

mode OtherMode; 

    OtherMode_LBRACE : LBRACE -> type(LBRACE); 

由於在ANTLR 4工具代碼生成優化,構建像上面也不會真正創造一個單獨的OtherMode_LBRACE令牌由於該規則使用type詞法分析器的命令。

+0

這就是我對「少數」規則的做法。 200條規則的做法是什麼? – Onur

+0

@Onur以這種形式創建原始規則的200份副本。 –

+0

我採取了你的方法,雖然我不手動做樣板代碼(請參閱我的答案)。 – Onur

0

我終於採取了方法來簡單地複製Sam提出的規則。我首先嚐試從另一種模式返回到主模式,並在某個位置檢查是否要使用嵌入式操作返回,並使用設置「當前活動頻道」的操作並將其添加到所有規則中,但這會混淆所有規則並沒有「感覺到正確的事情」。

減少人工工作,我改組我的詞法分析文件,現在可以很容易地複製到被包含在其他模式的規則和使用正則表達式的其他模式部分改造它們,將它們插入:

搜索:

^\s*(([a-z_0-9]+)[ \t\n]*)(:.*?;)\n 

與替換(PPP_只是一個前綴我選擇):

PPP_$1 : $2 -> type\($2\), channel\(2\); \n\t\t\t/*$3*/\n 

和使用正則EXP激活選項「忽略大小寫」,「單行」,「多行」

如果您不想將令牌發送到另一個通道,請刪除channel(2)部件。 我選擇的編輯(記事本+ +)需要我脫離大括號,你的可能不會。