2017-01-02 10 views
2

Я пишу парсер для языка программирования в ANTLR4. В основном я хочу игнорировать пробелы, однако есть некоторые случаи, когда важно использовать его для обозначения границы между токенами.ANTLR4 - Дополнительное пустое пространство на моем языке

Например, при разборе операторского приложения myvar = this + that мой текущий синтаксический анализатор будет принимать this+that как один длинный идентификатор. Это приведет к сбою синтаксического анализа, поскольку символы не разрешены в именах. В настоящее время я пропускаю все пробелы, что вызывает эту проблему, но я не могу найти решение, которое позволяет мне делать необязательные пробелы, но также использовать его для обозначения этих границ.

Мой парсер ниже вместе с тестовым кодом, который я пытаюсь проанализировать.

Parser:

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

Насколько я могу решить, ваша основная проблема заключается в том, что ваша грамматика пытается лечить каждый символ в отдельности, а затем анализировать их. Это не сработает, лексеры должны лечить отдельные «слова» этого языка, и это то, что делает вашу грамматику такой странной.

Другая проблема заключается в том, что «тест + тест» анализируется как «тест» «+ тест». Вместо этого я бы посоветовал следующую грамматику, которая допускает символические имена, но они не могут смешивать с буквенно-цифровыми.

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) 

Проблема на мой взгляд заключается в том, что вы разрешаете именам операторов как часть их алфавита.

 Смежные вопросы

  • Нет связанных вопросов^_^