IntelliJ: Grammar-Kit/BNF: как исправить ошибки?

Я пишу плагин Custom Language для IntelliJ.

Вот упрощенный пример языка. Обратите внимание, что структура является рекурсивной:

введите здесь описание изображения

Я успешно реализовал файлы FLEX и BNF, но не знаю, как добавить восстановление после ошибок. Я читал о RecoverWhile и pin в HOWTO Grammar-Kit, но я не уверен, как применить их к моему сценарию.

Я называю коричневые элементы выше ("aaa", "ccc" и т. д.) "элементы".

Я называю желтые ("bbb", "ddd", ...) "свойствами".

Каждый элемент имеет имя элемента (например, "aaa"), одно свойство (например, "bbb") и может содержать другие элементы (например, "aaa" содержит "ccc ", "ээээ" и "гг").

На данный момент плагин плохо себя ведет, когда элемент имеет неверный формат. Например:

введите здесь описание изображения

В этом примере я хотел бы, чтобы синтаксический анализатор «понимал», что «ccc» — это имя элемента с отсутствующим свойством (например, путем обнаружения новой строки перед закрывающей скобкой).

Я не хочу, чтобы сломанный элемент "ccc" влиял на синтаксический анализ "eeee" (но я хочу, чтобы PSI-дерево имело элементы "ccc", присутствующие в тексте, в в этом случае - его имя).

Вот FLEX и BNF, которые я использую:

ФЛЕКС:

CRLF= \n|\r|\r\n
WS=[\ \t\f]
WORD=[a-zA-Z0-9_#\-]+

%state EOF

%%
<YYINITIAL>    {WORD} { yybegin(YYINITIAL); return MyLangTypes.TYPE_FLEX_WORD; }
<YYINITIAL>    \[     { yybegin(YYINITIAL); return MyLangTypes.TYPE_FLEX_OPEN_SQUARE_BRACKET; }
<YYINITIAL>    \]     { yybegin(YYINITIAL); return MyLangTypes.TYPE_FLEX_CLOSE_SQUARE_BRACKET; }
<YYINITIAL>    \{     { yybegin(YYINITIAL); return MyLangTypes.TYPE_FLEX_OPEN_CURLY_BRACKET; }
<YYINITIAL>    \}     { yybegin(YYINITIAL); return MyLangTypes.TYPE_FLEX_CLOSE_CURLY_BRACKET; }
({CRLF}|{WS})+        { return TokenType.WHITE_SPACE; }
{WS}+                 { return TokenType.WHITE_SPACE; }
.                     { return TokenType.BAD_CHARACTER; }

БНФ:

myLangFile ::= (item|COMMENT|CRLF)
item ::=
    itemName
    (TYPE_FLEX_OPEN_SQUARE_BRACKET itemProperty? TYPE_FLEX_CLOSE_SQUARE_BRACKET?)?
    itemBody?
itemName ::= TYPE_FLEX_WORD
itemProperty ::= TYPE_FLEX_WORD
itemBody ::= TYPE_FLEX_OPEN_CURLY_BRACKET item* TYPE_FLEX_CLOSE_CURLY_BRACKET

person obe    schedule 05.03.2016    source источник
comment
Вы нашли ответ?   -  person Irina Rapoport    schedule 27.10.2016
comment
@IrinaRapoport вроде ... Я смог обойти это. Я не помню всех подробностей, так как это было давно, но я опубликовал ответ, основанный на окончательном коде, который у меня есть сейчас... надеюсь, это поможет!   -  person obe    schedule 28.10.2016


Ответы (1)


В конце концов я смог заставить его работать так:

myLangFile ::= (item|COMMENT|CRLF)
item ::=
    itemName
    itemProperties
    itemBody?
itemName ::= TYPE_FLEX_WORD
itemProperties ::= TYPE_FLEX_OPEN_SQUARE_BRACKET [!TYPE_FLEX_CLOSE_SQUARE_BRACKET itemProperty ((TYPE_FLEX_SEMICOLON itemProperty)|itemProperty)*] TYPE_FLEX_CLOSE_SQUARE_BRACKET {
    pin(".*") = 1
}
itemProperty ::= TYPE_FLEX_WORD TYPE_FLEX_EQUALS? itemPropertyValue? (TYPE_FLEX_EQUALS prv_swallowNextPropertyToPreventSyntaxErrors)?
private prv_swallowNextPropertyToPreventSyntaxErrors ::= TYPE_FLEX_WORD
itemPropertyValue ::= TYPE_FLEX_WORD
itemBody ::= TYPE_FLEX_OPEN_CURLY_BRACKET item* TYPE_FLEX_CLOSE_CURLY_BRACKET

Это не идеально; например, он позволяет разделять свойства элементов пробелом (а не только точкой с запятой), но, похоже, решает более важную проблему.

Это также может представлять интерес: https://github.com/JetBrains/Grammar-Kit/blob/master/resources/messages/attributeDescriptions/recoverWhile.html

person obe    schedule 28.10.2016