说我正在为扫描robots.txt写一个词法分析器。
说我想从旧的RFC(http://www.robotstxt.org/norobots-rfc.txt)开始,只想做最基本的语法:
# COMMENT
User-agent: Google
Disallow: /admin
Disallow: /foo.html
Allow: /bar/bar.html
Python中的基本规则就是这样的
_RULES = [
(WHITESPACE, r"\s+"),
(COLON, r":"),
(COMMENT, r"#.+"),
(UA_ID, r"user-agent"),
(ALLOW_ID, r"allow"),
(DISALLOW_ID, r"disallow"),
(RPATH, r"(\/[a-zA-Z0-9|\:|\@|\&|\=\.]*)+"),
(UA_VALUE, r".+"),
]
请注意,如果我们将UA_VALUE
放在RPATH
之前,则贪婪会使/admin
与UA_VALUE
匹配,这不是我们以后在解析器进程中真正想要的。< / p>
现在我想我的lexer会接受一组“扩展规则”(很多robots.txt现在都有“自定义”指令,这在旧RFC中被预见为“扩展”)。
扩展程序可能是支持完整的网址,而不是像RPATH
这样的路径文件。或者,如果我们支持Craw-delay
,其中包含数字或分数。现在,用户必须以正确的顺序将新的扩展规则插入_RULES
,以避免与错误的规则匹配,从而产生错误的令牌类型。
我可以看到无法正常使用正则表达式的问题,但我相信这个对顺序敏感的问题也可以存在于手写的char-by-char,基于switch语句的方法中。
一般来说,我们可以避免这种排序问题吗?或者,我是否会在语义分析中尝试通过查看邻居来“修复”这种令牌来“修复”错误的令牌类型?它可能适用于像robots.txt这样的琐碎语言。我是否需要将一些规则进一步细化为较小的单位?例如,整个http/https://url...
代替正则表达式,我将http://
和https://
作为两个单独的令牌类型。
答案 0 :(得分:1)
您可以在字段名称标记中包含:。此外,“标准”坚持声明从第一列开始,因此您还可以添加锚操作符(^
)。如果不是这样的话,你可以把正则表达式装扮一下:
"^[[:blank:]]*Allow[[:blank:]]*:"
除此之外,robots.txt
与许多互联网标准一样,对非语义词法分析也不会很好。个别指令有自己的词汇规则。 Unextended robots.txt
是一个简单的案例,因为在Allow
和Disallow
的情况下,允许的唯一内容是(部分)URL,在{的情况下,任意字符串不包含# {1}}。但扩展可能有自己的格式。
我解析User-Agent
协议的常用方法是提取字段(使用上面的简单正则表达式),然后在将字段名称映射到值解析器的表中查找语法。这个主题有各种各样的变种,但这是基本的想法。