Dan*_*use 3 java antlr3 antlr4
ANTLR 适合这个项目吗?
\n\n我正在寻找处理和转换用户输入的字符串,其中可能包含自定义函数。例如,用户可能会在字符串中写入类似 $CAPITALIZE('word') 的内容,而我想使用 StringUtils 在后台执行\n实际转换。
\n\n我想用户有时会编写嵌套函数,例如:
\n\n$RIGHT_PAD($RIGHT($CAPITALIZE('a123456789'),6),3,'0')
\n\n其中预期输出为字符串值“A12345000”。
\n\n我尝试使用正则表达式将函数分开,但一旦嵌套,就不那么容易了。我想我可以尝试编写自己的解析器,在进行研究时我发现了一篇建议使用 ANTLR 的文章。
\n\nANTLR 适合这样做吗?如果是这样,是否有任何类似的示例可供我查看?或者有人可以给我一个例子,说明如何在 ANTLR 中编写此代码,以便我可以拥有可以单独处理和以嵌套方式处理的自定义函数。
\n\n功能:
\n\n基本示例:
\n\n嵌套示例
\n\n实际示例: \n我所说的实际示例的意思是,这就是我期望的字符串值的样子。你会注意到有一些变量的写法类似于${var}。在将字符串传递到 ANTLR 之前,这些变量将使用 Apache Commons StringSubstitutor 替换为实际字符串值(如果结果证明我应该使用它)
\n\n用户写入的初始字符串\n\\HomeDir\\Students\\$RIGHT(${graduation.year},2)\\$LEFT_PAD($LEFT(${state.id},6),3,'0' )
\n\nStringSubstitutor 处理后的字符串\n\\HomeDir\\Students\\$RIGHT('2020',2)\\$LEFT_PAD($LEFT('123456789',6),3,'0')
\n\n由 ANTLR 处理后的字符串 (以及我的最终输出)
\n\n\\HomeDir\\Students\\20\\000123456
\n\nANTLR 看起来像我应该用于这个项目的东西,还是其他更适合的东西?
\n是的,ANTLR将是一个不错的选择。请记住,ANTLR 仅为您进行解析,并为您提供遍历生成的解析树的机制。您必须编写代码来计算表达式。
在您的情况下,当您的词法分析器偶然发现 a 时,需要'$'通过将词法状态推为“处于功能模式”来触发。当它看到 a 时')',应该从词法堆栈中弹出一个这样的“函数模式”。
在 ANTLR wiki 上阅读有关词法模式/堆栈的所有内容:https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md
以下是 ANTLR4 的快速演示(ANTLR3 不支持词法模式):
lexer grammar TLexer;
TEXT
: ~[$]
;
FUNCTION_START
: '$' -> pushMode(IN_FUNCTION), skip
;
mode IN_FUNCTION;
FUNTION_NESTED : '$' -> pushMode(IN_FUNCTION), skip;
ID : [a-zA-Z_]+;
PAR_OPEN : '(';
PAR_CLOSE : ')' -> popMode;
NUMBER : [0-9]+;
STRING : '\'' ( ~'\'' | '\'\'' )* '\'';
COMMA : ',';
SPACE : [ \t\r\n]-> skip;
Run Code Online (Sandbox Code Playgroud)
parser grammar TParser;
options {
tokenVocab=TLexer;
}
parse
: atom* EOF
;
atom
: text
| function
;
text
: TEXT+
;
function
: ID params
;
params
: PAR_OPEN ( param ( COMMA param )* )? PAR_CLOSE
;
param
: NUMBER
| STRING
| function
;
Run Code Online (Sandbox Code Playgroud)
使用 IntelliJ 的 ANTLR4 插件,您可以轻松测试parse解析器中的方法并向其提供以下输入:foo $RIGHT_PAD($RIGHT($CAPITALIZE('a123456789'), 6), 3, '0') bar,这将生成解析树的以下图像:
| 归档时间: |
|
| 查看次数: |
1273 次 |
| 最近记录: |