Поведінка за замовчуванням, коли синтаксичний аналізатор не знає, що робити, це друкувати повідомлення на терміналі, наприклад:
рядок 1:23 відсутній DECIMAL на '}'
Це гарне повідомлення, але не в тому місці. Я волів би отримати це як виняток.
Я спробував використовувати BailErrorStrategy
, але це видає a ParseCancellationException
без повідомлення (викликане a InputMismatchException
, також без повідомлення).
Чи можу я змусити його повідомляти про помилки через винятки, зберігаючи корисну інформацію в повідомленні?
Ось що я насправді шукаю - я зазвичай використовую дії в правилах для побудови об’єкта:
dataspec returns [DataExtractor extractor]
@init {
DataExtractorBuilder builder = new DataExtractorBuilder(layout);
}
@after {
$extractor = builder.create();
}
: first=expr { builder.addAll($first.values); } (COMMA next=expr { builder.addAll($next.values); })* EOF
;
expr returns [List<ValueExtractor> values]
: a=atom { $values = Arrays.asList($a.val); }
| fields=fieldrange { $values = values($fields.fields); }
| '%' { $values = null; }
| ASTERISK { $values = values(layout); }
;
Потім, коли я викликаю парсер, я роблю щось подібне:
public static DataExtractor create(String dataspec) {
CharStream stream = new ANTLRInputStream(dataspec);
DataSpecificationLexer lexer = new DataSpecificationLexer(stream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DataSpecificationParser parser = new DataSpecificationParser(tokens);
return parser.dataspec().extractor;
}
Все, що я справді хочу, - це
- для
dataspec()
виклику видавати виняток (в ідеалі перевірений), коли вхід неможливо проаналізувати - щоб цей виняток мав корисне повідомлення та забезпечував доступ до номера рядка та місця, де було виявлено проблему
Тоді я дозволю цьому винятку створити бульбашку, де б там не було, якнайкраще підходить для подання корисного повідомлення користувачеві - так само, як я б обробляв розірване мережеве підключення, читання пошкодженого файлу тощо.
Я бачив, що дії зараз вважаються "просунутими" в ANTLR4, тому, можливо, я дивлюся на щось дивно, але я не вивчав, яким би був "непросунутий" спосіб зробити це, оскільки таким чином добре працює для наших потреб.