首页 > 解决方案 > 为什么我的某些令牌无法识别?

问题描述

我正在尝试构建一个简单的 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 的工作方式一样。我不明白为什么它与其他令牌的工作方式不同。

标签: pythonlexlexerply

解决方案


您所做的一切都被添加<h1reserved. 这不会使字符串变得特别。它也不会更改包含字符串的字符串<h1与正则表达式匹配的方式。<h1 id="someid"是您的文本模式的匹配项,因此词法分析器执行t_text操作功能。

总的来说,这不是进行词法分析的方法。词法分析应该将输入划分为词位,其中每个词位都是一个原语。<h1 id="someid"不是词素;它可能是五个词位(<, h1, id, =, "someid",假设空格已被丢弃)。输入的结构将由解析器进行分析,不需要为了保存一两个产生式而使您的词法分析器复杂化。

HTML 解析通常要求您使用不同的词法状态来处理标签之外的文本以及构成标签的更多结构化文本。您可能会发现词汇状态很有帮助。


推荐阅读