【问题标题】:JAVACC How to pass token for 1 or moreJAVACC 如何为 1 个或多个传递令牌
【发布时间】:2021-11-26 13:36:36
【问题描述】:

我最近开始学习 javacc 解析器。我被要求编写一个解析器,其中一个令牌将数字从 1 到多个,另一个令牌将数字从 2 到多个 因此,我想出了这样的事情:

TOKEN : {
<NUM1: <NUM> (<NUM>)* > //for one or more
<NUM2: (<NUM>)+> //for two or more
<NUM :(["0"-"9"])+>





 // and in the function
    void calc():
    {}
    {
     (
      (<NUM1>)+
     (<NUM2>)+
     )* <EOF>
    }

但是,即使我传递了一个没有数字的文本值,它也会成功传递。我在这做错了什么?

【问题讨论】:

    标签: parsing lexer bnf javacc


    【解决方案1】:

    词法标记的 JavaCC 语法允许您在 () 范围内包含重复的元素,后跟以下之一:

    ? - zero or one time
    * - zero or more times
    + - one or more times
    

    在您的情况下,您需要两个令牌:

    TOKEN: 
    {
      <NUM2: ["0"-"9"] (["0"-"9"])+> // for two or more
      <NUM1:           (["0"-"9"])+> // for one or more
    }
    

    你的意思是:

    • 名为 NUM1 的令牌匹配从 1 到无穷大的位数
    • 名为 NUM2 的令牌匹配从两位到无穷大的位数

    JavaCC 中的词法机制使用输入字符流中的一个字符并尝试识别一个标记。两个自动机如下:

    词法分析器在两个自动机中同时处理两个标记。在没有更多进展之后,latest 找到的令牌被识别。如果 more the one 标记类型是可能的,那么声明的 first 将被识别。因此,NUM2NUM1 之前声明。这意味着对于输入 1,令牌 NUM2不会被识别,因为它需要一个以上的数字。在这种情况下,NUM1 将是唯一一个与该输入匹配的令牌类型。对于输入12,两种令牌类型都将接受它,但NUM2 将被识别,因为它首先声明。这意味着如果您先订购它们NUM1,然后订购NUM2,您将永远不会收到NUM2 令牌,因为NUM1 将始终以最高优先级“获胜”。

    要使用它们,您可以使用如下两个解析器函数:

    void match_one_to_many_numbers() : {} { <NUM1> (" " <NUM1>)* <EOF> }
    void match_two_to_many_numbers() : {} { <NUM2> (" " <NUM2>)* <EOF> }
    

    你的意思是:

    • function match_one_to_many_numbers 接受从 oneinfinity 个令牌 NUM1,用空格分隔,然后输入流必须以 @987654342 结尾@系统令牌
    • 函数match_two_to_many_numbers相同,只是来自令牌NUM2

    因为这两个标记都接受无限数量的数字,所以如果没有不是数字的分隔符,您就不能拥有这些标记的序列。

    【讨论】:

    • 感谢它的工作原理!!!
    • 因为&lt;NUM1&gt; 只匹配包含一位数字的标记,您可以简单地写成&lt;NUM1: (["0"-"9"])&gt;。如果要匹配1位或多位的token,可以在解析器中写(&lt;NUM1&gt; | &lt;NUM2&gt;)
    • 只有当您有 TOKEN 声明(例如 TOKEN:{ &lt;SPACE : " "&gt;})时,在解析器中使用 " " 才有意义。如果你用SKIP:{&lt; " "&gt;} 跳过空格,那么你不需要也不应该在语法中使用“”。如果" " 没有 TOKEN 或 SKIP 声明,并且您在语法规则中使用 " ",那么 JavaCC 将为您推断 TOKEN 声明,这可能不需要。阅读文档和常见问题解答以获得完整说明。
    • @TheodoreNorvell 第一条评论不正确,第二条评论与问题无关(没有什么可以阻止在解析器语法中使用内联标记声明,这是一个文档化的功能,我一直保留问题中要求的两种令牌类型,没有其他不相关的令牌)。
    • 第一条评论包含三个断言。哪个不是真的? (a) 多于一位的字符串不会产生 NUM1 个标记。 (b) 因此,NUM1 的定义可以简化。 (c) 您可以匹配 1 个或多个数字的字符串,如图所示。第二条评论旨在澄清您对提问者的“”使用。他的问题中没有任何迹象表明他希望“ ”成为一种象征。所以我认为值得指出的是,你的语法使 " " 成为一个标记,这对初学者来说可能并不明显。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多