Parsing 在antlr4语法中实现标记文本样式运算符时,如何首先进行最短匹配?
我在互联网上找到了以下(简化的)语法,当时我正在寻找一种解决方案,解决了一个必须解析类似Markdown的语法的问题Parsing 在antlr4语法中实现标记文本样式运算符时,如何首先进行最短匹配?,parsing,antlr,antlr4,ll,Parsing,Antlr,Antlr4,Ll,我在互联网上找到了以下(简化的)语法,当时我正在寻找一种解决方案,解决了一个必须解析类似Markdown的语法的问题 grammar Markdown; parse : stat+; stat : bold | text | WS ; text : TEXT|SPACE; bold : ('**'stat*'**'); TEXT : [a-zA-Z0-9]+; SPACE :
grammar Markdown;
parse : stat+;
stat : bold
| text
| WS
;
text : TEXT|SPACE;
bold : ('**'stat*'**');
TEXT : [a-zA-Z0-9]+;
SPACE : ' ';
WS : [\t\r\n]+;
我想要实现的是,antlr4首先对一个看起来像**bold1**not bold**bold2**
的句子进行最短匹配。
这意味着bold1
将是粗体的不粗体的
不,并且bold2
再次粗体
但是,由于antlr4首先使用最长匹配,antlr4将示例解析为两个嵌套的粗体,这是错误的
对于这个问题,我已经考虑过很多非常复杂的解决方案,但实际上我并不想使用。
有简单的解决办法吗
更新:
显然我把这个例子简化得太多了。
现在这里有一个扩展语法(不再识别标记),但它说明了我的问题。
需要注意的是,stat
也可以是一个变量
,它只是我的语言可能包含的任何关键字的占位符
grammar StyleParser;
parse : styled_stat+;
styled_stat : italic
| bold
| underline
| stat
;
stat : variable
| text
;
variable: VARIABLE;
text : TEXT|SPACE;
italic : ITALIC (stat | italic_bold | italic_underline)* ITALIC;
italic_bold: BOLD (stat | italic_bold_underline)* BOLD;
italic_bold_underline: UNDERLINE stat* UNDERLINE;
italic_underline: UNDERLINE (stat | italic_underline_bold)* UNDERLINE;
italic_underline_bold: BOLD stat* BOLD;
bold : BOLD (stat | bold_italic | bold_underline)* BOLD;
bold_italic: ITALIC (stat | bold_italic_underline)* ITALIC;
bold_italic_underline: UNDERLINE stat* UNDERLINE;
bold_underline: UNDERLINE (stat | bold_underline_italic)* UNDERLINE;
bold_underline_italic: ITALIC stat* ITALIC;
underline : UNDERLINE (stat | underline_bold | underline_italic)* UNDERLINE;
underline_italic: ITALIC (stat | underline_italic_bold)* ITALIC;
underline_italic_bold: BOLD stat* BOLD;
underline_bold: BOLD (stat | underline_bold_italic)* BOLD;
underline_bold_italic: ITALIC stat* ITALIC;
SPACE : ' ';
VARIABLE : 'VAR';
TEXT : [a-zA-Z0-9]+;
ITALIC: '//';
BOLD: '==';
UNDERLINE: '__';
使用这种语法,我不能嵌套相同的样式,但我可以嵌套不同的样式。例如,它正确地解析==bold1\u下划线//斜体//\u下划线==非
。
问题是规则的数量随着您引入的样式的数量呈指数增长,我想避免这种情况。解析标记非常重要。一种方法是
WORD
(定义为不包含限定属性的文本字符串)的一般情况,解析器定义为
word
: attrLeft*
w=( WORD | ENTITY | UNICODE
| URL | URLTAG | SPAN | HTML
)
attrRight*
;
attrLeft : LBOLD | LITALIC | LSTRIKE | LDQUOTE | LSQUOTE ;
attrRight : RBOLD | RITALIC | RSTRIKE | RDQUOTE | RSQUOTE ;
在lexer中,将所有属性定义为默认的left
,并为right
属性和WORD
tokens {
WORD,
RBOLD,
RITALIC,
RSTRIKE,
RDQUOTE,
RSQUOTE
}
// attributes
LBOLD : Bold ;
LITALIC : Italic ;
LSTRIKE : Strike ;
LDQUOTE : Quote ;
LSQUOTE : Mark ;
...
// last line in the lexer
CHAR : EscChar | . ;
在lexer超类中,覆盖
public void emit(Token t) {...}
并决定是否
任何特定的左
属性实际上都应该重新指定为右
属性
CHAR
应累积到当前的WORD
中,或应添加到新的WORD
实例中
现在,树漫游者可以评估word
s的序列,并处理潜在的多个重叠嵌套属性的处理。为什么要区分SPACE
和WS
?无论如何,你的问题是你的语法没有反映出粗体部分不能相互嵌套的事实。因此,bold
规则不应该与stat
相互递归。很抱歉造成混淆。我过分简化了这个例子。请再看看我的更新。