Я узнал, как. Возможно, это не лучший подход, но, похоже, он работает.
- Antlr парсеров получить параметр
ITokenStream
- Antlr лексеры сами
ITokenSource
s
ITokenSource
является значительно более простым интерфейсом, чем ITokenStream
- Самым простым способом преобразовать
ITokenSource
к ITokenStream
является использование CommonSourceStream
, который принимает параметр ITokenSource
Так что теперь нам нужно только сделать 2 вещи:
- Отрегулировать грамматику быть парсер только
- Реализовать ITokenSource
Регулировка грамматики очень просто. Просто удалите все объявления lexer и убедитесь, что вы объявляете грамматику как parser grammar
. Простой пример размещен здесь удобства:
parser grammar mygrammar;
options
{
language=CSharp2;
}
@parser::namespace { MyNamespace }
document: (WORD {Console.WriteLine($WORD.text);} |
NUMBER {Console.WriteLine($NUMBER.text);})*;
Обратите внимание, что следующий файл будет выводить class mygrammar
вместо class mygrammarParser
.
Итак, теперь мы хотим реализовать «поддельный» лексер. я лично использовал следующий псевдокод:
TokenQueue q = new TokenQueue();
//Do normal lexer stuff and output to q
CommonTokenStream cts = new CommonTokenStream(q);
mygrammar g = new mygrammar(cts);
g.document();
Наконец, нам нужно определить TokenQueue
. TokenQueue
не является строго необходимым, но я использовал его для удобства. Он должен иметь методы для получения лексерских токенов и методы вывода маркеров Antlr. Поэтому, если вы не используете собственные токены Antlr, вам нужно реализовать метод конвертирования в Antlr-token. Кроме того, TokenQueue
должен реализовать ITokenSource
.
Помните, что очень важно правильно установить переменные токена. Первоначально у меня были некоторые проблемы, потому что я просчитывал CharPositionInLine
. Если эти переменные установлены неправильно, то анализатор может выйти из строя. Кроме того, нормальный канал (не скрытый) равен 0.
Это, кажется, работает для меня до сих пор. Я надеюсь, что другие считают это полезным. Я открыт для обратной связи. В частности, если вы найдете лучший способ решить эту проблему, не стесняйтесь публиковать отдельный ответ.
Моя рекомендация заключается в том, что вы можете учиться на существующих. Тем не менее, я могу найти только NHibernate, который использует Antlr, и использование довольно ограничено. :( –
* «но тогда есть небольшие части, которые не имеют и невероятно болезненны для решения» * - Нечетная. Лексическая часть языка обычно проще реализовать. Возможно, вы могли бы объяснить, что «мелкие детали» дают вам Проблемы? –
@Bart Kiers У меня возникли проблемы с внедрением диапазонов и несколькими другими функциями (такими как 3.toString() и 3.0.toString()) по-другому, чем в списке, указанном в их FAQ. невероятно просто решить в создаваемом вручную лексере. – luiscubal