好吧,假设我正在解析一些XML(在阅读任何“语言”时存在问题,但XML是很多人都熟悉的。)
XML如下所示:
<Tag>
<[CDATA[ blah blah]]>
<Tag2>
<Tag3/>
</Tag2>
<Tag>
现在我想在该流中找到各种令牌。重要的令牌如下(请原谅我糟糕的“令牌”名称;))。
< = Open Token
<[CDATA[ = Open CDATA Token
]]> = Close CDATA Token
<! = Open Comment Token
/> = Close Open Token
</ = Open Close Token
> = Close Token
我遇到的问题是我有一个上面的数组,我正在尝试正确识别上述令牌中的一个,因为我逐字逐句地读取文件。
所以我读了第一个字符'&lt;'。当下的想法是,这与“开放令牌”匹配,所以我们将选择它。但是,它也与“打开关闭令牌”的第一个字符匹配。所以我们说我们读第二个字符及其'A'。所以我立即知道这是“开放令牌”而不是“打开关闭令牌”。
同样在完成标签时,例如“/&gt;”。我读了第一个字,我得到'/'。这与“Close Open Token”相匹配。但它不完整所以我应该检查下一个字符,在这种情况下是'&gt;'给我“/&gt;”它与Close Token匹配。
我的问题是,当这些令牌的数量显着增加时,很难跟踪可能的匹配是什么。有一种优雅的方式来做到这一点?或者我应该,只是当我遇到其中一个“令牌字符串”的第一个字符时,将该令牌推送到一个向量,然后在后续读取时只检查这些令牌?如果下一个字符不匹配,那么我可以清除令牌列表然后重新开始。
这是解决问题的正确方法吗?还有更好的方法吗?
(编辑:请不要指向Lexx,YACC等......我正在尝试学习一些基础知识)
任何帮助都会非常感激:)
答案 0 :(得分:1)
您需要在解析器中跟踪状态 - 我现在在哪里?我接下来会发生什么? - 以特定于上下文的方式。当您看到下一步得到的内容时,可以根据当前状态的有效值列表进行检查,并可能存储已完成的已解析数据项,并可能更改状态。
仅解析XML 看起来很简单< - em>如果你真的想自己手工完成这项工作,那么就有很多需要处理的问题。你的解析器是Finite State Machine,但这是一个非平凡的例子。
答案 1 :(得分:1)
我最近一直在做很多这种类型的解析(主要是使用C#)。
我不确切知道你要完成什么,所以我不确定这有多少帮助,但我会解析整个事情并将其存储在某种数据阵列中。
找到开始标记。然后解析接下来的任何文本(你知道当你到达文本的末尾,因为你要么点击空格或标点符号)。
您可以为“!”进行特殊测试并且可能在找到数据结构时在其中设置一个标志。我发现对已知序列进行快速扫描是不切实际的。你需要逐字逐句地分解整个事物。
您可以在http://www.softcircuits.com/Blog/post/2010/02/07/Parsing-HTML-Tags-in-C.aspx看到我的一个C#结果。
答案 2 :(得分:0)
您可以flex为您执行此操作。更好的是,为您的语言挖掘现有的XML解析器 - 我确信有人已经实现了它。
答案 3 :(得分:0)
解析是一个众所周知的问题,但这并不意味着它很容易编程。 你可以自己写任何东西,但正如你遇到的那样,这变得非常复杂。
您可以使用Boost.Spirit库,它非常大,可能需要一些时间来掌握。
或者作为替代方案,使用Lex / Yacc(或类似的东西)生成解析器和词法分析器。 (这比C ++更多C,但当然不一定是坏事)
我个人花时间学习掌握Boost Spirit库,虽然一开始可能看起来很多,但从长远来看,你会节省很多时间和头痛。手动解析类似XML的语言需要的工作量比您最初预期的要多得多。