2013-05-13 2 views
2

У меня есть проблема с EBNF грамматикой в ​​ANTLRWorks:EBNF грамматика (ANTLR)

line 37:  
upper_lower_case 
: LOWER_CASE 
| UPPER_CASE 
; 

line 42: 
CLASSNAME 
: UPPER_CASE (DIGITS | upper_lower_case)* 
; 

line 51: 
UPPER_CASE 
: 'A'..'Z' 
; 

line 55: 
LOWER_CASE 
: 'a'..'z' 
; 

line 60: 
DIGITS : '0'..'9' 
; 

Я хочу Classname всегда начинать с заглавной буквой, а чем она может состоять из цифр, верхних и строчных букв ,

Журнал ошибок:

[13:11:59] warning(200): classgenerator.g:43:42: 
Decision can match input such as "'0'..'9'" using multiple alternatives: 1, 2 

As a result, alternative(s) 2 were disabled for that input 
[13:11:59] warning(200): classgenerator.g:43:42: 
Decision can match input such as "<EOT>" using multiple alternatives: 2, 3 

As a result, alternative(s) 3 were disabled for that input 
[13:11:59] error(201): classgenerator.g:43:42: The following alternatives can never be 
matched: 3 

[13:11:59] error(208): classgenerator.g:60:1: The following token definitions can never 
be matched because prior tokens match the same input: UPPER_CASE,DIGITS 

Может кто-нибудь помочь мне решить эту проблему? Спасибо заранее.

С уважением, Hladeo

EDIT:

Так что я должен использовать фрагмент ключевое слово, если оно не относится к лексем? Таким образом, использование ключевого слова фрагмента будет неправильным?

tokens { 
PUBLIC = '+'; 
PRIVATE = '-'; 
PROTECTED = '='; 
} 

fragment ACCESSOR 
: PUBLIC 
| PRIVATE 
| PROTECTED 
; 

и другой вопрос.

OBJECTNAME 
: UPPER_LOWER_CASE (UPPER_LOWER_CASE | DIGIT)* 
; 

OBJECTNAME должен состоять, по меньшей мере, одной буквы (верхний или нижний регистр не имеет значения) и, возможно, из других букв или цифр - то, что случилось с этой частью коды? Когда я пытаюсь ввести, например variable - это нормально, но когда я начинаю с заглавной буквой Variable я получаю сообщение об ошибке:

line 1:15 mismatched input 'Variable' expecting OBJECTNAME 

ответ

2

Вашего правило лексер CLASSNAME в настоящее время ссылается правило синтаксического анализа upper_lower_case (правила лексера начинаются с заглавной буквой письмо, правила парсера начинаются с нижнего регистра). Правила Lexer могут ссылаться только на правила lexer.

Кроме того, оказывается, что UPPER_CASE, LOWER_CASE и DIGITS не должны создавать лексем себя таким образом, они должны быть помечены как fragment правил. В следующем примере я изменил DIGITS на DIGIT, так как он всегда соответствует одной цифре.

CLASSNAME : UPPER_CASE (DIGIT | UPPER_LOWER_CASE)*; 

fragment UPPER_LOWER_CASE : LOWER_CASE | UPPER_CASE; 
fragment UPPER_CASE : 'A'..'Z'; 
fragment LOWER_CASE : 'a'..'z'; 
fragment DIGIT : '0'..'9'; 

Edit 1 (для редактирования в вопросе):

  • Кусок текста на входе может иметь только один тип маркера. Например, рассмотрите вводный текст X3. Поскольку этот текст может соответствовать CLASSNAME или OBJECTNAME, лексер в конечном итоге назначит ему тип первого правила, появляющегося в грамматике. Другими словами, если CLASSNAME появляется перед OBJECTNAME в грамматике, вход X3 будет всегда быть CLASSNAME маркер и никогда быть OBJECTNAME маркер. Если OBJECTNAME появляется перед CLASSNAME в грамматике, вход X3 будет всегда быть OBJECTNAME и никогда быть CLASSNAME (на самом деле, в этом случае маркер не будет когда-либо быть CLASSNAME).

  • Ваше ACCESSOR правило выглядит это должно быть правилом синтаксического анализа, как следующее:

    accessor : PUBLIC | PROTECTED | PRIVATE; 
    

Edit 2 (для комментариев по поводу выделения CLASSNAME и OBJECTNAME):

Чтобы отличить CLASSNAME и OBJECTNAME, вы можете создать правило lexer IDENTIFIER, которое соответствует либо.

IDENTIFIER : UPPER_LOWER_CASE (DIGIT | UPPER_LOWER_CASE)*; 

Вы можете создать правило синтаксического анализа для обработки различия:

classname : IDENTIFIER; 
objectname : IDENTIFIER; 

Очевидно, что это позволяет быть classname, который не действует на вашем языке. Когда это возможно, я всегда предпочитаю немного ослаблять правила анализатора и выполнять дальнейшую проверку позже, когда я могу обеспечить лучшее сообщение об ошибке. Например, если вы разрешите соответствовать classname, то после того, как вы проанализируете ввод и получите AST (ANTLR 3) или дерево синтаксического анализа (ANTLR 4), вы можете посмотреть все экземпляры classname и убедиться, что соответствие IDENTIFIER начинается с требуемое письмо в верхнем регистре.

сообщение Пример ошибки, образуемый путем автоматического сообщения об ошибках парсера:

line 1:15 mismatched input 'variable' expecting CLASSNAME

Пример сообщения об ошибке производства отдельной проверки:

line 1:15 class name variable must start with an upper case letter

+0

Спасибо за ответ. Не могли бы вы ответить на мои новые вопросы? Я отредактировал первый пост. – Hladeo

+0

Так есть ли возможность отличить CLASSNAME и OBJECTNAME? Я пишу простой генератор классов Java, где я мог бы ввести: 'create ClassName + name: String, -age: int;' где variable, age, String и int являются объектами OBJECTNAME. – Hladeo

+0

@Hladeo См. Редактирование 2 в моем ответе :) –