Я пытаюсь сопоставить измерения в тексте ввода на английском языке, используя Antlr 3.2 и Java1.6. У меня есть лексические правила, подобные следующим:
fragment
MILLIMETRE
: 'millimetre' | 'millimetres'
| 'millimeter' | 'millimeters'
| 'mm'
;
MEASUREMENT
: MILLIMETRE | CENTIMETRE | ... ;
Я хотел бы иметь возможность принимать любую комбинацию ввода в верхнем и нижнем регистре и, что более важно, просто возвращать один лексический токен для всех вариантов MILLIMETRE. Но на данный момент мой AST содержит «миллиметры», «миллиметры», «мм» и т. д., как и во входном тексте.
После прочтения http://www.antlr.org/wiki/pages/viewpage.action?pageId=1802308, думаю, мне нужно сделать что-то вроде следующего:
tokens {
T_MILLIMETRE;
}
fragment
MILLIMETRE
: ('millimetre' | 'millimetres'
| 'millimeter' | 'millimeters'
| 'mm') { $type = T_MILLIMETRE; }
;
Однако, когда я это делаю, я получаю следующие ошибки компилятора в коде Java, сгенерированном Antlr:
cannot find symbol
_type = T_MILLIMETRE;
Вместо этого я попробовал следующее:
MEASUREMENT
: MILLIMETRE { $type = T_MILLIMETRE; }
| ...
но тогда ИЗМЕРЕНИЕ больше не соответствует.
Более очевидное решение с правилом перезаписи:
MEASUREMENT
: MILLIMETRE -> ^(T_MILLIMETRE MILLIMETRE)
| ...
вызывает NPE:
java.lang.NullPointerException at org.antlr.grammar.v2.DefineGrammarItemsWalker.alternative(DefineGrammarItemsWalker.java:1555).
Включение MEASUREMENT в правило синтаксического анализатора дает мне ужасную ошибку «Следующие определения токенов никогда не могут быть сопоставлены, потому что предыдущие токены соответствуют одному и тому же входу».
Создав правило парсера
measurement : T_MILLIMETRE | ...
Я получаю предупреждение «нет правила лексера, соответствующего токену: T_MILLIMETRE». Хотя Antlr работает, но он по-прежнему дает мне входной текст в AST, а не T_MILLIMETRE.
Очевидно, я еще не вижу мир так, как Antlr. Может ли кто-нибудь дать мне какие-либо советы или советы, пожалуйста?
Стив
