2

CocoR を使用して Java のようなスキャナー/パーサーを生成しています。コード
ブロックに一致する EBNF 式を作成する際に問題が発生しています。

コード ブロックが 2 つのよく知られたトークン <& と &> で囲まれていると想定しています。例:

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

非終端記号を定義すると

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

2 つのシンボル内のコードに「<」文字が含まれている場合、生成されたコンパイラはそれを処理しないため、構文エラーが発生します。

ヒントはありますか?

編集:

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()メソッドをオーバーライドして、最低レベルで食べることができます。

HTH

于 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 */

それと同時に、「数値」を float または int として定義し、加算/減算などのルールを作成するなど、即時のトークンの組み合わせを把握します。彼ら。

これまでのところ、あなたのアプローチが何であるかはわかりませんが、特定の構造が必要な場合は、すべてを慎重に指定し、新しいルールを使用するようにしてください. 1 対 1 のルールを作成することにばかげてはいけませんが、考えをよりよく整理するのに役立つ場合は、新しいルールを作成することを恐れないでください。

于 2010-09-09T14:28:49.353 に答える