ANTLR 嵌套函数

2024-04-24

ANTLR 适合这个项目吗?

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

我想用户有时会编写嵌套函数,例如:

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

其中预期输出为字符串值“A12345000”。

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

ANTLR 适合这样做吗?如果是这样,是否有任何类似的示例可供我查看?或者有人可以给我一个例子,说明如何在 ANTLR 中编写此代码,以便我可以拥有可以单独处理和以嵌套方式处理的自定义函数。

功能:

  • $CAPITALIZE(字符串 str)
  • $INDEX OF(字符串序列,字符串搜索序列)
  • $LEFT(字符串 str, int len)
  • $LEFT_PAD(字符串 str, int 大小,字符 padChar)
  • $LOWERCASE(字符串 str)
  • $RIGHT(字符串 str, int len)
  • $RIGHT_PAD(字符串 str, int 大小, 字符 padChar)
  • $STRIP(字符串str)
  • $STRIP_ACCENTS(字符串输入)
  • $SUBSTRING(字符串 str, int 开始)
  • $SUBSTRING(字符串 str, int 开始, int 结束)
  • $TRIM(字符串 str)
  • $TRUNCATE(字符串 str, int maxWidth)
  • $UPPERCASE(字符串 str)

基本示例:

  • $CAPITALIZE('单词') → '单词'
  • $INDEX_OF('单词', 'r') → 2
  • $LEFT('0123456789',6) → '012345'
  • $LEFT_PAD('0123456789',3, '0') → '0000123456789'
  • $LOWERCASE('Word') → '单词'
  • $RIGHT('0123456789',6) → '456789'
  • $RIGHT_PAD('0123456789',3, '0') → '0123456789000'
  • $STRIP('单词') → '单词'
  • $STRIP_ACCENTS('单词') → '单词'
  • $SUBSTRING('word', 1) → 'ord'
  • $SUBSTRING('word', 0, 2) → 'wor'
  • $TRIM('单词') → '单词'
  • $TRUNCATE('更多单词', 3) → '更多'
  • $UPPERCASE('单词') → '单词'

嵌套示例

  • $LEFT_PAD($LEFT('123456789',6),3,'0') → '000123456'
  • $RIGHT_PAD($RIGHT($CAPITALIZE('a123456789'),6),3,'0') → 'A12345000'

实际例子:我的实际示例的意思是,这就是我期望的字符串值的样子。你会注意到有一些变量的写法类似于${var}。在将字符串传递到 ANTLR 之前,这些变量将使用 Apache Commons StringSubstitutor 替换为实际字符串值(如果结果证明我应该使用它)

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

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

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

\HomeDir\学生\20\000123456

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


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

在你的情况下,当你的词法分析器偶然发现一个'$'通过将词汇状态推为“处于功能模式”。当它看到一个')',一个这样的“函数模式”应该从词法堆栈中弹出。

在 ANTLR wiki 上阅读有关词法模式/堆栈的所有内容:https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md

以下是 ANTLR4 的快速演示(ANTLR3 不支持词法模式):

文件:TLexer.g4

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;

文件:TParser.g4

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
 ;

