解析字符串时如何处理 Antlr 空格
How to handle Antlr whitespace when parsing a string
我有一个需要解析的字符串,它对于正则表达式来说太重了。正则表达式不太擅长找到平衡的匹配项......不过这个任务相当简单,因为每个字符串可以包含三种类型的信息:
- 函数
- 变量
- 任意文本
我需要插入字符串,以便我可以用我的程序生成的内容替换变量和函数,但要保留任意文本(包括空格)。
我发现这是学习 ANTLR 的绝佳机会,但我正在努力让它发挥作用。
我基本上在三件事上遇到问题:
- 我需要保留空格,因为任意文本都不会丢失。
- 我希望函数中的参数不关心空格
- 我不确定如何匹配任意文本。我尝试了几种不同的选择,但 none 对我有用。包括例如
.+
、.+?
、~[$<]
.
几个测试字符串:
"The length of the COMPUTER environment variable is $Length(<Env:COMPUTER>)"
"The last 10 chars of the COMPUTER environment is $Substring($Length(<Env:COMPUTER>)-10, $Length(<Env:COMPUTER>))"
到目前为止,这是我的代码:
grammar Output;
start
: (expr)* ;
expr
: expr expr
| VAR
| FUNC '(' commaexpr ')'
;
commaexpr
: expr
| commaexpr ',' commaexpr
;
FUNC: '$' ID ;
VAR : '<' ID '>' ;
fragment ID : [a-zA-Z] | [a-zA-Z][a-zA-Z0-9:]+ ;
WS : [\r\n]+ -> skip ;
编辑:
我已经能够在这方面取得一些进展。好像我有一个解决方案,有点。不确定我的解决方案是否是最佳选择:
grammar Output;
start
: (expr)* ;
expr
: expr expr
| variable
| function
| text
;
variable
: VAR
;
function
: FUNC '(' commaexpr ')'
;
commaexpr
: WS? expr WS?
| commaexpr ',' commaexpr
;
text: TEXT+ ;
FUNC: '$' ID ;
VAR : '<' ID '>' ;
fragment ID : [a-zA-Z] | [a-zA-Z][a-zA-Z0-9:]+ ;
TEXT: .+?;
NL : [\r\n]+ -> skip ;
WS: [ ]+ ;
这样做有什么陷阱吗?我看到 text
表达式是一个字符列表而不是字符串,但这对我有用,因为我可以在访问者中对它们使用 GetText() 来获取实际数据。
结果
我选择了 的变体。
最终代码,ANTLR 代码以及与此相关的访问者在这里:https://github.com/IntelliSearch/FlexVersion/tree/master/IntelliSearch.FlexVersion.OutputParser
还有这里的 OutputVisitor:https://github.com/IntelliSearch/FlexVersion/blob/master/IntelliSearch.FlexVersion/OutputVisitor.cs
以防 link 在一个阶段死亡,这里是 ANTLR g4 文件:
grammar Output;
start
: expr* EOF
;
expr
: function
| variable
| text
;
function
: FUNC '(' params ')';
variable
: VAR;
params
: expr+ ( ',' expr+ )*
;
text
: OTHER+
;
FUNC : '$' ID;
VAR : '<' ID '>';
OPEN_PAR : '(';
CLOSE_PAR : ')';
COMMA : ',';
OTHER : . ;
fragment ID : [a-zA-Z] [a-zA-Z0-9:]* ;
如您所见,我也放弃了运算符 (++-/*),因为这只应该在参数中允许,但后来我不确定这是否真的明智,所以改为我采用了一种方法,该方法也可以通过特定的 $functions 解决。
在词法分析器中,.+?
将始终使用单个字符,因此请注意删除 +?
部分。
我有这样的想法:
grammar Output;
start
: expr* EOF
;
expr
: FUNC '(' params ')'
| expr ( MULT | DIV ) expr
| expr ( PLUS | MINUS ) expr
| VAR
| ignore
;
params
: expr+ ( ',' expr+ )*
;
ignore
: OTHER+
;
FUNC : '$' ID;
VAR : '<' ID '>';
OPEN_PAR : '(';
CLOSE_PAR : ')';
MULT : '*';
DIV : '/';
MINUS : '-';
PLUS : '+';
OTHER : . ;
fragment ID : [a-zA-Z] [a-zA-Z0-9:]* ;
我刚刚看到了您自己的解决方案,但如果它按您希望的方式工作,那很好。
我有一个需要解析的字符串,它对于正则表达式来说太重了。正则表达式不太擅长找到平衡的匹配项......不过这个任务相当简单,因为每个字符串可以包含三种类型的信息:
- 函数
- 变量
- 任意文本
我需要插入字符串,以便我可以用我的程序生成的内容替换变量和函数,但要保留任意文本(包括空格)。
我发现这是学习 ANTLR 的绝佳机会,但我正在努力让它发挥作用。
我基本上在三件事上遇到问题:
- 我需要保留空格,因为任意文本都不会丢失。
- 我希望函数中的参数不关心空格
- 我不确定如何匹配任意文本。我尝试了几种不同的选择,但 none 对我有用。包括例如
.+
、.+?
、~[$<]
.
几个测试字符串:
"The length of the COMPUTER environment variable is $Length(<Env:COMPUTER>)"
"The last 10 chars of the COMPUTER environment is $Substring($Length(<Env:COMPUTER>)-10, $Length(<Env:COMPUTER>))"
到目前为止,这是我的代码:
grammar Output;
start
: (expr)* ;
expr
: expr expr
| VAR
| FUNC '(' commaexpr ')'
;
commaexpr
: expr
| commaexpr ',' commaexpr
;
FUNC: '$' ID ;
VAR : '<' ID '>' ;
fragment ID : [a-zA-Z] | [a-zA-Z][a-zA-Z0-9:]+ ;
WS : [\r\n]+ -> skip ;
编辑:
我已经能够在这方面取得一些进展。好像我有一个解决方案,有点。不确定我的解决方案是否是最佳选择:
grammar Output;
start
: (expr)* ;
expr
: expr expr
| variable
| function
| text
;
variable
: VAR
;
function
: FUNC '(' commaexpr ')'
;
commaexpr
: WS? expr WS?
| commaexpr ',' commaexpr
;
text: TEXT+ ;
FUNC: '$' ID ;
VAR : '<' ID '>' ;
fragment ID : [a-zA-Z] | [a-zA-Z][a-zA-Z0-9:]+ ;
TEXT: .+?;
NL : [\r\n]+ -> skip ;
WS: [ ]+ ;
这样做有什么陷阱吗?我看到 text
表达式是一个字符列表而不是字符串,但这对我有用,因为我可以在访问者中对它们使用 GetText() 来获取实际数据。
结果
我选择了
最终代码,ANTLR 代码以及与此相关的访问者在这里:https://github.com/IntelliSearch/FlexVersion/tree/master/IntelliSearch.FlexVersion.OutputParser
还有这里的 OutputVisitor:https://github.com/IntelliSearch/FlexVersion/blob/master/IntelliSearch.FlexVersion/OutputVisitor.cs
以防 link 在一个阶段死亡,这里是 ANTLR g4 文件:
grammar Output;
start
: expr* EOF
;
expr
: function
| variable
| text
;
function
: FUNC '(' params ')';
variable
: VAR;
params
: expr+ ( ',' expr+ )*
;
text
: OTHER+
;
FUNC : '$' ID;
VAR : '<' ID '>';
OPEN_PAR : '(';
CLOSE_PAR : ')';
COMMA : ',';
OTHER : . ;
fragment ID : [a-zA-Z] [a-zA-Z0-9:]* ;
如您所见,我也放弃了运算符 (++-/*),因为这只应该在参数中允许,但后来我不确定这是否真的明智,所以改为我采用了一种方法,该方法也可以通过特定的 $functions 解决。
在词法分析器中,.+?
将始终使用单个字符,因此请注意删除 +?
部分。
我有这样的想法:
grammar Output;
start
: expr* EOF
;
expr
: FUNC '(' params ')'
| expr ( MULT | DIV ) expr
| expr ( PLUS | MINUS ) expr
| VAR
| ignore
;
params
: expr+ ( ',' expr+ )*
;
ignore
: OTHER+
;
FUNC : '$' ID;
VAR : '<' ID '>';
OPEN_PAR : '(';
CLOSE_PAR : ')';
MULT : '*';
DIV : '/';
MINUS : '-';
PLUS : '+';
OTHER : . ;
fragment ID : [a-zA-Z] [a-zA-Z0-9:]* ;
我刚刚看到了您自己的解决方案,但如果它按您希望的方式工作,那很好。