问题描述
这是我的词法分析器规则的开始:
F_TEXT_START
: {! matchingFText}? 'f"' {matchingFText = true;}
;
F_TEXT_PH_ESCAPE
: {matchingFText && ! matchingFTextPh}? '{=/'
;
F_TEXT_PH_START
: {matchingFText && ! matchingFTextPh}? '{=' {matchingFTextPh = true;}
;
F_TEXT_PH_END
: {matchingFText && matchingFTextPh}? '}' {matchingFTextPh = false;}
;
F_TEXT_CHAR
: {matchingFText && ! matchingFTextPh}? (~('"' | '{')+ | '""' | '{' ~'=')
;
F_TEXT_END
: {matchingFText && ! matchingFTextPh}? '"' {matchingFText = false;}
;
IF
: {! matchingFText || matchingFTextPh}? 'if'
;
ELIF
: {! matchingFText || matchingFTextPh}? 'elif'
;
// Lots of other keywords
fragment LETTER
: ('A' .. 'Z' | 'a' .. 'z' | '_')
;
VARIABLE
: {! matchingFText || matchingFTextPh}? LETTER (LETTER | DIGIT)*
;
我正在做的是将格式化后的文本不仅像普通文本标记一样放置,而且之前加上a,但我将其添加到解析树中,以便能够分辨解析时是否有错误(仅{{1 }}。因此,格式化的文本以parser.start()
开头,以f"
结尾,任何"
必须替换为"
,并且可以包含以""
开头并以结尾结尾的占位符与{=
一起使用,但是如果您想实际编写}
,则必须将其替换为{=
。
问题在于,在普通格式的文本内容(而不是占位符)中,词法分析器不仅开始处理{=/
,而且还开始处理其他词法分析器规则,例如变量。我所做的工作似乎很愚蠢,我只是将语义谓词用于其他所有规则,以避免它们在格式化文本的内容中(但仍在占位符中)匹配。
没有更好的方法吗?
解决方法
为此,我将使用词汇模式。要使用词法模式,您必须定义单独的词法分析器和解析器语法。这是一个快速演示:
lexer grammar TestLexer;
F_TEXT_START
: 'f"' -> pushMode(F_TEXT)
;
VARIABLE
: LETTER (LETTER | DIGIT)*
;
F_TEXT_PH_ESCAPE
: '{=/'
;
F_TEXT_PH_END
: '}' -> popMode
;
SPACES
: [ \t\r\n]+ -> skip
;
fragment LETTER
: [a-zA-Z_]
;
fragment DIGIT
: [0-9]
;
mode F_TEXT;
F_TEXT_CHAR
: ~["{]+ | '""' | '{' ~'='
;
F_TEXT_PH_START
: '{=' -> pushMode(DEFAULT_MODE)
;
F_TEXT_END
: '"' -> popMode
;
像这样在解析器中使用词法分析器:
parser grammar TestParser;
options {
tokenVocab=TestLexer;
}
// ...
如果您现在对输入f"mu {=mu}" mu
进行标记,则将获得以下标记:
F_TEXT_START `f"`
F_TEXT_CHAR `mu `
F_TEXT_PH_START `{=`
VARIABLE `mu`
F_TEXT_PH_END `}`
F_TEXT_END `"`
VARIABLE `mu`