【问题标题】:Parsing a code block with EBNF expression使用 EBNF 表达式解析代码块
【发布时间】:2010-09-09 14:25:35
【问题描述】:

我正在使用 CocoR 生成类似 java 的扫描器/解析器:
我在创建 EBNF 表达式以匹配代码块时遇到了一些麻烦:

我假设一个代码块被两个众所周知的标记包围: 示例:

public method(int a, int b) <&  
various code  
&>  

如果我定义一个非终结符

codeblock = "<&" {ANY} "&>"  

如果两个符号内的代码包含“

有什么提示吗?

编辑:

COMPILER JavaLike
CHARACTERS

nonZeroDigit  = "123456789".
digit         = '0' + nonZeroDigit .
letter        = 'A' .. 'Z' + 'a' .. 'z' + '_' + '$'.

TOKENS
ident = letter { letter | digit }.

PRODUCTIONS
JavaLike = {ClassDeclaration}.
ClassDeclaration ="class" ident ["extends" ident] "{" {VarDeclaration} {MethodDeclaration }"}" .
MethodDeclaration ="public" Type ident "("ParamList")" CodeBlock.
Codeblock = "<&" {ANY} "&>".

为了简单起见,我省略了一些产生式。
这是我对语法的实际实现。主要错误是,如果块中的代码包含符号“>”或“&”之一,则会失败。

【问题讨论】:

    标签: java compiler-construction grammar ebnf cocor


    【解决方案1】:

    尼克,在这里聚会迟到了……

    有很多方法可以做到这一点:

    为&lt;&amp; 和&amp;&gt; 定义标记,以便词法分析器了解它们。

    您可以使用 COMMENTS 指令

    来自&lt;&amp; 到&amp;&gt; 的评论 - 正如 CoCo 所期望的那样。

    或者在你的scanner.frame 文件中修改NextToken()。做这样的事情(伪代码):

    if (Peek() == CODE_START)
    {
         while (NextToken() != CODE_END)
         {
            // eat tokens
         }
    }
    

    或者可以重写Buffer中的Read()方法,在最底层吃。

    HTH

    【讨论】:

      【解决方案2】:

      您可以扩展 ANY 术语以包括 &lt;&amp;、&amp;&gt; 和另一个非终结符(称之为 ANY_WITHIN_BLOCK)。

      那你就用

      ANY = "<&" | {ANY_WITHIN_BLOCK} | "&>"
      codeblock = "<&" {ANY_WITHIN_BLOCK} "&>"
      

      如果以后真的需要的话,{ANY}的含义不变。

      好吧,我对CocoR一无所知,给了你一个无用的答案,让我们再试一次。

      正如我后来在 cmets 中开始说的,我觉得真正的问题是你的语法可能太松散并且没有足够明确。

      当我为我尝试创建的一种语言编写 CFG 时,我最终使用了一种“中间相遇”的方法:我编写了顶层结构和直接的底层结构首先是令牌的组合,然后努力使它们在中层(我猜大约是条件和控制流的级别)相遇。

      你说这种语言有点像 Java,所以让我向你展示我将写的第一行作为描述其语法的初稿(用伪代码,抱歉。实际上它就像 yacc/bison。在这里,我'我使用你的括号而不是 Java 的):

      /* High-level stuff */
      
      program: classes
      
      classes: main-class inner-classes
      
      inner-classes: inner-classes inner-class
                   | /* empty */
      
      main-class: class-modifier "class" identifier class-block
      
      inner-class: "class" identifier class-block
      
      class-block: "<&" class-decls "&>"
      
      class-decls: field-decl
                 | method
      
      method: method-signature method-block
      
      method-block: "<&" statements "&>"
      
      statements: statements statement
                | /* empty */
      
      class-modifier: "public"
                    | "private"
      
      identifier: /* well, you know */
      

      在您执行所有这些操作的同时,找出您的直接标记组合,例如将“数字”定义为浮点数或整数,然后创建加/减/等规则。他们。

      到目前为止,我不知道您的方法是什么,但您肯定希望确保仔细指定所有内容并在需要特定结构时使用新规则。不要因为创建一对一的规则而感到荒谬,但如果它可以帮助您更好地组织您的想法,请不要害怕创建新规则。

      【讨论】:

      • 你会如何定义 ANY_WITHIN_BLOCK?
      • ANY 是 CocoR 中的“快乐”标记:它匹配每个标记。
      • 对不起,我承认我对 CocoR 不熟悉。我只是在写一个伪代码 CFG 语言。我假设您已经定义了 {ANY} 但如果这只是一个包罗万象的标记,那么这显然会使事情复杂化。 :-)(编辑:该死。哈哈)
      • 我给你更多细节:我可以用这种方式定义一个字符集:字母 ="A..Z" + "%>" 所以一个字母可以是任何大写字母或 " 中的符号”。然后我可以定义一个令牌,它必须根据字符集来定义。所以一个记号,比方说,word 应该定义为: word = letter{letter}
      • 啊,而 {WHATEVER} 表示零个或多个 WHATEVER?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-20
      相关资源
      最近更新 更多