ANTLR4 Правильно продолжать разбирать разделы после ошибки - PullRequest
0 голосов
/ 03 ноября 2018

Я пытаюсь написать некоторые инструменты (проверка / возможно автозаполнение) для языка запросов SQL-esk. Однако синтаксический анализатор разбивает токены на недопустимые / неполные входные данные таким образом, что затрудняет работу с ним.

Я сократил свой сценарий до его самой простой воспроизводимой формы. Вот моя минимизированная грамматика:

grammar SOQL;

WHITE_SPACE : ( ' '|'\r'|'\t'|'\n' ) -> channel(HIDDEN) ;

FROM    : 'FROM' ;
SELECT  : 'SELECT' ;

/********** SYMBOLS **********/


COMMA       : ',' ;

ID: ( 'A'..'Z' | 'a'..'z' | '_' | '$') ( 'A'..'Z' | 'a'..'z' | '_' | '$' | '0'..'9' )* ;

soql_query:    select_clause from_clause;
select_clause: SELECT field ( COMMA field )*;
from_clause:   FROM table;

field : ID;
table : ID;

Когда я запускаю следующий код (используя antlr4ts , но он должен быть похож на любой другой порт):

const input = 'SELECT ID, Name, Website, Contact, FROM Account'; //invalid trailing ,
let inputStream = new ANTLRInputStream(input);
let lexer = new SOQLLexer(inputStream);
let tokenStream = new CommonTokenStream(lexer);
let parser = new SOQLParser(tokenStream);

let qry = parser.soql_query();
let select = qry.select_clause();
console.log('FIELDS: ', select.field().map(field => field.text));
console.log('FROM: ', qry.from_clause().text);

Журнал консоли

line 1:35 extraneous input 'FROM' expecting ID
line 1:47 mismatched input '<EOF>' expecting 'FROM'
FIELDS: Array(5) ["ID", "Name", "Website", "Contact", "FROMAccount"]
FROM:  

Я получаю ошибки (что ожидается), но я надеялся, что он все равно сможет правильно выбрать предложение FROM.

Это было мое понимание, поскольку FROM - это идентификатор, это недопустимое поле в select_clause (может быть, я просто неправильно понимаю)?

Есть ли способ настроить грамматику или синтаксический анализатор так, чтобы он продолжал правильно определять предложение FROM в этом сценарии (и другие общие состояния запроса WIP).

1 Ответ

0 голосов
/ 04 ноября 2018

Это было мое понимание, поскольку FROM является идентификатором, он недействителен поле в select_clause (может я просто недопонимаю)?

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

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

Две функции ANTLR, особенно полезные для этой цели, включают:

1) реализовать лексер TokenFactory и пользовательский токен, обычно расширяющий CommonToken. Пользовательский токен предоставляет удобное пространство для флагов и логики для определения правильного синтаксического / семантического использования и ожидаемого контекста для конкретного экземпляра токена.

2) реализовать стратегию обработки ошибок синтаксического анализатора, расширяющую или расширяющую DefaultErrorStrategy . Стратегия ошибок позволит скромные изменения в работе анализатора в потоке токенов, когда попытка совпадения приведет к ошибке распознавания. Если ошибка не может быть полностью устранена и надлежащим образом исправлена ​​при проверке окружающих (пользовательских) токенов, по крайней мере те же пользовательские токены могут быть соответствующим образом аннотированы для облегчения решения проблемы во время последующих обходов дерева.

...