【问题标题】:Validating a string against a grammar in Java根据 Java 中的语法验证字符串
【发布时间】:2015-05-18 01:14:06
【问题描述】:

我正在做一个附带项目(尝试学习正则表达式并在一般解析方面做得更好)并尝试编写一个函数来验证字符串在特定语法下是否有效。语法如下:

statement -> delimeter token
delimeter -> / or -
token -> name ([check])* (delimeter token)?
check -> token
         @id="..."

我已经为上面的每一个(除了token)写出了正则表达式,它们写在下面。但是,当我尝试写出令牌正则表达式时,我意识到它依赖于自身(递归)。我不太确定如何编写这个正则表达式,或者这是否是正确的方法,因为检查可能会非常深入。有没有更好的方法来验证字符串是否可以用语法表示?如果没有,我该如何使用正则表达式?

String delimeter = "/|-";
String name = "((?i)\\A[a-z][_a-z\\d\\-\\.]*){1}";
String checkToken = would just be equal to token;
String checkID = "(?i)\\A\\s*@id\\s*=\\s*\".*\"\\s*\\Z";

我正在使用 String.matches 调用来查看字符串是否与正则表达式匹配,现在只检查较小的内容,例如名称是否正确。

【问题讨论】:

    标签: java regex validation parsing


    【解决方案1】:

    您正在寻找对Chomsky hierarchy 的更好理解。

    层次结构的简单形式有以下几种:

    1. 递归可枚举图灵机匹配
    2. Context-sensitiveLinear-bounded non-deterministic Turing machine 匹配
    3. 上下文无关由一个非确定性下推自动机匹配
    4. RegularFinite state automaton 匹配

    正则表达式是对可以匹配正则语言的有限状态自动机的描述。如果语言不是正则语言,则在尝试将非正则语言与正则表达式匹配时,您会冒summoning Tony the Pony 的风险(这不是一件好事)。

    给定的匹配工具可以匹配其级别或更高级别的任何语言。因此,非确定性下推自动机可以匹配上下文无关语言和常规语言。但是有限状态自动机只能匹配正则语言。

    通常,在编译器设计等方面,词法分析器(使用常规语言)与一个解析器生成器配对,后者适用于上下文无关语言。这可以通过 lexyacc 或 flex 和 bison 的配对看到。

    Lex 具有匹配标记并将它们传递给 yacc 的语法。在现代 Java 世界中,您可能希望查看 antlr - 另一种语言识别工具,以帮助您编写解析器。 JavaCC 也被推荐(另一种工具,有些人更喜欢,如果你打算走这条路,你应该研究这两个工具)。 Lex & Yacc、Antlr 和 JavaCC 属于称为parser generators 的工具领域的一部分,如果您想对它们进行比较的话。

    我建议阅读Lex & Yacc Tutorial。虽然,是的,它适用于您没有使用的 lex 和 yacc,但有一节介绍了它背后的理论(词法分析和解析)。理解理论将帮助您了解为什么您当前的方法不起作用。

    【讨论】:

    • 我会推荐 JavaCC 而不是 ANTLR - 它更简单,更容易开始。
    • @thehandyman 您正在研究的领域被称为“计算理论” - 当您寻找它时,您会发现更多关于您正在尝试做的事情背后的理论。快速搜索可以找到许多教授在其网页上发表的书籍和讲义。如果您不想过于学术,O'Riely 有一本书 Understanding Computation 使用 Ruby 从正则表达式转换为高度评价的图灵机。
    • 非常感谢!我去看看这本书。
    【解决方案2】:

    尝试编写一个函数来验证字符串在特定语法下是否有效

    Err,parser 就是执行此操作的函数。如果它解析,它是有效的。如果它得到一个语法错误,它不是。这是验证一个字符串,不是根据你的标题验证语法本身。

    我已经为上面的每一个(除了token)写出了正则表达式,它们写在下面。但是,当我尝试写出令牌正则表达式时,我意识到它依赖于自身(递归)。我不太确定如何编写这个正则表达式,或者这是否是正确的方法,因为检查可能会非常深入。有没有更好的方法来验证字符串是否可以用语法表示?如果没有,我该如何使用正则表达式?

    你没有。

    您无法使用正则表达式解析递归语法。正则表达式用于表征 词法分析器。 语法 将是一个上下文无关的语法,要么是 LL(1),要么是 LR(1)。如果您不知道这些术语的含义,那么您需要大量阅读。

    【讨论】:

      【解决方案3】:

      具有递归定义的语法通常不是正则的,因此不能用正则表达式解析。

      但是,在您的情况下,您似乎可以将语法转换为常规形式:

      statement -> ( delimiter token )+
      delimiter -> / or -
      token -> name ([check])*
      check -> token
               @id="..."
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-06
        • 2020-12-23
        • 1970-01-01
        • 2015-05-31
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        相关资源
        最近更新 更多