Как обрабатывать специфичные для языка зарезервированные слова, которые встречаются в выражениях или именах переменных

Я работаю над этой проблемой около 4 часов. Вот мой файл грамматики ANTLR V4, который я сократил, чтобы быть самым простым из возможных.

grammar Cfscript;

component
    : (statement)*
    ;

statement
    : 'return' expression? ';'
    | statementExpression ';'
    ;

statementExpression
    : expression
    ;

expression
    : primary
    | expression '.' Identifier
    ;

primary
    : Identifier
    ;

Identifier
    : [a-zA-Z0-9_]+
    ;

WS
    : [ \t\r\n]+ -> skip 
    ;

Мой файл содержит

local.return;

Когда я пытаюсь разобрать этот файл, введя component, я получаю следующую ошибку: mismatched input 'return' expecting Identifier. Я не могу понять, почему возникает эта ошибка.

Обновить

Если я правильно понимаю, это потому, что return - зарезервированное слово в Java, и именно поэтому они структурировали свою грамматику таким образом. На моем языке, Coldfusion Cfscript, return действителен до тех пор, пока имеет область видимости: local.return, variables.return, local["return"]. Это также верно для if, else, savecontent и многих других слов, все из которых действительны только в пределах области видимости, но не в качестве первого члена переменной или выражения: if.blah = "something" недопустимо, но blah.if = "something" допустимо. Это означает, что я столкнусь с той же проблемой с каждым из этих терминов, поскольку они будут конфликтовать с правилом синтаксического анализатора, которое их захватывает.

Обобщая то, что сказал Барт, является ли это чистым способом решения этой проблемы?

grammar Cfscript;

component
    : (statement)*
    ;

statement
    : K_Return expression? ';'
    | expression ';'
    ;

expression
    : primary
    | expression '.' secondary
    ;

primary
    : Identifier
    ;

secondary
    : K_Return
    | K_If
    | K_Else
    | Identifier
    ;

K_Return : 'return' ;
K_If : 'if' ;
K_Else : 'else' ;

Identifier
    : [a-zA-Z0-9_]+
    ;

WS
    : [ \t\r\n]+ -> skip 
    ;

person Nucleon    schedule 11.03.2013    source источник


Ответы (1)


Добавление буквальных токенов внутри правил синтаксического анализатора, как вы это сделали с 'return', не означает, что лексер будет соответствовать строке "return" как Identifier внутри второй альтернативы в вашем expression правиле:

expression '.' Identifier

Если вы хотите сопоставить "return" как ключевое слово и как идентификатор на вашем языке, вам необходимо создать правило синтаксического анализатора, которое соответствует как Identifiers, так и ключевым словам:

expression
    : primary
    | expression '.' id
    ;

primary
    : id
    ;

id
    : Identifier
    | K_Return
    ;

// Better explicitly define them instead of litering keywords inside parser rules
K_Return
    : 'return'
    ;

Identifier
    : [a-zA-Z0-9_]+
    ;
person Bart Kiers    schedule 11.03.2013
comment
Если это так, то как функционирует официальная грамматика Java? - person Nucleon; 11.03.2013
comment
@Nucleon, он не допускает local.return; в качестве допустимого выражения. - person Bart Kiers; 11.03.2013
comment
Как обычно, Барт, отличный ответ, я обновил свой вопрос, основываясь на том, что я узнал из вашего ответа, не могли бы вы просмотреть его, чтобы увидеть, является ли это действенным способом очистки этого. - person Nucleon; 11.03.2013
comment
@Nucleon, да, похоже, все в порядке. - person Bart Kiers; 11.03.2013