Java ANTLR嵌套函数

Java ANTLR嵌套函数,java,antlr4,antlr3,Java,Antlr4,Antlr3,ANTLR适合这个项目吗? 我希望处理和转换用户输入的字符串,其中可能包含自定义函数。例如,用户可能会在字符串中写入类似$CAPITALIZE('word')的内容,我希望执行此操作 使用StringUtils在后台进行的实际转换 我认为用户有时会编写嵌套函数,如: $RIGHT_PAD($RIGHT($CAPITALIZE('a123456789'),6),3,'0')) 其中,预期输出为字符串值“A1234500” 我尝试使用正则表达式将函数分开,但一旦嵌套,就不那么容易了。我想我可能会尝试

ANTLR适合这个项目吗?

我希望处理和转换用户输入的字符串,其中可能包含自定义函数。例如,用户可能会在字符串中写入类似$CAPITALIZE('word')的内容,我希望执行此操作 使用StringUtils在后台进行的实际转换

我认为用户有时会编写嵌套函数,如:

$RIGHT_PAD($RIGHT($CAPITALIZE('a123456789'),6),3,'0'))

其中,预期输出为字符串值“A1234500”

我尝试使用正则表达式将函数分开,但一旦嵌套,就不那么容易了。我想我可能会尝试编写自己的解析器,在进行研究时,我看到一篇文章建议使用ANTLR

这是ANTLR适合的吗?如果有的话,有没有类似的例子可供我参考?或者有人能给我举个例子,说明我如何在ANTLR中写出来,这样我就可以拥有两个自定义函数,它们可以单独处理,也可以嵌套处理

功能:

  • $CAPITALIZE(字符串str)
  • $INDEX_OF(字符串顺序,字符串搜索顺序)
  • $LEFT(字符串str,整数len)
  • $LEFT_PAD(字符串str、整型大小、字符padChar)
  • $LOWERCASE(字符串str)
  • $RIGHT(字符串str,整数len)
  • $RIGHT_PAD(字符串str、int size、char padChar)
  • $STRIP(字符串str)
  • $STRIP_重音符号(字符串输入)
  • $SUBSTRING(字符串str,int start)
  • $SUBSTRING(字符串str,int start,int end)
  • $TRIM(字符串str)
  • $TRUNCATE(字符串str,int-maxWidth)
  • $UPPERCASE(字符串str)
基本示例:

  • $CAPITALIZE('单词')→ '字
  • $INDEX_OF('word','r')→ 二,
  • $LEFT('0123456789',6)→ '012345'
  • $LEFT_PAD('0123456789',3',0')→ '0000123456789'
  • $LOWERCASE('单词')→ '字
  • $RIGHT('0123456789',6)→ '456789'
  • $RIGHT_PAD('0123456789',3',0')→ '0123456789000'
  • $STRIP('word')→ '字
  • $STRIP_口音(“wórd”)→ '字
  • $SUBSTRING('word',1)→ 'ord'
  • $SUBSTRING('word',0,2)→ '沃尔
  • $TRIM('word'))→ '字
  • $TRUNCATE('更多单词',3)→ '更多'
  • $UPPERCASE('单词')→ '字
嵌套示例

  • $LEFT_PAD($LEFT('123456789',6',3,'0'))→ '000123456'
  • $RIGHT_PAD($RIGHT($CAPITALIZE('a123456789'),6),3,'0'))→ 'A1234500'
实际示例: 我所说的实际示例的意思是,这就是我所期望的字符串值的样子。您将注意到,有些变量的编写方式类似于${var}。在将字符串传递到ANTLR之前,使用ApacheCommonsStringSubstitutor将这些变量替换为实际字符串值(如果结果是我应该使用它)

用户编写的初始字符串 \HomeDir\Students\$RIGHT(${degression.year},2)\$LEFT\u PAD($LEFT(${state.id},6),3,'0'))

经过StringSubstitutor处理后的字符串 \HomeDir\Students\$RIGHT('2020',2)\$LEFT\u PAD($LEFT('123456789',6),3,'0'))

经过ANTLR处理后的字符串(以及我的最终输出)

\HomeDir\Students\20\000123456


是ANTLR似乎是我应该用于这个项目的东西,还是其他更合适的东西?

是的,ANTLR将是一个不错的选择。请记住,ANTLR只为您进行解析,并为您提供了遍历生成的解析树的机制。您必须编写代码来计算表达式

在您的情况下,当lexer偶然发现一个
“$”
时,需要通过将词法状态推为“In-a-function-mode”来触发它。当它看到一个
)”
时,应该从词法堆栈中弹出一个这样的“in-a-function-mode”

阅读ANTLR wiki上关于词法模式/堆栈的所有内容:

下面是一个如何在ANTLR4中工作的快速演示(ANTLR3不支持词法模式):

文件:TLexer.g4
lexer语法;
正文
: ~[$]
;
功能启动
:“$”->pushMode(在函数中),跳过
;
_函数中的模式;
函数嵌套:“$”->pushMode(在函数中),跳过;
ID:[a-zA-Z_]+;
PARU OPEN:'(';
PARU CLOSE:')->popMode;
编号:[0-9]+;
字符串:'\''(~'\'''\''\''\'''\'''.'')\''''.'';
逗号:',';
空格:[\t\r\n]->跳过;
文件:TParser.g4
语法分析器;
选择权{
tokenVocab=TLexer;
}
作语法分析
:原子*EOF
;
原子
:文本
|作用
;
文本
:文本+
;
功能
:ID参数
;
params
:PAR_OPEN(参数(逗号参数)*)?平局
;
param
:号码
|串
|作用
;
使用IntelliJ的ANTLR4插件,您可以轻松测试解析器的
parse
方法,并向其提供以下输入:
foo$RIGHT\u PAD($RIGHT($CAPITALIZE('a123456789'),6),3,'0')bar
,这将生成解析树的以下图像: