我正在为IntelliJ编写自定义语言插件。
以下是该语言的简化示例。请注意,结构是递归的:
我已成功实施了FLEX和BNF文件,但我不确定如何添加错误恢复。我已经在Grammar-Kit的HOWTO中了解了 RecoverWhile 和 pin ,但我不确定如何将它们应用到我的场景中。
我打电话给上面的棕色物品(" aaa"," ccc"等等......)" 物品"。
我称之为黄色(" bbb"," ddd",...)" 属性"。
每个项目都有一个项目名称(例如" aaa"),一个属性(例如" bbb"),并且可以包含其他项目(例如" aaa"包含" ccc"," eeee"和" gg")。
目前,当项目格式错误时,插件不会表现良好。例如:
在这个例子中,我希望解析器能够理解"那" ccc"是具有缺失属性的项的名称(例如,通过在结束括号之前检测换行符)。
我不想要破碎的" ccc" item 影响解析" eeee" (但我确实希望PSI树具有" ccc"的元素,这些元素存在于文本中,在本例中为其名称)。
以下是我使用的FLEX和BNF:
FLEX:
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
答案 0 :(得分:0)
我最终能够让它像这样工作:
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
它并不完美;例如,它允许用空格分隔项属性(而不仅仅是用分号),但它似乎解决了更重要的问题。