2014-06-12 21 views
0

我正在为包含特殊预处理器部分中的预处理器指令的语言(由{}包含)构建解析器。其中之一与C#define类似。如何在两个单独的词法分析模式中使用词法分析器规则?

我想在一次运行中使用针对预处理器部件的孤岛语法来分析文件。 当我点击#define指令时,我想包含另一个孤岛语法,其中包含“常规”部分的所有标记(大约200个),除了预处理区域开始标记并在不同通道上发出标记以及当然有一个停止令牌返回到预处理器岛语法。由于我解析的文件是有效的,所以预处理器区域起始令牌{真的被删除并不是非常重要,但会很好。

有没有办法为两种模式“重复使用”词法分析器规则(我可以发射到命名的非const通道,该值可以在进入/离开岛时改变)?

这是一些示例源文件:

int a = 42; 

{ // start preprocessor section 

// simple single line #define 
#define ABC 42 

// will be fix "2 * 42" even if ABS is changed later on 
#define DEF 2 * ABC 

// multiple line define (all but last line needs to have a "\" before the newline 
#define GHI 3 \ 
       + 4 

// the definition can contain (almost) arbitrary code, except line comments, preprocessor sections and preprocessor statements 
#define JKL if (a > 23) then b = c + d; str = "} <- this must not be the end of the preprocessor section"; end_if;    

} // end preprocessor section 

回答

1

您当前无法重用/导入在一个模式定义为另一个词法规则。我通常做类似以下的事情。

LBRACE : '{'; 

mode OtherMode; 

    OtherMode_LBRACE : LBRACE -> type(LBRACE); 

由于在ANTLR 4工具代码生成优化,构建像上面也不会真正创造一个单独的OtherMode_LBRACE令牌由于该规则使用type词法分析器的命令。

+0

这就是我对“少数”规则的做法。 200条规则的做法是什么? – Onur

+0

@Onur以这种形式创建原始规则的200份副本。 –

+0

我采取了你的方法,虽然我不手动做样板代码(请参阅我的答案)。 – Onur

0

我终于采取了方法来简单地复制Sam提出的规则。我首先尝试从另一种模式返回到主模式,并在某个位置检查是否要使用嵌入式操作返回,并使用设置“当前活动频道”的操作并将其添加到所有规则中,但这会混淆所有规则并没有“感觉到正确的事情”。

减少人工工作,我改组我的词法分析文件,现在可以很容易地复制到被包含在其他模式的规则和使用正则表达式的其他模式部分改造它们,将它们插入:

搜索:

^\s*(([a-z_0-9]+)[ \t\n]*)(:.*?;)\n 

与替换(PPP_只是一个前缀我选择):

PPP_$1 : $2 -> type\($2\), channel\(2\); \n\t\t\t/*$3*/\n 

和使用正则EXP激活选项“忽略大小写”,“单行”,“多行”

如果您不想将令牌发送到另一个通道,请删除channel(2)部件。 我选择的编辑(记事本+ +)需要我脱离大括号,你的可能不会。