2016-10-15 101 views
-1

我使用ANTLR4來解析一些「簡化」的C風格源代碼。我的語法如下:匹配到函數結束

grammar Language; 

script: (include)* (functionDefinition)* EOF; 

include: '#include' Blank FilePath Semicolon; 

functionName: FileName; 

functionDefinition: functionName '(' parameters ')' '{' functionBody '}'; 

functionBody: .*?; // This needs fixing 

parameter: FileName; 

parameters: parameter (',' Blank parameter)*; 

FileName: AlphaCharacter WordCharacter*; 

FilePath: FileName ChildFilePath*; 

ChildFilePath: PathSlash FileName; 

PathSlash: ForwardSlash | BackwardSlash; 

ForwardSlash: '/'; 

BackwardSlash: '\\'; 

AlphaCharacter: [a-zA-Z]; 

WordCharacter: [a-zA-Z_0-9]; 

Blank: ' '; 

Whitespace: (' ' | '\t' | '\r' | '\n'); 

Semicolon: ';'; 

SkipWhitespaces: Whitespace+ -> skip; 

鑑於以下輸入文本:

#include testWz/fdrf675tr\a56s; 
#include testWz/fdrftr\s; 

func1(param, par) 
{ 
    if(true) 
    { 
     whatever(); 
    } 
} 

func2() 
{ 

} 

我實現下面的訪問,看看發生了什麼事情:

public class ListenerPrinter extends LanguageBaseListener 
{ 
    @Override 
    public void enterInclude(LanguageParser.IncludeContext context) 
    { 
     System.out.println("[INCLUDE] " + context.FilePath().getText()); 
    } 

    @Override 
    public void enterFunctionDefinition(LanguageParser.FunctionDefinitionContext definition) 
    { 
     LanguageParser.ParametersContext parameters = definition.parameters(); 
     System.out.println("[FUNCTION DEFINITION] " + definition.getText()); 
     System.out.println("[PARAMETERS] " + parameters.getText()); 
     System.out.println("[BODY] " + definition.functionBody().getText()); 
    } 
} 

我想正確檢測函數體沒有將它們分解成它們的組件,因爲這當然是更多的工作。到目前爲止,將生成以下輸出:

[INCLUDE] testWz/fdrf675tr\a56s 
[INCLUDE] testWz/fdrftr\s 
[FUNCTION DEFINITION] func1(param, par){if(true){whatever();}}func2(){} 
[PARAMETERS] param, par 
[BODY] if(true){whatever();}}func2(){ 

函數體太長,並且還包括下一個函數的定義。一個想法是檢測下一個右括號+在兩者之間找到的已打開括號的數量,但我不確定如何單獨使用語法規則來做到這一點。

+0

您的「簡化」C是否允許函數包含嵌套的{...}?您意味着用*檢測...在兩者之間找到的已打開括號的數量。如果是這樣,一個簡單的正則表達式不能拿起函數體,因爲正則表達式不能匹配任意的括號。如果不是,你簡化的C是不現實的,你不清楚你將通過一個不切實際的語言做這個練習會學到什麼,你可以在別的地方使用它。 –

+0

@IraBaxter:它不是一種不現實的語言,因爲它作爲腳本引擎存在。我也不確定你的意思是嵌套{...},因爲存在常規的'if'和'while'循環,但是沒有「嵌套在另一個函數中的函數」,這是非常不尋常的 – BullyWiiPlaza

+0

你允許嵌套{ ...}?例如,如果c {... if d {} ...}?這很常見。一種不允許他們的語言是非常罕見的。 –

回答

-1

functionBody是一個匹配全部規則。非貪婪修飾符在這裏沒有幫助,因爲規則本身沒有終止令牌。因此,嘗試刪除它,而是把通配符匹配到functionDefinition規則:

functionDefinition: functionName '(' parameters ')' '{' .*? '}'; 

或可選擇地移動大括號的functionBody規則:

functionDefinition: functionName '(' parameters ')' functionBody; 
functionBody: OpenCurly .*? CloseCurly; 

注:我用詞法規則捲曲通過意圖大括號。建議在自己的規則中定義所有詞法分析標記,而不是隱式地在分析器規則中定義(避免像多個定義,自動分配的標記名稱等那樣的麻煩)。


UPDATE

我不知道所需要的解決方案應支持大括號分隔嵌套塊(整個問題可能需要一些拋光,這就是爲什麼有接近3票)。解決方案的一般原則是您定義一個或多個明確定義花括號對的規則,以便只有在開始和結束花括號均衡時才匹配規則。你可以做這樣的:

functionBody: OpenCurly .*? (functionBody .*?)? CloseCurly; 

即遞歸定義functionBody含有本身。

+0

你的兩個建議仍然會產生相同(不正確)的結果,所以我可能還需要描述一切?但是這不應該是必要的: – BullyWiiPlaza

+0

@MikeLischke:OP告訴我們{...}在他的語言嵌套中是任意深的,你正在使用一個正則表達式來試圖通過找到最外層的{}來匹配一個函數體。 –

+0

@IraBaxter是的,你是對的,我更新了我的答案 –