0

CでXMLファイル用の小さなパーサーを構築しようとしています。完成したソリューションを見つけることができましたが、組み込みプロジェクトには基本的なものが必要です。タグだけで属性なしでXMLを記述するための文法を作成しようとしていますが、機能していないようで、理由を理解できませんでした。

文法は次のとおりです。

   XML : FIRST_TAG NIZ
   NIZ : VAL NIZ | eps
   VAL : START VAL END
     | STR
     | eps

この文法を実装するCコードの一部を次に示します。

void check() {

getSymbol();
if( sym == FIRST_LINE )
{
    niz();
}
else {
    printf("FIRST_LINE EXPECTED");
    exit(1);
 }
}

 void niz() {
getSymbol();
if( sym == ERROR )
    return;
if( sym == START ) {
    back = 1;
    val();
    niz();
}
printf(" EPS OR START EXPECTED\n");

}

void val() {
getSymbol();
if( sym == ERROR )
    return;
if( sym == START ) {
    back = 0;

    val();
    getSymbol();
    if( sym != END ) {
        printf("END EXPECTED");
        exit(1);
    }
    return;
}
if( sym == EMPTY_TAG || sym == STR)
    return;
printf("START, STR, EMPTY_TAG OR EPS EXPECTED\n");
exit(1);

}

 void getSymbol() {
int pom;

if(back == 1) {
    back = 0;
    return;
}
sym = getNextToken(cmd + offset, &pom);
offset += pom + 1;


   }

編集:これは、この文法を満たさないXMLファイルの例です。

<?xml version="1.0"?> 
<VATCHANGES> 
<DATE>15/08/2012</DATE>
<TIME>1452</TIME>
<EFDSERIAL>01KE000001</EFDSERIAL> 
<CHANGENUM>1</CHANGENUM> 
<VATRATE>A</VATRATE> 
<FROMVALUE>16.00</FROMVALUE> 
<TOVALUE>18.00</TOVALUE> 
<VATRATE>B</VATRATE> 
<FROMVALUE>2.00</FROMVALUE> 
<TOVALUE>0.00</TOVALUE> 
<VATRATE>C</VATRATE> 
<FROMVALUE>5.00</FROMVALUE> 
<TOVALUE>0.00</TOVALUE> 
<DATE>25/05/2010</DATE> 
<CHANGENUM>2</CHANGENUM> 
<VATRATE>C</VATRATE> 
<FROMVALUE>0.00</FROMVALUE> 
<TOVALUE>4.00</TOVALUE> 
</VATCHANGES> 

出力でENDEXPECTEDを与えます。

4

1 に答える 1

3

まず、文法にいくつかの作業が必要です。プリアンブルが正しく処理されていると仮定すると、NIZの定義に基本的なエラーがあります。

NIZ : VAL NIZ | eps
VAL : START VAL END
    | STR
    | eps

そこで、NIZに入り、最初にVALを探します。問題は、VALの可能なプロダクションNIZの両方の終わりのepsです。したがって、VALが何も生成せず(つまり、eps)、プロセスでトークンを消費しない場合(epsは生成であるため、適切ではありません)、NIZは次のようになります。

NIZ: eps NIZ | eps

これは良くありません。

これらの線に沿ってもっと何かを考えてみてください。私は、純粋に基本的な構造を超えた何かを持つことに、本当の先見性なしにこれを吐き出しました。

XML:         START_LINE ELEMENT
ELEMENT:     OPENTAG BODY CLOSETAG
OPENTAG:     lt id(n) gt
CLOSETAG:    lt fs id(n) gt
BODY:        ELEMENT | VALUE
VALUE:       str | eps

これは基本です。ターミナルには次のものが含まれます。

lt:    '<'
gt:    '>'
fs:    '/'
str:   any alphanumeric string excluding chars lt or gt.
id(n): any alphanumeric string excluding chars lt, gt, or fs. 

XMLの純粋主義者の怒りが今私に降り注いでいるのをほとんど感じることができますが、私が伝えようとしているポイントは、文法が明確に定義されている場合、RDPは文字通り自分自身を書き込むということです。明らかに、レクサー(つまりトークンエンジン)はそれに応じて端末を処理する必要があります。注:id(n)は、最も内側のタグを適切に閉じるためのidスタックであり、タグIDの管理方法に応じたパーサーの属性です。それは伝統的ではありませんが、物事をはるかに簡単にします。

これは、スタンドアロンの要素宣言とショートカット要素のクロージャを含めるように明確に拡張できます/すべきです。たとえば、この文法では、次の形式の要素を使用できます。

<ElementName>...</ElementName>

しかし、この形式ではありません:

<ElementName/>

また、次のようなショートカットの終了も考慮されていません。

<ElementName>...</>

このような追加を考慮すると、明らかに文法がかなり複雑になりますが、パーサーが大幅に堅牢になります。私が言ったように、上記のサンプルは大文字のBを使用した基本的なものです。これに着手する場合、これらは文法を設計するときに考慮したいことであり、結果としてRDPも考慮します。

とにかく、文法を少しやり直すだけで、これが大幅に簡単になることを考えてみてください。

于 2012-10-10T08:39:48.557 に答える