2

我正在使用 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} "&>".

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

4

2 回答 2

1

尼克,这里的派对迟到了……

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

定义标记<&&>以便词法分析器知道它们。

您也许可以使用 COMMENTS 指令

<&来自TO的评论&>- 正如 CoCo 所期望的那样引用。

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

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

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

高温高压

于 2011-03-02T16:15:18.430 回答
0

您可以扩展 ANY 术语以包括<&&>和另一个非终结符(称其为 ANY_WITHIN_BLOCK )。

然后你只需使用

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

然后如果你以后真的需要它,{ANY} 的含义就不会改变。

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

正如我稍后在评论中所说的那样,我觉得真正的问题是你的语法可能太松散并且没有足够好的指定。

当我为我尝试创建的一种语言编写 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 */

在你做这一切的同时,找出你的直接标记组合,例如将“数字”定义为浮点数或整数,然后创建加/减/等规则。他们。

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

于 2010-09-09T14:28:49.353 回答