<h2>简短回答</h2>
<p>所有的问题都归结为这样一个事实:在解析字符串之前,没有对字符串进行标记化。在</p>
<h2>冗长的回答</h2>
<p>解析过程实际上分为两个不同的部分:<strong>词法分析</strong>和<strong>解析</strong>。在</p>
<h3>Lexing</h3>
<p>在您思考解析的方式中似乎缺少的东西称为标记化或词法分析。它是将字符串转换为令牌流(即单词)的过程。这就是你在问我如何将文本分成不同部分时所要寻找的东西?</em></p>
<p>您可以通过使用<code>re</code>根据regexp列表检查字符串,也可以使用一些著名的库,如<a href="https://github.com/dabeaz/ply" rel="nofollow noreferrer">PLY</a>。虽然如果您使用的是Python3,我将倾向于使用我编写的词法分析库<a href="https://github.com/omelancon/ComPyl" rel="nofollow noreferrer">ComPyl</a>。在</p>
<p>所以继续使用ComPyl,您要寻找的语法如下所示。在</p>
<pre><code>from compyl.lexer import Lexer
rules = [
(r'\s+', None),
(r'\w+', 'ID'),
(r'< *\w+ *>', 'TYPE'), # Will match your <TYPE> token with inner whitespaces
(r'{', 'L_BRACKET'),
(r'}', 'R_BRACKET'),
]
lexer = Lexer(rules=rules, line_rule='\n')
# See ComPyl doc to figure how to proceed from here
</code></pre>
<p>注意,第一条规则<code>(r'\s+', None)</code>,实际上是解决空白问题的方法。它基本上告诉lexer匹配任何空白字符并忽略它们。当然,如果您不想使用词法分析工具,只需在您自己的<code>re</code>实现中添加一个类似的规则。在</p>
<h3>解析</h3>
<p>您似乎想编写自己的<strong>LL(1)</strong>解析器,因此我将简要介绍这一部分。只需知道,有很多工具可以为您做到这一点(PLY和compyllibraries提供了LR(1)解析器,这些解析器功能更强大,但更难手工编写,请看LL(1)和LR(1)<a href="https://stackoverflow.com/questions/5975741/what-is-the-difference-between-ll-and-lr-parsing">here</a>)之间的区别。在</p>
<p>请注意,既然您已经知道如何标记字符串,那么<em>如何查找长度超过1个字符的标记?</em>已解决。现在解析的不是字符流,而是封装匹配的<em>单词</em>的令牌流。在</p>