【问题标题】:IntelliJ: Grammar-Kit / BNF: how to recover from errors?IntelliJ:Grammar-Kit / BNF:如何从错误中恢复?
【发布时间】:2016-06-19 15:03:57
【问题描述】:

我正在为 IntelliJ 编写自定义语言插件。

这是该语言的简化示例。注意结构是递归的:

我已经成功实现了 FLEX 和 BNF 文件,但我不确定如何添加错误恢复。我在 Grammar-Kit 的 HOWTO 中阅读了有关 RecoverWhilepin 的内容,但我不确定如何将它们应用到我的场景中。

我将上面的棕色项目(“aaa”、“ccc”等)称为“items”。

我称黄色的(“bbb”、“ddd”、...)为“properties”。

每个项目都有一个项目名称(例如“aaa”)、单个属性(例如“bbb”),并且可以包含其他项目(例如“aaa”包含“ccc”、“eeee”和“gg”)。

目前,当项目格式错误时,插件表现不佳。例如:

在本例中,我希望解析器“理解”“ccc”是具有缺失属性的 item 的名称(例如,通过检测右括号前的换行符)。

我不希望损坏的“ccc”item 影响“eeee”的解析(但我确实希望 PSI 树具有存在于文本,在这种情况下 - 它的名称)。

这是我使用的 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; }

BNF:

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

【问题讨论】:

  • 你找到答案了吗?
  • @IrinaRapoport 有点……我能够绕过它。我不记得所有的细节,因为它已经有一段时间了,但我根据我现在拥有的最终代码发布了一个答案......希望它有所帮助!

标签: parsing intellij-idea bnf intellij-plugin grammar-kit


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-27
    • 2017-03-19
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2023-03-03
    • 2015-02-17
    相关资源
    最近更新 更多