如何使用带引号的字符解析分隔符分隔值并转义

时间:2014-01-24 08:08:39

标签: java parser-generator parser-combinators jparsec

我想用引号解析Delimiter Separated值,并使用escape来引用。

例如:a, "b""c""", d - >期望将三列(a),(b"C"),(d)视为逗号作为分隔符,而引用是引用字符和转义字符。

我想支持多个分隔符并包含字符。

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

另一个例子:a, <b\<c\>>|d - &gt;如果我们同时使用逗号和|作为分隔符,<作为左边框>作为右边框,\作为转义,则预计会解析为三列。

是否可以使用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是否可行,有没有更好的选择?

1 个答案:

答案 0 :(得分:0)

这是一个基本的工作示例,使用双引号作为字符串封闭和加倍双引号来转义双引号(类似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));
         }
       };
   }

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

作为一般指导原则,使用Test Driven Development编写jparsec解析器是一个很好的组合。至少你应该编写单元测试,以便很好地理解每个解析器的工作原理以及它们如何组合。