将单个 senerio 与 ANTLR 匹配并跳过其他所有内容作为噪音
Match a single senerio with ANTLR and skip everything else as noise
我使用 ANTLR V4 Eclipse 插件定义了一个简单的语法。我想解析一个包含 Coldfusion cfscript 代码的文件,并找到 属性 定义的每个实例。例如:
property name="productTypeID" ormtype="string" length="32" fieldtype="id" generator="uuid" unsavedvalue="" default="";
即 属性 关键字后跟任意数量的属性,行以分号结束。
.g4 文件
grammar CFProperty;
property : 'property ' (ATR'='STRING)+EOL; // match keyword property followed by an attribute definition
ATR : [a-zA-Z]+; // match lower and upper-case identifiers name
STRING: '"' .*? '"'; // match any string
WS : [ \t\r\n]+ -> skip; // skip spaces, tabs, newlines
EOL : ';'; // end of the property line
我整理了一个简单的 java 项目,该项目使用生成的解析器、tree-walker 等打印出这些匹配项的出现。
我正在测试的输入是:
"property id=\"actionID\" name=\"actionName\" attr=\"actionAttr\" hbMethod=\"HBMethod\"; public function some funtion {//some text} property name=\"actionID\" name=\"actionName\" attr=\"actionAttr\" hbMethod=\"HBMethod\"; \n more noise "
我的问题是这只匹配:
property id="actionID" name="actionName" attr="actionAttr" hbMethod="HBMethod";
而且因为它不理解其他任何东西都是噪音,所以它不符合 属性 定义的第二个实例。
如何匹配 属性 定义的多个实例并匹配中间的所有其他内容作为要跳过的噪声?
你可以使用词法分析器模式来做你想做的事。 属性 和东西的一种模式和噪声的一种模式。模式背后的想法是从一种模式(一种状态)转到我们在词法分析操作期间发现的另一个后续标记。
为此,您必须将语法分成两个文件,一个文件中的解析器和另一个文件中的词法分析器。
这是词法分析器部分(在我的例子中命名为 TestLexer.g4
)
lexer grammar TestLexer;
// Normal mode
PROPERTY : 'property';
EQUALS : '=';
ATR : [a-zA-Z]+; // match lower and upper-case identifiers name
STRING: '"' .*? '"'; // match any string
WS : [ \t\r\n]+ -> skip; // skip spaces, tabs, newlines
EOL : ';' -> pushMode(NOISE); // when ';' is found, go to noise mode where everything is skip
mode NOISE;
NOISE_PROPERTY : 'property' -> type(PROPERTY), popMode; // when 'property' is found, we say it's a PROPERTY token and we go back to normal mode
ALL : .+? -> skip; // skip all other stuffs
这是解析器部分(在我的例子中命名为 Test.g4
)
grammar Test;
options { tokenVocab=TestLexer; }
root : property+;
property : PROPERTY (ATR EQUALS STRING)+ EOL; // match keyword property followed by an attribute definition
这应该可以完成工作:)
我使用 ANTLR V4 Eclipse 插件定义了一个简单的语法。我想解析一个包含 Coldfusion cfscript 代码的文件,并找到 属性 定义的每个实例。例如:
property name="productTypeID" ormtype="string" length="32" fieldtype="id" generator="uuid" unsavedvalue="" default="";
即 属性 关键字后跟任意数量的属性,行以分号结束。
.g4 文件
grammar CFProperty;
property : 'property ' (ATR'='STRING)+EOL; // match keyword property followed by an attribute definition
ATR : [a-zA-Z]+; // match lower and upper-case identifiers name
STRING: '"' .*? '"'; // match any string
WS : [ \t\r\n]+ -> skip; // skip spaces, tabs, newlines
EOL : ';'; // end of the property line
我整理了一个简单的 java 项目,该项目使用生成的解析器、tree-walker 等打印出这些匹配项的出现。
我正在测试的输入是:
"property id=\"actionID\" name=\"actionName\" attr=\"actionAttr\" hbMethod=\"HBMethod\"; public function some funtion {//some text} property name=\"actionID\" name=\"actionName\" attr=\"actionAttr\" hbMethod=\"HBMethod\"; \n more noise "
我的问题是这只匹配:
property id="actionID" name="actionName" attr="actionAttr" hbMethod="HBMethod";
而且因为它不理解其他任何东西都是噪音,所以它不符合 属性 定义的第二个实例。
如何匹配 属性 定义的多个实例并匹配中间的所有其他内容作为要跳过的噪声?
你可以使用词法分析器模式来做你想做的事。 属性 和东西的一种模式和噪声的一种模式。模式背后的想法是从一种模式(一种状态)转到我们在词法分析操作期间发现的另一个后续标记。
为此,您必须将语法分成两个文件,一个文件中的解析器和另一个文件中的词法分析器。
这是词法分析器部分(在我的例子中命名为 TestLexer.g4
)
lexer grammar TestLexer;
// Normal mode
PROPERTY : 'property';
EQUALS : '=';
ATR : [a-zA-Z]+; // match lower and upper-case identifiers name
STRING: '"' .*? '"'; // match any string
WS : [ \t\r\n]+ -> skip; // skip spaces, tabs, newlines
EOL : ';' -> pushMode(NOISE); // when ';' is found, go to noise mode where everything is skip
mode NOISE;
NOISE_PROPERTY : 'property' -> type(PROPERTY), popMode; // when 'property' is found, we say it's a PROPERTY token and we go back to normal mode
ALL : .+? -> skip; // skip all other stuffs
这是解析器部分(在我的例子中命名为 Test.g4
)
grammar Test;
options { tokenVocab=TestLexer; }
root : property+;
property : PROPERTY (ATR EQUALS STRING)+ EOL; // match keyword property followed by an attribute definition
这应该可以完成工作:)