java - 如何用引号和转义符解析分隔符分隔值

标签 java parser-generator parser-combinators jparsec

我想用引号字符和转义来解析分隔符分隔值。

例如:a, "b""c""", d -> 预期削减为三列 ( a ), ( b"C" ), ( d ) 假定逗号作为分隔符,引号既是引号又是转义符。

我也想支持多个分隔符和封闭字符。

例如:a, "b""c"""|d -> 如果我们同时使用逗号和 |,预计将减少为三列用作分隔符。

另一个例子:a, <b\<c\>>|d -> 如果我们同时使用逗号和 |,预计将解析为三列作为分隔符,<如左外壳 >作为右外壳和 \作为逃生。

是否可以使用 JParsec 创建解析器组合器?

在花了一些时间使用 API 之后,我希望下面的代码能够正常工作,但它并没有像预期的那样解析上面的示例。

Parser<?> quote_content = Scanners.notAmong(rightEnclose).many();
Parser<?> quoted = Scanners.nestableBlockComment(Scanners.among(leftEnclose),
            Scanners.among(rightEnclose), quote_content);
Parser<?> unquoted = Scanners.notAmong(delimiter + leftEnclose);
Parser<?> chunk =  Parsers.or(escapedSequence(), unquoted);

Parser<?>  all = chunk().many1().source().sepBy(Scanners.among(delimiter));

请建议是否可以使用 JParsec,是否有更好的选择?

最佳答案

这是一个基本的工作示例,使用双引号作为包含字符串并使用双引号来转义双引号(类似于 SQL 的字符串...):

   @Test public void test() throws Exception {
     Parser<Void> escapingDoubleQuotesString = pattern(regex("((\"\")|[^\",])*"), "string");
     Parser<String> quoted = escapingDoubleQuotesString //
       .between(isChar('"'), isChar('"')).source() //
       .map(unquoteString());

     assertThat(quoted.parse("\"\"\"c\"")).isEqualTo("\"c");

     Parser<String> unquoted = escapingDoubleQuotesString.source().map(unescapeQuotes());

     assertThat(unquoted.parse("\"\"c")).isEqualTo("\"c");

     Parser<List<String>> separated = quoted.or(unquoted).sepBy(pattern(regex("\\s*,\\s*"), "comma"));

     assertThat(separated.parse("a,\"b\"\"c\"\"\", d")).containsExactly("a", "b\"c\"", "d");
   }

   private Map<? super String, ? extends String> unescapeQuotes() {
     return new Map<String, String>() {
         @Override public String map(String s) {
           return s.replace("\"\"", "\"");
         }
       };
   }

   private Map<String, String> unquoteString() {
     return new Map<String, String>() {
         @Override public String map(String s) {
           return unescapeQuotes().map(s.substring(1, s.length() - 1));
         }
       };
   }

这可以通过区分带引号的字符串内容和不带引号的字符串内容以允许在带引号的字符串内使用逗号来改进。在此基础上,添加更多分隔符或更改字符串的引号/括号方式应该相当容易。

作为一般准则,使用测试驱动开发来编写 jparsec 解析器是一个很好的组合。至少您应该编写单元测试,以便很好地了解每个解析器的工作方式以及它们的组合方式。

关于java - 如何用引号和转义符解析分隔符分隔值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21327504/

相关文章:

scala - 在 ScalaCheck 中从语法生成字符串

用于递归 bnf 的 Scala Parser Combinators 技巧?

rust - 使用 nom errorkind 返回简单自定义错误的正确方法是什么?

java - 在Java Eclipse中添加 "Run to Line"按钮

java - JPQL 查询 - java.lang.String 无法转换为 model.xxx

regex - 什么时候使用解析器生成器,什么时候使用正则表达式就足够了?

compiler-construction - GLR解析算法资源

java - 如何在PreparedStatement上使用一种方法设置多个参数

java - 如何在本地文件上使用 XMLPullParser

scala - 如何允许可选的最外括号?