python - 为什么我的某些令牌无法识别?
问题描述
我正在尝试构建一个简单的 HTML 词法分析器,并且我已经像这样定义了我的标记:
tokens = [
'text',
'num',
'id',
'url',
'newline',
'space',
'bigger',
'sp',
'del',
'vert',
'carr',
]
reserved = {'<html lang = "en"':"html_open", '<h1': 'h1_open', '</h1>':'h1_close','<p': 'p_open',
'</p': 'p_close', '<body': 'body_open', 'id=': 'id_att', '</body': 'body_close' }
tokens = tokens+list(reserved.values())
t_bigger = '>'
t_newline = r'[\n]'
t_sp = r'[\s]'
t_del = r'[\d]'
t_vert = r'[\v]'
t_carr = r'[\r]'
def t_text(t):
r'[a-zA-Z_0-9_<_ _"_=_/][ a-zA-Z_0-9_<_ _"_=_/]*'
t.type = reserved.get(t.value,'text')
return t
def t_id(t):
r'[a-zA-Z_0-9_<_"][a-zA-Z_0-9_"]*'
t.type = reserved.get(t.value,'id')
return t
def t_num(t):
r'\d'
t.value = int(t.value)
return t
def t_error(t):
print ("invalid char '%s'" %t.value[0])
t.lexer.skip(1)
我用来测试的文本是:
<html lang = "en">
<body>
<h1 id="someid"> This is a test </h1>
<p> Paragraph </p>
</body>
当我运行它时,我得到了这个:
LexToken(html_open,'<html lang = "en"',1,0)
LexToken(bigger,'>',1,17)
LexToken(sp,'\r',1,18)
LexToken(newline,'\n',1,19)
LexToken(body_open,'<body',1,20)
LexToken(bigger,'>',1,25)
LexToken(text,' ',1,26)
LexToken(sp,'\r',1,27)
LexToken(newline,'\n',1,28)
LexToken(sp,'\t',1,29)
LexToken(text,'<h1 id="someid"',1,30)
LexToken(bigger,'>',1,45)
LexToken(text,' This is a test </h1',1,46)
LexToken(bigger,'>',1,66)
LexToken(text,' ',1,67)
LexToken(sp,'\r',1,68)
LexToken(newline,'\n',1,69)
LexToken(sp,'\t',1,70)
LexToken(p_open,'<p',1,71)
LexToken(bigger,'>',1,73)
LexToken(text,' Paragraph </p',1,74)
LexToken(bigger,'>',1,88)
LexToken(text,' ',1,89)
LexToken(sp,'\r',1,90)
LexToken(newline,'\n',1,91)
LexToken(body_close,'</body',1,92)
LexToken(bigger,'>',1,98)
我的问题是它<h1 id="someid"
被解释为“文本”,并且
LexToken(h1_open,'<h1)
LexToken(id_att, 'id=')
LexToken(id, ' "someid" ')
LexToken(text,' Paragraph')
LexToken(p_close,'</p')
我怎样才能做到这一点?我已经将 h1_open、p_close 和 id_att 定义为“保留”,认为它们将被单独标识,就像 p_open 和 body_open 的工作方式一样。我不明白为什么它与其他令牌的工作方式不同。
解决方案
您所做的一切都被添加<h1
为reserved
. 这不会使字符串变得特别。它也不会更改包含字符串的字符串<h1
与正则表达式匹配的方式。<h1 id="someid"
是您的文本模式的匹配项,因此词法分析器执行t_text
操作功能。
总的来说,这不是进行词法分析的方法。词法分析应该将输入划分为词位,其中每个词位都是一个原语。<h1 id="someid"
不是词素;它可能是五个词位(<
, h1
, id
, =
, "someid"
,假设空格已被丢弃)。输入的结构将由解析器进行分析,不需要为了保存一两个产生式而使您的词法分析器复杂化。
HTML 解析通常要求您使用不同的词法状态来处理标签之外的文本以及构成标签的更多结构化文本。您可能会发现词汇状态很有帮助。
推荐阅读
- php - 如何在 Web 服务器中正确调用 Angular 和 Php 应用程序的 api 调用?
- asterisk - Asterisk 11 谁挂断了电话?
- flutter - 如何获取要在另一个函数中使用的复选框值?
- javascript - 如何从角度服务结果中正确退订?
- ios - 水平 UIStackView - 修复中心项目的大小并拉伸其他项目
- c# - 打包的 Excel DNA .xll 文件不加载功能区
- laravel - Laravel 事务即使在回滚时也会将数据保存到数据库中
- cmake - 如何在模块模式下为 find_package 设置 Find*.cmake?
- haskell - 学习 Haskell 中“:?:”运算符的含义
- ruby - 更改多维哈希值,它仍然相等