2017-01-02 74 views
2

我正在爲ANTLR4中的編程語言編寫解析器。大多數情況下,我想忽略空白,但是有些情況下使用它來表示標記之間的邊界是至關重要的。ANTLR4 - 我的語言中可選的空白區域

例如,當解析運算符應用程序myvar = this + that時,我當前的解析器會將this+that作爲一個長標識符。這會導致解析器失敗,因爲名稱中不允許使用符號。我目前正在跳過所有的空白,這會導致這個問題,但我找不到一個解決方案,允許我使空白可選,但也用它來指定這些邊界。

我的解析器與我試圖解析的測試代碼一起在下面。

分析器:

grammar archie; 
// Parser Rules 

program: line* EOF; 

line: (element | COMMENT) (';' | '\n' | ';\n')+; 

//assignment: identifier EQ element; 

element: 
    //Function Call 
    element elementList | 

    //Function Literal 
    nameList FARROW element | 

    //Identifier 
    identifier | 

    //CombinedID 
    element (DOT name)+ | 

    //assignment 
    identifier EQ element | 

    O_C_BRACK (element (';' | '\n' | ';\n'))* C_C_BRACK | 

    element name element 
; 


elementList: O_R_BRACK element? (COMMA element)* C_R_BRACK; 

identifier: (name (DOT name)*); 

nameList: O_R_BRACK name? (COMMA name)* C_R_BRACK; 
name: (ALPHABET | SYMBOL+) (ALPHABET | NUMERIC)*; 

NUMERIC: [0-9]; 
ALPHABET: [a-zA-Z]; 
SYMBOL : [~!$^*&+#<>?|]; 
FARROW: '=>'; 
WS: [ \t]+ -> skip; 
SKP: [\r]+ -> skip; 
COMMENT: '//' (ALPHABET | SYMBOL | NUMERIC | WS)*; 

DOT: '.'; 
COMMA: ','; 

EQ: '='; 

O_R_BRACK: '('; 
C_R_BRACK: ')'; 
O_C_BRACK: '{'; 
C_C_BRACK: '}'; 

測試代碼:

this.that = that.this; 
this.this = that.other; 
that = this; 
that =() => that; 
a(); 
this + that; 

回答

4

只要我能解決你的主要問題,就是你的語法試圖單獨解析每個字符然後解析它們。這是行不通的,詞法分析員應該把語言的個別「詞彙」,這是讓你的語法如此怪異的原因。

您的其他問題是「test + test」解析爲「test」「+ test」。相反,我會建議下面的語法,它允許符號名稱,但它們不能與字母數字混合。

grammar archie; 
// Parser Rules 

programme: line* EOF; 

line 
: element (';' | '\n')+ 
| COMMENT 
; 

//assignment: identifier EQ element; 

element 
: element elementList   //Function Call 
| nameList FARROW element //Function Literal 
| identifier     //Identifier 
| element (DOT NAME)+   //CombinedID 
| identifier EQ element  //assignment 
| O_C_BRACK (element (';' | '\n' | ';\n'))* C_C_BRACK 
| element NAME element 
; 


elementList: O_R_BRACK element? (COMMA element)* C_R_BRACK; 

identifier: NAME (DOT NAME)*; 

nameList: O_R_BRACK (NAME COMMA)* (NAME COMMA?)? C_R_BRACK; 

NAME 
: [A-Za-z_][A-Za-z0-9_]* 
| [~!$^*&+#<>?|]+ 
; 

FARROW: '=>'; 
WS: [ \t]+ -> skip; 
SKP: [\r]+ -> skip; 
COMMENT: '//' ~[\n]* '\n'+; 

DOT: '.'; 
COMMA: ','; 

EQ: '='; 

O_R_BRACK: '('; 
C_R_BRACK: ')'; 
O_C_BRACK: '{'; 
C_C_BRACK: '}'; 

這會更改允許的標識符,但會實現您的總體目標。

前:

this + that // (element (element (name this)) (name +) (element (name that))) 
++that // (element (name ++that)) 
this+that // (element (element (name this)) (name +that) (element) and ERROR ERROR 

後:

this + that // (element (element this) + (element that)) 
++that // ERROR ERROR 
that+that // (element (element this) + (element that)) 

對不起,我認識到,@thst回答第一,但我工作的語法的解決方案,而當我去爲了測試它,我的antlr4設置已損壞,我正在修復該問題

3

的問題是,你的任期解析沒有明確的規定。

myvar = this + that 

被解析爲

element -> identifier EQ element <- identifier = myvar, 
            element = "this + that" 

this + that -> element name element 

這是不明確的:

element可以降低到標識符,其具有(1)的最小長度:

element(t) name(his) element(+that) 

element可能會盡可能地解析所有字符:

element(this) name(+that) element() <- error 
element(this) name(+tha) element(t) 

我認爲問題在於,您允許名稱的運算符作爲其字母表的一部分。