XML的形式语法

时间:2012-10-10 07:43:28

标签: c xml grammar formal-languages

我试图在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> 

它在输出端给出了END EXPECTED。

1 个答案:

答案 0 :(得分: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

这是 super 基本。终端包括:

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-stack,用于确保正确关闭最内层标记,并且是解析器根据其管理标记ID的方式的属性。它不是传统的,但它使事情变得更容易。

这可以/应该清楚地扩展到包括独立元素声明和快捷元素闭包。例如,该语法允许使用此形式的元素:

<ElementName>...</ElementName>

但不是这种形式:

<ElementName/>

它也不会解释捷径终止,例如:

<ElementName>...</>

这种添加的计算显然会使语法复杂化,但也会使解析器更加健壮。就像我说的那样,上面的例子是带有大写字母B的 basic 。如果你真的要开始这个,那么你在设计语法时要考虑的是这些,因此你的RDP也是如此

无论如何,只要考虑一下你的语法中的一些修改可以/将如何使你更容易。