#java #antlr #antlr3
#java #antlr #antlr3
Вопрос:
Это моя древовидная грамматика:
grammar t;
options{
output = AST;
}
type
:
'NVARCHAR' -> "VARCHAR"
;
ANTLR3 3.1.3 гласит:
syntax error: antlr: t.g:12:5: unexpected token: 'NVARCHAR'
Что здесь не так? Я взял это из этой статьи.
ps. Я использую эту грамматику позже, чтобы извлечь из нее AST. Как только AST извлекается, я просматриваю его и добавляю текст каждого токена в некоторый строковый буфер. Идея переписывания выше заключается в замене определенных токенов. Я делаю сопоставление языка с языком (SQL с диалектом SQL, чтобы быть более конкретным).
Ответ №1:
Обратите внимание на первое предложение, с которого начинается Теренс: «только что пришло несколько классных идей о языке спецификации семантических правил …». Вот что такое первый пример: идея. Это недопустимый синтаксис.
Для вас есть (как минимум) два варианта:
1. немедленно перепишите текст в токене
grammar T;
options{
output=AST;
}
@parser::members {
public static void main(String[] args) throws Exception {
TLexer lexer = new TLexer(new ANTLRStringStream("NVARCHAR"));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.type();
}
}
type
: NVARCHAR {System.out.println("token=" $NVARCHAR.text);}
;
NVARCHAR
: 'NVARCHAR' {setText("VARCHAR");}
;
Но это только корректирует text
, а не type
токен, который остается NVARCHAR
типом.
2. используйте воображаемый токен:
grammar T;
options{
output=AST;
}
tokens {
VARCHAR='VARCHAR';
}
@parser::members {
public static void main(String[] args) throws Exception {
TLexer lexer = new TLexer(new ANTLRStringStream("NVARCHAR"));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.type();
}
}
type
: NVARCHAR -> VARCHAR
;
NVARCHAR
: 'NVARCHAR'
;
которое изменяет text
и type
токена.
Как вы можете видеть, в обеих демонстрациях token=VARCHAR
выводится на консоль:
bart@hades:~/Programming/ANTLR/Demos/T$ java -cp antlr-3.3.jar org.antlr.Tool T.g bart@hades:~/Programming/ANTLR/Demos/T$ javac -cp antlr-3.3.jar *.java bart@hades:~/Programming/ANTLR/Demos/T$ java -cp .:antlr-3.3.jar TParser токен = VARCHAR
Комментарии:
1. @Bart Мне нравится первый вариант (с
setText()
), но он не работает. ANTLR генерирует.java
класс, который не компилируется:cannot find symbol method setText(java.lang.String) in TParser
. Есть идеи?2. @yegor256, это действительно работает. Посмотрите демо, которое я добавил. Я предполагаю, что вы пытаетесь вызвать этот метод внутри правила синтаксического анализа (мое предложение показывает это в правиле лексера).
3. @Bart У меня есть древовидная грамматика, как в вопросе выше. Не могли бы вы, пожалуйста, внести исправления в мой пример?
4. @yegor256, нет, ты опубликовал комбинированную грамматику, которая выводит AST. Древовидная грамматика начинается с
tree grammar T;
вместоgrammar T;
. Или вы не включили свою древовидную грамматику? Вы сказали, что хотите изменить текст токена. Тип токена просто останетсяNVARCHAR
(с текстом:"VARCHAR"
). Возможно, пришло время отредактировать ваш вопрос и добавить еще немного информации.5. @Bart Я добавил некоторые детали к своему вопросу, надеюсь, что они лучше объяснят ситуацию. Вы правы, это грамматика, которая выводит AST. Мне нужно получить AST с «уже замененными» токенами. Имеет смысл?
Ответ №2:
в antlr4 замена текста и типа может быть достигнута с помощью type
действия:
OldTokenType:
('Token1' | 'Token2' | 'Token3' ) {setText("New Token");}
-> type(NewTokenType);