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> 

它在输出端给出 END EXPECTED。

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-stack 以确保您正确关闭最里面的标签,并且是您的解析器的一个属性,根据它管理标签 id 的方式。它不是传统的,但它使事情变得容易得多。

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

<ElementName>...</ElementName>

但不是这种形式:

<ElementName/>

它也不考虑捷径终止,例如:

<ElementName>...</>

考虑到这些添加显然会使语法变得相当复杂,但也会使解析器更加健壮。就像我说的,上面的示例是基本的,带有大写字母 B。如果你真的要开始这个,这些是你在设计语法时要考虑的事情,因此也是你的 RDP。

无论如何,只要考虑一下你的语法中的一些修改如何/将大大地让你更容易做到这一点。

于 2012-10-10T08:39:48.557 回答