我的第一个Python程序——lexer

你好,
我开始在python写一个lexer-我第一次尝试做某事
对Python有用(而不是尝试从教程中尝试摘要)。它
还不完整,但我想要一些反馈 - 我是Python
新手,似乎有了python,总是有一个更简单的
做到这一点的方法比您想象的要好。
### 开始 ###
导入
类Lexer(对象):
def __init __(自我,来源,代币):
self.source = re.sub(r" \ r?\ n | \ r \ n"," \ n",source)
self.tokens =令牌
self.offset = 0
self.result = []
self.line = 1
self._compile()
self._tokenize()
def _compile(self):
为了姓名,self.tokens.iteritems()中的regex:
self.tokens [name] = re.compile(Regex,re.m)
def _tokenize(self):
而self.offset 为了姓名,self.tokens.iteritems()中的regex:
match = regex.match(self.source,self.offset)
如果不匹配:继续
self.offset += len(match.group(0))
self.result.append((名称,匹配,self.line))
self.line += match.group(0).count(" \ n")
休息
别的:
提高例外(
'offset%s'%的源语法错误
str(self.offset))
def __str __(self):
返回" \ n" .join(
[" [l:%s] \ t [o:%s] \ t [%s] \ t'%s'"%
(str(line),str(match.pos),名称,match.group(0))
为了姓名,匹配,在self.result中行])))
#测试示例
source = r""""
名称:"托马斯",#只是评论
年龄:37
"""
tokens = {
't_Identifier':r'[a-za-z _] [a-za-z0-9 _]*',
't_number':r'[+ - ]?\ d+',
't_string':r'""(?:\\。| [^\\"])*"',
't_operator':r'[=:,,;]',,
't_newline':r'\ n',
't_lwsp':r'[\ t]+',,
't_comment':r'(?:\#| //)
打印Lexer(来源,令牌)
### 结尾 ###
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison!
(coluche)

# 回答1


thomas mlynarczyk 你好,
除了约翰的评论中,我不会作为成员
lexer对象,但作为tokenise()方法的参数(我会
公开)。令牌方法将返回您当前称呼的内容
自我。因此,它将像这样使用。
# 之后:
- -
Arnaud
# 回答2


Arnaud Delobelle Schrieb:
在以后的阶段,我打算不要一次让源代币化,
但是令牌是"及时的",当时解析器(尚未写成)
访问下一个令牌:
token = mylexer.next('foo_token')
如果不是代币:提高异常('Foo Token预期。')
#继续做一些有用的令牌
next()将返回下一个令牌(并推进内部
指针) *如果 *是foo_token,否则它将返回false。这个
方式,将减少正则匹配的总数:只有
预期是"尝试的"。
但是否则,经过反思,我认为你是对的,那会
确实,按照您的建议更合适。
感谢您的反馈意见。
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison!
(coluche)
# 回答3


11月9日,8:34*PM,Dennis Lee Bieber < wlfr ...@ix.netcom.comwrote:
* * * *您是否强迫使用固定长度线?
* * * *否则,您将通过哪种算法转换:
... 一
... 二
... 三
...四
... 五
...超级fielifragilisticexpialidocious
... 七
... 八
...九"" >> ix = data.index(" list")
39
loc = data.index("列表")
打印数据[:loc] .count(" \ n") - 1
打印loc-data [:loc] .rindex(" \ n") - 1
打印5,14
我敢肯定这是不最佳的,但是 *是 *一种算法
需要跟踪每行的开始...
- 保罗
# 回答4


在阳光下,2008年11月9日15:53:01 +0100,托马斯·梅纳尔奇克(Thomas Mlynarczyk)写道:
在以后的阶段,我打算不要一次让源代币化,
但是令牌是"及时的",当时解析器(尚未写成)
访问下一个令牌:
您不必为Lexer类引入" Next"方法。你
可以通过替换将您的"令牌"方法转换为发电机
``self.result.append'带有``屈服''。它给了你刚刚的零件
免费的同时不将算法挑选成微小的无关零件。
Python发电机最近(2.5)增长了"发送"方法。您可以使用
``next`用于无条件的令牌化和``mytokenizer.send''(预期
令牌")`
有关详细信息,请参见http://www.python.org/dev/peps/pep-0342/。
hth,
- -
罗伯特·" Stargaming" Lehmann
# 回答5


罗伯特·雷曼·施里布(Robert Lehmann Schrieb):
我会尝试的。感谢您的建议。
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - * avoir tort qu'ils ont Raison!
(coluche)
# 回答6


Paul McGuire Schrieb:
是的,我在想这样的事情。只要线/列
仅在发生错误时需要(即每个脚本运行一次),
我认为这种性能比跟踪行/列更重要
每个令牌。
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison!
(coluche)
# 回答7


11月10日,7:29*AM,Thomas Mlynarczyk
写道:
是的,我在想这样的事情。只要线/列
仅在发生错误时需要(即每个脚本运行一次),
我认为这种性能比跟踪行/列更重要
每个令牌。
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison!
(Coluche)
只需确保计算列时考虑选项卡,这是
简单的算法没有。
- 保罗
# 回答8


一些普拉特写道:
诅咒你的
# 回答9


Paul McGuire Schrieb:
我没有想到的另一件事 - 感谢您的提示。
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison!
(coluche)
# 回答10


约翰·马基(John Machin Schrieb):
是的,我会记住这一点。暂时,我只会使用
REGEXES可以使代码更简单。稍后或需要加速时需要
出现,我可以使用您的建议来优化我的代码。 de 等待
令牌,甚至可以立即使用dict查找可能会更好
正则次级是次要的,这意味着更复杂的东西。
[相互排斥的代币=无歧义=相同的输入-SAME输出]
也许是lexer。不适合用户。模棱两可的lexer将是
无用。
确切地。这与我说的话相矛盾?
[使用dict]
我 /可以 /可以用一个元组列表完成。我不使用功能
那个 /唯一的 /一个dict可以做到。所以在这里使用dict就像在使用卡车
用于运输一张纸?
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison!
(coluche)
# 回答11


11月11日,8:35*AM,Thomas Mlynarczyk
写道:
我 /可以 /可以用一个元组列表完成。我不使用功能
那个 /唯一的 /一个dict可以做到。所以在这里使用dict就像在使用卡车
用于运输一张纸?
你越来越近。一个更好的比喻是,使用dict就像
沿着飞机或
永远不会离开地面的直升机。
# 回答12


约翰·马基(John Machin Schrieb):
在飞机上运送乘客并不是一个坏主意,但是
飞机不应遵循Autobahn,而应使用最短的方式 -
在适当的高度。翻译回Python dicts,这将
意味着将dict用于我的目的是一个好主意,但我没有
利用它的完整功能 - 换句话说,我应该重写我的
代码 - 仍然使用dict,但以更好的方式。还是你的意思是10
公里的Autobahn,飞机会过大吗?
也许我对我的php背景有些偏见,但是{name:Regex,...}
对我来说看起来比[(name,Regex),...]更简单,因为前者是
不是嵌套的结构,而后者将是PHP中的2D阵列。
假设我使用dict,我想与
令牌名为" tokenname"(也就是说,没有迭代,而是一个
使用权)。我可以简单地编写Tokendict [" Tokenname"]。但是与列表
在元组中,我想不出一种同样简单的方法。但是,作为
一个初学者,我可能会低估python。
问候,
托马斯
- -
ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison!
(coluche)
# 回答13


托马斯·梅纳尔奇克(Thomas Mlynarczyk)写道:
在飞机上运送乘客并不是一个坏主意,但是
飞机不应遵循Autobahn,而应使用最短的方式 -
在适当的高度。翻译回Python dicts,这将
意味着将dict用于我的目的是一个好主意,但我没有
利用它的完整功能 - 换句话说,我应该重写我的
代码 - 仍然使用dict,但以更好的方式。还是你的意思是10
公里的Autobahn,飞机会过大吗?
后者。
但这是对象属性的问题。因为列表是
订购在您想迭代它们时使用它们是适当的
而且没有兰德 需要OM访问。
如果您需要按键随机访问,并且不需要订购特定的订购
对于迭代,您应该使用dict。
忘记"简单性",直到您知道不同对象是如何的
在引擎盖下实施。
一个好的第一条规则是简单,可读的python通常会是
高效的。就执行效率而言,如果
dict解决方案速度更快,但是即使是我仍然更喜欢
基于列表的解决方案,因为它更适合问题。
"过早的优化是万能的根源" ...
但是您什么时候想这样做呢?发明用例没有意义 -
他们应该被证明需求。
您的原始代码唯一需要使用令牌名称检索的时间
该值适用于您的compile()方法,但假设传递
令牌是[(名称,图案),...]您可以同样容易的形式
将方法扔掉,然后在__init __()写入
self.tokens = [(name,re.compile(pat))in name,pat in dokens]
或者首先简单地通过编译令牌图案
是必要的...然后呼叫者可以选择不费心
首先优化!
基于列表的方法的优点是至少允许
您可以观察到相对频率的可能性
代币在真实代码中的外观,然后优化订单以给出
最好的(平均)性能(通过将最常见的令牌放在首位)应该
令牌化成为程序热点。
用dict,您没有这样的机会,因为订购是
由实现而不是您的数据结构确定。
问候
史蒂夫
- -
史蒂夫·霍顿+1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
# 回答14


史蒂夫·霍顿·施里布(Steve Holden Schrieb):
好吧,我一直在考虑进一步减少正则数量
需要比赛。所以我想修改我的词词不给
一次输入,但仅尝试从输入中获取下一个令牌
"正好及时" /按需。为此,我正在考虑下一个()
这样的方法:
def next(self,name of expedtoken):
REGEX = self.getRegexByTokenName(namefexpedtoken)
match = regex.match(self.source,self.offset)
如果不匹配:返回false
线= self.line
self.line += match.group(0).count(" \ n")
self.offset += len(match.group(0))
返回(namefexpedtoken,匹配,行)
我不确定这是否是个好主意,但对我来说看起来像是一个好主意。这
问题是检索正则拨号的方法的第一行
与给定令牌名称相关联。使用dict,我可以简单地写
regex = self.tokendict [nameofexpedtoken]
但是有了一个列表,我想我不会没有循环。我
假设比命令更昂贵。
那将是一种选择。但是不应该是勒克斯(Lexer)照顾
在没有呼叫者的情况下,尽可能多地优化自己的工作
协助?毕竟,呼叫者不需要知道
内部工作 Lexer的GS。 [通过将最频繁的令牌放在首位来优化性能] 真的。 不过,我应该能够通过我的表现更好 上述方法使用next()函数,因为这将完全 消除所有"无用"匹配(例如试图匹配foo,没有foo 被允许)。 问候, 托马斯 - - ce n'est pas parce qu'ils sont nombreux - avoir tort qu'ils ont Raison! (coluche)

标签: python

添加新评论