在解析器中使用 ANTLR4 标记之前先对其进行过滤

问题描述 投票:0回答:1

我正在尝试建立一种语法,忽略未定义的 #if 语句中的任何文本,例如该字符串中的标记

#if UNDEFINED
  bla bla
#endif
Real Code here

在传递给解析器之前应转换为以下内容

#if UNDEFINED
#endif
Real Code here

我的想法是在 CommonTokenStream 生成 IToken 实例后手动清除它们。这对我来说效果很好。不过,我试图找出将 IToken 实例的过滤列表传递给解析器的最佳方法。我最初是在看 TokenStreamRewriter 但这个家伙似乎没有做我正在寻找的事情。

注意:我不能使用解析器来完成这项工作,因为解析器不喜欢非法的未定义内容。

现在我正在考虑在手动设置 tokens 字段并将此实例传递给解析器时创建 CommonTokenStream 子类型。但我不确定这是否是最好的方法。

c# antlr antlr4 antlr4cs
1个回答
0
投票

这是一个示例,可能不足以满足您的目的,因此我将尝试解释。

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 文本,就可以工作。

© www.soinside.com 2019 - 2024. All rights reserved.