使用 IntelliJ 的 ANTLR4 插件,您可以轻松测试parse解析器中的方法并向其提供以下输入:foo $RIGHT_PAD($RIGHT($CAPITALIZE('a123456789'), 6), 3, '0') bar,这将生成以下解析树图像:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ANTLR 嵌套函数 的相关文章

  • 在java中将StreamWriter转换为OutputStream?

    我正在尝试使用 System setOut 将 System out 重定向到字符串 它需要一个 PrintStream 有什么方法可以将 StringWriter 转换为 Stream 以便我可以将其传递给 setOut 吗 你不能完全这
  • 如何使用 SLF4J 和 Log4j2 记录 FATAL(或任何自定义日志级别)

    我有那些具体的要求 需要能够登录FATAL level 需要使用SLF4J 需要使用Log4j2 现在 这是我的执行 final Logger logger LoggerFactory getLogger HelloWorld class
  • 从 OMElement 对象获取 InputStream/io.Reader

    我有一个OMElement对象 从中我想得到一个InputStream或读者对象 我想要的是流式传输xml来自OMElement我有 没有加载到内存中 我只能得到XMLStreamReader对此表示反对 但我找不到办法得到InputStr
  • 有效地查找正则表达式的所有重叠匹配项

    这是后续与 java 正则表达式匹配的所有重叠子字符串 https stackoverflow com q 11303309 244526 有没有办法让这段代码更快 public static void allMatches String
  • 使用 jdbc 程序连接到 Open Office odb 文件

    我编写了以下代码来连接到 OpenOffice db String db C Documents and Settings hkonakanchi Desktop Test odb Class forName org hsqldb jdbc
  • 如何在Spring的applicationContext.xml中指定默认范围来请求范围?

    我想让所有 bean 请求默认作用域 但是 Spring 文档说默认作用域是 Singleton 第 3 4 1 和 3 4 2 节http static springsource org spring docs 2 5 x referen
  • 在气球内显示带有照片的多个地标的最佳做法是什么?

    我有一个项目如下 从手机上拍摄几张照片 将照片保存在网络系统中 然后将照片显示在其中的谷歌地球上 我读过很多文章 但它们都使用 fetchKml 我读过的一篇好文章是使用 php 但使用 fetchKml 我不知道是否可以使用 parseK
  • 独占锁定ConcurrentHashMap

    我知道不可能锁定 ConcurrentHashMap 进行独占访问 但是 我找不到原因 是因为构成CHM的 Segment 没有被api公开吗 据推测 如果是的话 客户端代码可以执行 交接 锁定 Cheers 我知道不可能锁定 Concur
  • 您能让 Tomcat 6 stdout.log 文件表现得像 log4j DailyRollingFileAppender 吗?

    我们使用的是 Tomcat 6 的 Windows 安装 默认情况下 我们应用程序的 log4j 输出将转到 catalina base logs stdout log 文件 该日志文件仅在我们重新启动 Tomcat 时滚动 并且文件名始终
  • java JFileChooser 文件大小过滤器

    我知道我可以按文件类型进行过滤 但是可以按文件大小进行过滤吗 例如 JFileChooser 仅显示 3 MB 以内的图片 简短的回答应该是 你尝试过什么 长答案是肯定的 JFileChooser fc new JFileChooser f
  • Java String.format 向整数添加空格

    我有一小段代码 我不明白输出 此输出向我的字符串格式文本添加空格 我做错了什么吗 public class HelloWorld public static void main String args int a1 540 int a2 4
  • .class 与 .java

    class 文件和 java 文件有什么区别 我正在尝试让我的小程序工作 但目前我只能在 Eclipse 中运行它 还不能嵌入 HTML 谢谢 编辑 那么如何使用 JVM 进行编译呢 class 文件是编译后的 java 文件 java 都
  • 使用外部硬盘写入和存储 mysql 数据库

    我已经设置了 mysql 数据库在我的 Mac 上使用 java 和 eclipse 运行 它运行得很好 但现在我将生成大约 43 亿行数据 这将占用大约 64GB 的数据 我存储了大量的密钥和加密值 我有一个 1TB 外部我想用作存储位置
  • 通用 JSF 实体转换器[重复]

    这个问题在这里已经有答案了 我正在编写我的第一个 Java EE 6 Web 应用程序作为学习练习 我没有使用框架 只是使用 JPA 2 0 EJB 3 1 和 JSF 2 0 我有一个自定义转换器 用于将存储在 SelectOne 组件中
  • 为什么在尝试使用 Java 连接到 RDS PostgreSQL 数据库时会收到 SocketTimeoutException?

    我有一个 Spring 应用程序 我试图在 AWS 上托管 几天来我一直在努力配置 我有一个 EC2 实例 并且能够通过 SSH 连接到它 我还在 AWS 中设置了 Postgres RDS 数据库 但我无法使用 IDE 中的代码连接到它
  • Scala repl 抛出错误

    当我打字时scala在终端上启动 repl 它会抛出此错误 scala gt init error error while loading AnnotatedElement class file usr lib jvm java 8 ora
  • Java SE + Spring Data + Hibernate

    我正在尝试使用 Spring Data Hibernate 启动 Java SE 应用程序 并且到目前为止已经完成了以下操作 配置文件 Configuration PropertySource classpath hibernate pro
  • Java的hashCode可以为不同的字符串产生相同的值吗?

    使用java的哈希码函数是否可以为不同的字符串提供相同的哈希码 或者如果可能的话 其可能性的 是多少 Java 哈希码是 32 位 它散列的可能字符串的数量是无限的 所以是的 会发生冲突 百分比是没有意义的 项目 字符串 的数量是无限的 而
  • 日期时间解析异常

    解析日期时 我的代码中不断出现异常错误 日期看起来像这样 Wed May 21 00 00 00 EDT 2008 这是尝试读取它的代码 DateTimeFormatter formatter DateTimeFormatter ofPat
  • 如何在Java中跨类共享变量,我尝试了静态不起作用

    类 Testclass1 有一个变量 有一些执行会改变变量的值 现在在同一个包中有类 Testclass2 我将如何访问 Testclass2 中变量的更新值 由 Testclass1 更新 试过这个没用 注意 Testclass1和Tes

随机推荐