我正在尝试建立一个简单的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解析通常需要您使用不同的词法状态来处理标签之外的文本和构成标签的结构更复杂的文本。您可能会发现 词汇状态 是有帮助的。