2010-01-12 5 views
3

У меня возникла небольшая проблема с ручным испусканием токена с помощью правила lexer в ANTLR. Я знаю, что функция emit() должна использоваться, но, похоже, существует четкая нехватка документации об этом. У кого-нибудь есть хороший пример того, как это сделать?Вручную выдавать токен с ANTLR

Книга ANTLR дает хороший пример того, как вам нужно это сделать, чтобы разобрать гнездо Python. Например, если вы видите определенное количество пробелов, которое больше, чем пробел предыдущей строки, испустите токен INDENT, но если он меньше, испустите токен DEDENT. К сожалению, книга затушевывает реальный синтаксис, который требуется.

EDIT: Вот пример того, что я пытаюсь проанализировать. Это вложенные уценки по блокам цитат:

before blockquote 

> text1 
> 
> > text2 
> 
> text3 

outside blockquote 

Теперь мой подход до сих пор по существу считать > символов в строку. Например, приведенное выше кажется, что оно должно испускать (грубо ...) PARAGRAPH_START, CDATA, PARAGRAPH_END, BQUOTE_START, CDATA, BQUOTE_START, CDATA, BQUOTE_END, CDATA, BQUOTE_END, PARAGRAPH_START, CDATA, PARAGRAPH_END. Трудность здесь - это окончательный BQUOTE_END, который, как мне кажется, должен быть мнимым маркером, испускаемым после того, как найден неблокирующий элемент (и уровень вложенности> = 1)

+0

Скотт, не могли бы вы привести пример того, что вы пытаетесь разобрать? –

+0

Вы упоминаете Python в вопросе, но фактически не говорите, на каком языке вы используете. Я привел пример, который делает это на C++. – chollida

ответ

2

Ну, если токен, который вы хотите испустить, не определяется правилу лексического, то вам нужно добавить маркер раздела следующим образом:

tokens 
{ 
    MYFAKETOKEN 
} 

в вашем лексере вам все равно нужно правило, которое говорит о лексере когда производить этот маркер. Обычный экземпляр определяет, является ли что-то целым или диапазоном или реальным значением.

NUMBERS_OR_RANGE 
: INT 
     ({ LA(1) == '.' && LA(2) == '.' }? { _ttype = INT; } 
    | { LA(1) == '.' || LA(1) == 'e' || LA(1) == 'E' }? { _ttype = REAL; } 
    ) 
| PERIOD 
    (PERIOD { _ttype = RANGE; } 
    INT (('e' | 'E') ('-' | '+')? INT)? { _ttype = REAL; } 
) 
; 

Здесь вы можете увидеть, мы сопоставляем либо в INT, а затем предпросмотр, если мы находим двойной период, то мы знаем, что INT действительно является INT, а не реальным. В этом случае переменная _ttype устанавливается как INT. Если мы найдем ПЕРИОД, а затем «е», мы знаем, что это реально.

Второй случай, когда мы сопоставляем период, когда мы знаем, что если следующий символ - это период, тогда у нас есть диапазон, иначе у нас есть реальный.

Мы можем использовать тип MYFAKETOKEN, который мы определили выше, чтобы назначить _ttype, если это необходимо.

+0

Спасибо, это очень близко к тому, что я ищу ... Я уточнил вопрос с более конкретным примером, как и требовалось. Если у вас есть какие-то идеи, это было бы высоко оценено! – Scott

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