Возможно, вы не указали prog
в качестве начального правила в ANTLRWorks.Если вы это сделаете, все будет хорошо.
Но вы действительно не должны создавать правило лексера, которое соответствует выражению, как вы делаете в ADDNUM
: это должно быть правило синтаксического анализатора:
grammar Example;
prog : addExpr EOF;
addExpr : INT PLUS INT;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
INT : '0'..'9'+;
PLUS : '+';
ANTLR правила
Нет строгих правил, когда использовать правила синтаксического анализа, лексера или фрагмента, но вот для чего они обычно используются:
правила лексера
Правило лексераобычно самая маленькая часть языка (строка, числа, идентификатор, комментарий и т. д.).Попытка создать правило лексера из ввода, например 1+2
, вызывает проблемы, потому что:
- , если вы когда-нибудь захотите извлечь что-то значимое из этого токена (например, оцените его), вам нужно разделить содержимоеэтого токена, потому что после создания 1 токена из него текст всего выражения «склеивается»;
- вы сталкиваетесь с проблемами, если между ними есть пробел:
1 + 2
.
Выражение 1+2
- это три токена: INT
, PLUS
и еще один INT
.
правила фрагмента
Правило фрагмента используется, когда вы не используетене хочу, чтобы это правило когда-либо существовало, потому что это «настоящий» токен.Например, возьмите следующие правила лексера:
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
FLOAT : '0'..'9'+ '.' '0'..'9'+;
INT : '0'..'9'+;
В приведенных выше правилах вы используете '0'..'9'
четыре раза, так что вы можете поместить это в отдельное правило
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | DIGIT)*
FLOAT : DIGIT+ '.' DIGIT+;
INT : DIGIT+;
DIGIT : '0'..'9';
Но вы не хотите когда-либо создавать токен DIGIT
: вам нужно, чтобы DIGIT
использовался другими правилами лексера.В этом случае вы можете создать fragment
правило:
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | DIGIT)*
FLOAT : DIGIT+ '.' DIGIT+;
INT : DIGIT+;
fragment DIGIT : '0'..'9';
. Это гарантирует, что никогда не будет токена DIGIT
: и поэтому никогда не сможет использовать его в ваших правилах синтаксического анализа!
правила парсера
Правила парсера склеивают токены: они гарантируют, что язык синтаксически действителен (он же синтаксический анализ) .Чтобы подчеркнуть, правила синтаксического анализатора могут использовать другие правила синтаксического анализатора или правила лексера, но не правила фрагмента.
Также см .: ANTLR: есть простой пример?