2

我是 ANTLR 的初学者,我需要修改现有的复杂语法。

我想创建一个规则来保留一个块而不用其他规则解析。为了更清楚,我需要将用 c++ 编写的代码插入到解释代码中。


编辑 2013 年 11 月 2 日

经过多次测试,这是我的语法,我的测试,我得到的结果,以及结果和想要的:

语法

cppLiteral
    : cppBegin cppInnerTerm cppEnd
    ;
cppBegin
    :  '//$CPP_IN$'
    ;
cppEnd
    : '//$CPP_OUT$'
    ;
cppInnerTerm
    : ( ~('//$CPP_OUT$') )*
    ;

测试

//$CPP_IN$
txt1 txt2
//$CPP_OUT$

结果

cppLiteral ->
cppBegin = '//$CPP_IN$'
cppInnerTerm = 'txt1' 'txt2'
cppEnd = '//$CPP_OUT$'

预期结果

cppLiteral ->
cppBegin = '//$CPP_IN$'
cppInnerTerm = 'txt1 txt2'
cppEnd = '//$CPP_OUT$'

(对不起,我不能发布AST的图像,因为我没有10个声望)

“cppBegin”、“cppInnerTerm”和“cppEnd”这三个标记可以在一个标记中,如下所示:

cppLiteral
    : '//$CPP_IN$'( ~('//$CPP_OUT$') )*'//$CPP_OUT$'
    ;

得到这个结果:

cppLiteral = '//$CPP_IN$\n txt1 txt2\n //$CPP_OUT$'
4

1 回答 1

0

我想创建一个规则来保留一个块而不用其他规则解析。

像多行注释一样解析它,例如/* foobar */. 下面是一个使用您问题中指定的关键字的小示例。

请注意,大部分工作都是使用词法分析器规则(以大写字母开头的规则)完成的。任何时候你想处理文本块,特别是如果你想避免像这种情况下的其他规则,你可能会考虑词法分析器规则而不是解析器规则。

CppBlock.g

grammar CppBlock;

document: CPP_LITERAL* EOF;


fragment CPP_IN:'//$CPP_IN$';
fragment CPP_OUT:'//$CPP_OUT$';
 
CPP_LITERAL:  CPP_IN .* CPP_OUT
            {
                String t = getText(); 
                t = t.substring(10, t.length() - 11); //10 = length of CPP_IN, 11 = length of CPP_OUT
                setText(t);
            }
            ;
WS: (' '|'\t'|'\f'|'\r'|'\n')+ {skip();};

这是一个简单的测试用例:

输入

//$CPP_IN$
static const int x = 0; //magic number
int *y; //$CPP_IN$ <-- junk comment
static void foo(); //forward decl...
//$CPP_OUT$

//$CPP_IN$
//Here is another block of CPP code...
const char* msg = ":D";
//The end.
//$CPP_OUT$

输出令牌

[CPP_LITERAL : 
static const int x = 0; //magic number
int *y; //$CPP_IN$ <-- junk comment
static void foo(); //forward decl...
]
[CPP_LITERAL : 
//Here is another block of CPP code...
const char* msg = ":D";
//The end.
] 

规则CPP_LITERAL在输入的开头和结尾(之后//$CPP_IN$和之前//$CPP_OUT$)保留换行符。如果您不想要这些,只需更新操作以将它们删除。否则,我认为这种语法可以满足您的要求。

于 2013-02-12T04:14:41.320 回答