我正在尝试建立一种语法,忽略未定义的 #if 语句中的任何文本,例如该字符串中的标记
#if UNDEFINED
bla bla
#endif
Real Code here
在传递给解析器之前应转换为以下内容
#if UNDEFINED
#endif
Real Code here
我的想法是在 CommonTokenStream 生成 IToken 实例后手动清除它们。这对我来说效果很好。不过,我试图找出将 IToken 实例的过滤列表传递给解析器的最佳方法。我最初是在看 TokenStreamRewriter 但这个家伙似乎没有做我正在寻找的事情。
注意:我不能使用解析器来完成这项工作,因为解析器不喜欢非法的未定义内容。
现在我正在考虑在手动设置 tokens 字段并将此实例传递给解析器时创建 CommonTokenStream 子类型。但我不确定这是否是最好的方法。
这是一个示例,可能不足以满足您的目的,因此我将尝试解释。
lexer grammar MyLexer;
channels { IGNORED }
WS
: [ \t\r\n]+
-> channel(HIDDEN)
;
OCTOTHORPE
: '#'
;
IFUNDEFINED
: OCTOTHORPE [iI] [fF] WS [uU] [nN] [dD] [eE] [fF] [iI] [nN] [eE] [dD]
-> mode(UNDEFINED_MODE)
;
mode UNDEFINED_MODE;
INTENTIONALLY_IGNORED
: .*?
->channel(IGNORED)
;
ENDIF
: OCTOTHORPE [eE] [nN] [dD] [iI] [fF]
->mode(DEFAULT_MODE)
;
一旦进入词法分析器模式,只有在那里定义的标记才会被发出。
这个例子不处理,例如...
#if UNDEFINED
blah
#if BOO
blah blah
#endif
#endif
IFUNDEFINED 规则将匹配 #if UNDEFINED 文本并切换到模式(UNDEFINED_MODE)。 在此模式下处理时,INTENTIONALLY_IGNORED 规则将匹配所有内容并将其路由到 IGNORED 通道但是非贪婪修饰符“?”将允许 ENDIF 规则匹配 #endif 文本,因此模式(DEFAULT_MODE)命令可以让我们摆脱 UNDEFINED_MODE。
遗憾的是,我给出的例子表明可能有多个#endif。
如果你可能遇到这种情况,你必须做一些更复杂的事情......
lexer grammar MyLexer;
channels { IGNORED }
WS
: [ \t\r\n]+
-> channel(HIDDEN)
;
OCTOTHORPE
: '#'
;
IFUNDEFINED
: OCTOTHORPE [iI] [fF] WS [uU] [nN] [dD] [eE] [fF] [iI] [nN] [eE] [dD]
-> pushMode(UNDEFINED_MODE)
;
mode UNDEFINED_MODE;
INTENTIONALLY_IGNORED
: .*?
->channel(IGNORED)
;
HASHIF
: OCTOTHORPE [iI] [fF] WS
-> pushMode(UNDEFINED_MODE)
;
ENDIF
: OCTOTHORPE [eE] [nN] [dD] [iI] [fF]
->popMode
;
pushMode() 命令切换到指定的模式,并将其记录在模式堆栈上。 popMode 命令切换到前一个模式并将当前模式从模式堆栈中弹出。 只要源代码中存在匹配的 #if 和 #endif 文本,就可以工作。