首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python -词法分析和标记化

Python -词法分析和标记化
EN

Stack Overflow用户
提问于 2010-03-01 20:32:35
回答 5查看 15.1K关注 0票数 12

我希望在这里加快我的发现过程,因为这是我第一次进入词汇分析的世界。也许这是一条错误的道路。首先,我将描述我的问题:

我有非常大的属性文件(按1000个属性的顺序排列),经过蒸馏后,实际上只有大约15个重要的属性,其余的属性可以生成,或者很少更改。

因此,例如:

代码语言:javascript
复制
general {
  name = myname
  ip = 127.0.0.1
}

component1 {
   key = value
   foo = bar
}

这是我想要创建的格式类型,用于标记如下所示:

代码语言:javascript
复制
property.${general.name}blah.home.directory = /blah
property.${general.name}.ip = ${general.ip}
property.${component1}.ip = ${general.ip}
property.${component1}.foo = ${component1.foo}

转到

代码语言:javascript
复制
property.mynameblah.home.directory = /blah
property.myname.ip = 127.0.0.1
property.component1.ip = 127.0.0.1
property.component1.foo = bar

词法分析和标记化听起来是我最好的方法,但这是一个非常简单的形式。这是一个简单的语法,一个简单的替代,我想确保我没有带来一个大锤敲钉子。

我可以创建我自己的lexer和记号器,或者ANTlr是一种可能,但是我不喜欢重新发明轮子,ANTlr听起来有点过火了。

我不熟悉编译器技术,所以最好是正确方向的指针&代码。

注意事项:我可以更改输入格式。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-03-01 22:36:45

用正则表达式进行词法分析上有一篇关于effbot.org的优秀文章。

根据您的问题调整令牌程序:

代码语言:javascript
复制
import re

token_pattern = r"""
(?P<identifier>[a-zA-Z_][a-zA-Z0-9_]*)
|(?P<integer>[0-9]+)
|(?P<dot>\.)
|(?P<open_variable>[$][{])
|(?P<open_curly>[{])
|(?P<close_curly>[}])
|(?P<newline>\n)
|(?P<whitespace>\s+)
|(?P<equals>[=])
|(?P<slash>[/])
"""

token_re = re.compile(token_pattern, re.VERBOSE)

class TokenizerException(Exception): pass

def tokenize(text):
    pos = 0
    while True:
        m = token_re.match(text, pos)
        if not m: break
        pos = m.end()
        tokname = m.lastgroup
        tokvalue = m.group(tokname)
        yield tokname, tokvalue
    if pos != len(text):
        raise TokenizerException('tokenizer stopped at pos %r of %r' % (
            pos, len(text)))

为了测试它,我们做:

代码语言:javascript
复制
stuff = r'property.${general.name}.ip = ${general.ip}'
stuff2 = r'''
general {
  name = myname
  ip = 127.0.0.1
}
'''

print ' stuff '.center(60, '=')
for tok in tokenize(stuff):
    print tok

print ' stuff2 '.center(60, '=')
for tok in tokenize(stuff2):
    print tok

适用于:

代码语言:javascript
复制
========================== stuff ===========================
('identifier', 'property')
('dot', '.')
('open_variable', '${')
('identifier', 'general')
('dot', '.')
('identifier', 'name')
('close_curly', '}')
('dot', '.')
('identifier', 'ip')
('whitespace', ' ')
('equals', '=')
('whitespace', ' ')
('open_variable', '${')
('identifier', 'general')
('dot', '.')
('identifier', 'ip')
('close_curly', '}')
========================== stuff2 ==========================
('newline', '\n')
('identifier', 'general')
('whitespace', ' ')
('open_curly', '{')
('newline', '\n')
('whitespace', '  ')
('identifier', 'name')
('whitespace', ' ')
('equals', '=')
('whitespace', ' ')
('identifier', 'myname')
('newline', '\n')
('whitespace', '  ')
('identifier', 'ip')
('whitespace', ' ')
('equals', '=')
('whitespace', ' ')
('integer', '127')
('dot', '.')
('integer', '0')
('dot', '.')
('integer', '0')
('dot', '.')
('integer', '1')
('newline', '\n')
('close_curly', '}')
('newline', '\n')
票数 14
EN

Stack Overflow用户

发布于 2010-03-01 21:22:52

一个简单的DFA可以很好地解决这个问题。你只需要几个州:

  1. 寻找${
  2. 看到${寻找至少一个构成名称的有效字符
  3. 至少看到一个有效的名称字符,查找更多的名称字符或}

如果属性文件与顺序无关,则可能需要两个pass处理器来验证每个名称是否正确解析。

当然,您需要编写替换代码,但是一旦您有了所有使用的名称的列表,最简单的实现就是在${name}上找到/替换它的相应值。

票数 4
EN

Stack Overflow用户

发布于 2010-03-01 20:50:03

因为尽管您的格式看起来很简单,但我认为一个完整的解析器/词法器可能会太过分了。看起来,将regexes和字符串操作结合起来就可以做到这一点。

另一个想法是将文件更改为类似于json或xml的内容,并使用现有的包。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2358890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档