PEP8 compliance, reduce munging on tagged names
This commit is contained in:
parent
9a9922a3ca
commit
2a11825779
2
bot.py
2
bot.py
|
@ -41,7 +41,7 @@ try:
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'ERROR: malformed config file', Exception, e
|
print 'ERROR: malformed config file', Exception, e
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
bot.persist_dir = os.path.abspath('persist')
|
bot.persist_dir = os.path.abspath('persist')
|
||||||
if not os.path.exists(bot.persist_dir):
|
if not os.path.exists(bot.persist_dir):
|
||||||
os.mkdir(bot.persist_dir)
|
os.mkdir(bot.persist_dir)
|
||||||
|
|
17
core/main.py
17
core/main.py
|
@ -17,7 +17,7 @@ class Input(dict):
|
||||||
conn.msg(chan, msg)
|
conn.msg(chan, msg)
|
||||||
|
|
||||||
def reply(msg):
|
def reply(msg):
|
||||||
if chan == nick: # PMs don't need prefixes
|
if chan == nick: # PMs don't need prefixes
|
||||||
conn.msg(chan, msg)
|
conn.msg(chan, msg)
|
||||||
else:
|
else:
|
||||||
conn.msg(chan, nick + ': ' + msg)
|
conn.msg(chan, nick + ': ' + msg)
|
||||||
|
@ -68,7 +68,7 @@ def do_sieve(sieve, bot, input, func, type, args):
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Handler(object):
|
class Handler(object):
|
||||||
'''Runs plugins in their own threads (ensures order)'''
|
'''Runs plugins in their own threads (ensures order)'''
|
||||||
def __init__(self, func):
|
def __init__(self, func):
|
||||||
|
@ -106,12 +106,12 @@ def dispatch(input, kind, func, args):
|
||||||
input = do_sieve(sieve, bot, input, func, kind, args)
|
input = do_sieve(sieve, bot, input, func, kind, args)
|
||||||
if input == None:
|
if input == None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if func._thread:
|
if func._thread:
|
||||||
bot.threads[func].put(input)
|
bot.threads[func].put(input)
|
||||||
else:
|
else:
|
||||||
thread.start_new_thread(run, (func, input))
|
thread.start_new_thread(run, (func, input))
|
||||||
|
|
||||||
|
|
||||||
def main(conn, out):
|
def main(conn, out):
|
||||||
inp = Input(conn, *out)
|
inp = Input(conn, *out)
|
||||||
|
@ -120,14 +120,13 @@ def main(conn, out):
|
||||||
for func, args in bot.events[inp.command] + bot.events['*']:
|
for func, args in bot.events[inp.command] + bot.events['*']:
|
||||||
dispatch(Input(conn, *out), "event", func, args)
|
dispatch(Input(conn, *out), "event", func, args)
|
||||||
|
|
||||||
|
|
||||||
if inp.command == 'PRIVMSG':
|
if inp.command == 'PRIVMSG':
|
||||||
# COMMANDS
|
# COMMANDS
|
||||||
if inp.chan == inp.nick: # private message, no command prefix
|
if inp.chan == inp.nick: # private message, no command prefix
|
||||||
prefix = r'^(?:[.!]?|'
|
prefix = r'^(?:[.!]?|'
|
||||||
else:
|
else:
|
||||||
prefix = r'^(?:[.!]|'
|
prefix = r'^(?:[.!]|'
|
||||||
|
|
||||||
command_re = prefix + inp.conn.nick
|
command_re = prefix + inp.conn.nick
|
||||||
command_re += r'[:,]*\s+)(\w+)(?:$|\s+)(.*)'
|
command_re += r'[:,]*\s+)(\w+)(?:$|\s+)(.*)'
|
||||||
|
|
||||||
|
@ -139,10 +138,10 @@ def main(conn, out):
|
||||||
input = Input(conn, *out)
|
input = Input(conn, *out)
|
||||||
input.inp_unstripped = m.group(2)
|
input.inp_unstripped = m.group(2)
|
||||||
input.inp = m.group(2).strip()
|
input.inp = m.group(2).strip()
|
||||||
|
|
||||||
func, args = bot.commands[command]
|
func, args = bot.commands[command]
|
||||||
dispatch(input, "command", func, args)
|
dispatch(input, "command", func, args)
|
||||||
|
|
||||||
# REGEXES
|
# REGEXES
|
||||||
for func, args in bot.plugs['regex']:
|
for func, args in bot.plugs['regex']:
|
||||||
m = args['re'].search(inp.lastparam)
|
m = args['re'].search(inp.lastparam)
|
||||||
|
|
|
@ -28,11 +28,9 @@ def format_plug(plug, kind='', lpad=0, width=40):
|
||||||
if kind == 'regex':
|
if kind == 'regex':
|
||||||
out += ' ' * (50 - len(out)) + plug[1]['regex']
|
out += ' ' * (50 - len(out)) + plug[1]['regex']
|
||||||
|
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def reload(init=False):
|
def reload(init=False):
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
|
@ -41,12 +39,12 @@ def reload(init=False):
|
||||||
bot.threads = {}
|
bot.threads = {}
|
||||||
|
|
||||||
core_fileset = set(glob.glob(os.path.join("core", "*.py")))
|
core_fileset = set(glob.glob(os.path.join("core", "*.py")))
|
||||||
|
|
||||||
for filename in core_fileset:
|
for filename in core_fileset:
|
||||||
mtime = os.stat(filename).st_mtime
|
mtime = os.stat(filename).st_mtime
|
||||||
if mtime != mtimes.get(filename):
|
if mtime != mtimes.get(filename):
|
||||||
mtimes[filename] = mtime
|
mtimes[filename] = mtime
|
||||||
|
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -82,7 +80,7 @@ def reload(init=False):
|
||||||
mtime = os.stat(filename).st_mtime
|
mtime = os.stat(filename).st_mtime
|
||||||
if mtime != mtimes.get(filename):
|
if mtime != mtimes.get(filename):
|
||||||
mtimes[filename] = mtime
|
mtimes[filename] = mtime
|
||||||
|
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -95,7 +93,7 @@ def reload(init=False):
|
||||||
|
|
||||||
# remove plugins already loaded from this filename
|
# remove plugins already loaded from this filename
|
||||||
for name, data in bot.plugs.iteritems():
|
for name, data in bot.plugs.iteritems():
|
||||||
bot.plugs[name] = [x for x in data
|
bot.plugs[name] = [x for x in data
|
||||||
if x[0]._filename != filename]
|
if x[0]._filename != filename]
|
||||||
|
|
||||||
for func, handler in list(bot.threads.iteritems()):
|
for func, handler in list(bot.threads.iteritems()):
|
||||||
|
@ -107,7 +105,7 @@ def reload(init=False):
|
||||||
if hasattr(obj, '_hook'): # check for magic
|
if hasattr(obj, '_hook'): # check for magic
|
||||||
if obj._thread:
|
if obj._thread:
|
||||||
bot.threads[obj] = Handler(obj)
|
bot.threads[obj] = Handler(obj)
|
||||||
|
|
||||||
for type, data in obj._hook:
|
for type, data in obj._hook:
|
||||||
bot.plugs[type] += [data]
|
bot.plugs[type] += [data]
|
||||||
|
|
||||||
|
@ -141,7 +139,7 @@ def reload(init=False):
|
||||||
if bot.commands:
|
if bot.commands:
|
||||||
# hack to make commands with multiple aliases
|
# hack to make commands with multiple aliases
|
||||||
# print nicely
|
# print nicely
|
||||||
|
|
||||||
print ' command:'
|
print ' command:'
|
||||||
commands = collections.defaultdict(list)
|
commands = collections.defaultdict(list)
|
||||||
|
|
||||||
|
@ -149,11 +147,11 @@ def reload(init=False):
|
||||||
commands[make_signature(func)].append(name)
|
commands[make_signature(func)].append(name)
|
||||||
|
|
||||||
for sig, names in sorted(commands.iteritems()):
|
for sig, names in sorted(commands.iteritems()):
|
||||||
names.sort(key=lambda x: (-len(x), x)) # long names first
|
names.sort(key=lambda x: (-len(x), x)) # long names first
|
||||||
out = ' ' * 6 + '%s:%s:%s' % sig
|
out = ' ' * 6 + '%s:%s:%s' % sig
|
||||||
out += ' ' * (50 - len(out)) + ', '.join(names)
|
out += ' ' * (50 - len(out)) + ', '.join(names)
|
||||||
print out
|
print out
|
||||||
|
|
||||||
for kind, plugs in sorted(bot.plugs.iteritems()):
|
for kind, plugs in sorted(bot.plugs.iteritems()):
|
||||||
if kind == 'command':
|
if kind == 'command':
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -10,7 +10,7 @@ from util import hook
|
||||||
api_url = "http://encyclopediadramatica.com/api.php?action=opensearch&search="
|
api_url = "http://encyclopediadramatica.com/api.php?action=opensearch&search="
|
||||||
ed_url = "http://encyclopediadramatica.com/"
|
ed_url = "http://encyclopediadramatica.com/"
|
||||||
|
|
||||||
ua_header = ('User-Agent','Skybot/1.0 http://bitbucket.org/Scaevolus/skybot/')
|
ua_header = ('User-Agent', 'Skybot/1.0 http://bitbucket.org/Scaevolus/skybot/')
|
||||||
|
|
||||||
|
|
||||||
@hook.command('ed')
|
@hook.command('ed')
|
||||||
|
@ -20,7 +20,7 @@ def drama(inp):
|
||||||
'''article on <phrase>'''
|
'''article on <phrase>'''
|
||||||
if not inp:
|
if not inp:
|
||||||
return drama.__doc__
|
return drama.__doc__
|
||||||
|
|
||||||
q = api_url + (urllib2.quote(inp, safe=''))
|
q = api_url + (urllib2.quote(inp, safe=''))
|
||||||
request = urllib2.Request(q)
|
request = urllib2.Request(q)
|
||||||
request.add_header(*ua_header)
|
request.add_header(*ua_header)
|
||||||
|
@ -28,12 +28,12 @@ def drama(inp):
|
||||||
if not j[1]:
|
if not j[1]:
|
||||||
return 'no results found'
|
return 'no results found'
|
||||||
article_name = j[1][0].replace(' ', '_')
|
article_name = j[1][0].replace(' ', '_')
|
||||||
|
|
||||||
url = ed_url + (urllib2.quote(article_name))
|
url = ed_url + (urllib2.quote(article_name))
|
||||||
request = urllib2.Request(url)
|
request = urllib2.Request(url)
|
||||||
request.add_header(*ua_header)
|
request.add_header(*ua_header)
|
||||||
page = html.fromstring(urllib2.build_opener().open(request).read())
|
page = html.fromstring(urllib2.build_opener().open(request).read())
|
||||||
|
|
||||||
for p in page.xpath('//div[@id="bodyContent"]/p'):
|
for p in page.xpath('//div[@id="bodyContent"]/p'):
|
||||||
if p.text_content():
|
if p.text_content():
|
||||||
summary = ' '.join(p.text_content().splitlines())
|
summary = ' '.join(p.text_content().splitlines())
|
||||||
|
|
|
@ -11,11 +11,12 @@ from util import hook
|
||||||
# say('(--[. ]-[ .] /')
|
# say('(--[. ]-[ .] /')
|
||||||
# say('(_______o__)')
|
# say('(_______o__)')
|
||||||
|
|
||||||
|
|
||||||
@hook.command
|
@hook.command
|
||||||
@hook.command('gs')
|
@hook.command('gs')
|
||||||
def goonsay(inp):
|
def goonsay(inp):
|
||||||
".gs/.goonsay <id|add [message]> -- Get's the goonsay.com result for <id> or "
|
".gs/.goonsay <id|add [message]> -- Get's the goonsay.com result for <id> "
|
||||||
"add a new :goonsay: to the database. If no arg it will get a random result."
|
" or add a new :goonsay: to the database. With no args, random result."
|
||||||
|
|
||||||
url = "http://goonsay.com/api/goonsays"
|
url = "http://goonsay.com/api/goonsays"
|
||||||
|
|
||||||
|
@ -44,7 +45,8 @@ def goonsay(inp):
|
||||||
|
|
||||||
if len(inp):
|
if len(inp):
|
||||||
try:
|
try:
|
||||||
req = urllib2.Request('%s/%d/' % (url, int(inp)), None, req_headers)
|
req = urllib2.Request('%s/%d/' % (url, int(inp)), None,
|
||||||
|
req_headers)
|
||||||
j = json.loads(urllib2.urlopen(req).read())
|
j = json.loads(urllib2.urlopen(req).read())
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
if e.code == 410 or e.code == 404:
|
if e.code == 410 or e.code == 404:
|
||||||
|
|
|
@ -14,7 +14,7 @@ def mem(inp):
|
||||||
status = dict(line_pairs)
|
status = dict(line_pairs)
|
||||||
keys = 'VmSize VmLib VmData VmExe VmRSS VmStk'.split()
|
keys = 'VmSize VmLib VmData VmExe VmRSS VmStk'.split()
|
||||||
return ', '.join(key + ':' + status[key] for key in keys)
|
return ', '.join(key + ':' + status[key] for key in keys)
|
||||||
|
|
||||||
elif os.name == 'nt':
|
elif os.name == 'nt':
|
||||||
cmd = "tasklist /FI \"PID eq %s\" /FO CSV /NH" % os.getpid()
|
cmd = "tasklist /FI \"PID eq %s\" /FO CSV /NH" % os.getpid()
|
||||||
out = os.popen(cmd).read()
|
out = os.popen(cmd).read()
|
||||||
|
|
|
@ -28,7 +28,6 @@ def mtg(inp):
|
||||||
text = re.sub(r'\(.*?\)', '', text) # strip parenthetical explanations
|
text = re.sub(r'\(.*?\)', '', text) # strip parenthetical explanations
|
||||||
text = re.sub(r'\.(\S)', r'. \1', text) # fix spacing
|
text = re.sub(r'\.(\S)', r'. \1', text) # fix spacing
|
||||||
|
|
||||||
|
|
||||||
printings = card.find('td/small').text_content()
|
printings = card.find('td/small').text_content()
|
||||||
printings = re.search(r'Editions:(.*)Languages:', printings).group(1)
|
printings = re.search(r'Editions:(.*)Languages:', printings).group(1)
|
||||||
printings = re.findall(r'\s*(.+?(?: \([^)]+\))*) \((.*?)\)',
|
printings = re.findall(r'\s*(.+?(?: \([^)]+\))*) \((.*?)\)',
|
||||||
|
|
|
@ -1,98 +1,98 @@
|
||||||
#-----------------------------------------------------------------
|
#-----------------------------------------------------------------
|
||||||
# pycparser: cdecl.py
|
# pycparser: cdecl.py
|
||||||
#
|
#
|
||||||
# Example of the CDECL tool using pycparser. CDECL "explains"
|
# Example of the CDECL tool using pycparser. CDECL "explains"
|
||||||
# C type declarations in plain English.
|
# C type declarations in plain English.
|
||||||
#
|
#
|
||||||
# The AST generated by pycparser from the given declaration is
|
# The AST generated by pycparser from the given declaration is
|
||||||
# traversed recursively to build the explanation.
|
# traversed recursively to build the explanation.
|
||||||
# Note that the declaration must be a valid external declaration
|
# Note that the declaration must be a valid external declaration
|
||||||
# in C. All the types used in it must be defined with typedef,
|
# in C. All the types used in it must be defined with typedef,
|
||||||
# or parsing will fail. The definition can be arbitrary, it isn't
|
# or parsing will fail. The definition can be arbitrary, it isn't
|
||||||
# really used - by pycparser must know which tokens are types.
|
# really used - by pycparser must know which tokens are types.
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
#
|
#
|
||||||
# 'typedef int Node; const Node* (*ar)[10];'
|
# 'typedef int Node; const Node* (*ar)[10];'
|
||||||
# =>
|
# =>
|
||||||
# ar is a pointer to array[10] of pointer to const Node
|
# ar is a pointer to array[10] of pointer to const Node
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008, Eli Bendersky
|
# Copyright (C) 2008, Eli Bendersky
|
||||||
# License: LGPL
|
# License: LGPL
|
||||||
#-----------------------------------------------------------------
|
#-----------------------------------------------------------------
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pycparser import c_parser, c_ast
|
from pycparser import c_parser, c_ast
|
||||||
|
|
||||||
|
|
||||||
def explain_c_declaration(c_decl):
|
def explain_c_declaration(c_decl):
|
||||||
""" Parses the declaration in c_decl and returns a text
|
""" Parses the declaration in c_decl and returns a text
|
||||||
explanation as a string.
|
explanation as a string.
|
||||||
|
|
||||||
The last external node of the string is used, to allow
|
The last external node of the string is used, to allow
|
||||||
earlier typedefs for used types.
|
earlier typedefs for used types.
|
||||||
"""
|
"""
|
||||||
parser = c_parser.CParser()
|
parser = c_parser.CParser()
|
||||||
|
|
||||||
node = parser.parse(c_decl, filename='<stdin>')
|
node = parser.parse(c_decl, filename='<stdin>')
|
||||||
|
|
||||||
if ( not isinstance(node, c_ast.FileAST) or
|
if ( not isinstance(node, c_ast.FileAST) or
|
||||||
not isinstance(node.ext[-1], c_ast.Decl)):
|
not isinstance(node.ext[-1], c_ast.Decl)):
|
||||||
return "Last external node is invalid type"
|
return "Last external node is invalid type"
|
||||||
|
|
||||||
return _explain_decl_node(node.ext[-1])
|
return _explain_decl_node(node.ext[-1])
|
||||||
|
|
||||||
|
|
||||||
def _explain_decl_node(decl_node):
|
def _explain_decl_node(decl_node):
|
||||||
""" Receives a c_ast.Decl note and returns its explanation in
|
""" Receives a c_ast.Decl note and returns its explanation in
|
||||||
English.
|
English.
|
||||||
"""
|
"""
|
||||||
#~ print decl_node.show()
|
#~ print decl_node.show()
|
||||||
storage = ' '.join(decl_node.storage) + ' ' if decl_node.storage else ''
|
storage = ' '.join(decl_node.storage) + ' ' if decl_node.storage else ''
|
||||||
|
|
||||||
return (decl_node.name +
|
return (decl_node.name +
|
||||||
" is a " +
|
" is a " +
|
||||||
storage +
|
storage +
|
||||||
_explain_type(decl_node.type))
|
_explain_type(decl_node.type))
|
||||||
|
|
||||||
|
|
||||||
def _explain_type(decl):
|
def _explain_type(decl):
|
||||||
""" Recursively explains a type decl node
|
""" Recursively explains a type decl node
|
||||||
"""
|
"""
|
||||||
typ = type(decl)
|
typ = type(decl)
|
||||||
|
|
||||||
if typ == c_ast.TypeDecl:
|
if typ == c_ast.TypeDecl:
|
||||||
quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
|
quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
|
||||||
return quals + _explain_type(decl.type)
|
return quals + _explain_type(decl.type)
|
||||||
elif typ == c_ast.Typename or typ == c_ast.Decl:
|
elif typ == c_ast.Typename or typ == c_ast.Decl:
|
||||||
return _explain_type(decl.type)
|
return _explain_type(decl.type)
|
||||||
elif typ == c_ast.IdentifierType:
|
elif typ == c_ast.IdentifierType:
|
||||||
return ' '.join(decl.names)
|
return ' '.join(decl.names)
|
||||||
elif typ == c_ast.PtrDecl:
|
elif typ == c_ast.PtrDecl:
|
||||||
quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
|
quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
|
||||||
return quals + 'pointer to ' + _explain_type(decl.type)
|
return quals + 'pointer to ' + _explain_type(decl.type)
|
||||||
elif typ == c_ast.ArrayDecl:
|
elif typ == c_ast.ArrayDecl:
|
||||||
arr = 'array'
|
arr = 'array'
|
||||||
if decl.dim: arr += '[%s]' % decl.dim.value
|
if decl.dim: arr += '[%s]' % decl.dim.value
|
||||||
|
|
||||||
return arr + " of " + _explain_type(decl.type)
|
return arr + " of " + _explain_type(decl.type)
|
||||||
|
|
||||||
elif typ == c_ast.FuncDecl:
|
elif typ == c_ast.FuncDecl:
|
||||||
if decl.args:
|
if decl.args:
|
||||||
params = [_explain_type(param) for param in decl.args.params]
|
params = [_explain_type(param) for param in decl.args.params]
|
||||||
args = ', '.join(params)
|
args = ', '.join(params)
|
||||||
else:
|
else:
|
||||||
args = ''
|
args = ''
|
||||||
|
|
||||||
return ('function(%s) returning ' % (args) +
|
return ('function(%s) returning ' % (args) +
|
||||||
_explain_type(decl.type))
|
_explain_type(decl.type))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
c_decl = sys.argv[1]
|
c_decl = sys.argv[1]
|
||||||
else:
|
else:
|
||||||
c_decl = "char *(*(**foo[][8])())[];"
|
c_decl = "char *(*(**foo[][8])())[];"
|
||||||
|
|
||||||
print "Explaining the declaration:", c_decl
|
print "Explaining the declaration:", c_decl
|
||||||
print "\n", explain_c_declaration(c_decl)
|
print "\n", explain_c_declaration(c_decl)
|
||||||
|
|
|
@ -1,75 +1,75 @@
|
||||||
#-----------------------------------------------------------------
|
#-----------------------------------------------------------------
|
||||||
# pycparser: __init__.py
|
# pycparser: __init__.py
|
||||||
#
|
#
|
||||||
# This package file exports some convenience functions for
|
# This package file exports some convenience functions for
|
||||||
# interacting with pycparser
|
# interacting with pycparser
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009, Eli Bendersky
|
# Copyright (C) 2008-2009, Eli Bendersky
|
||||||
# License: LGPL
|
# License: LGPL
|
||||||
#-----------------------------------------------------------------
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
__all__ = ['c_lexer', 'c_parser', 'c_ast']
|
__all__ = ['c_lexer', 'c_parser', 'c_ast']
|
||||||
__version__ = '1.05'
|
__version__ = '1.05'
|
||||||
|
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from types import ListType
|
from types import ListType
|
||||||
|
|
||||||
from c_parser import CParser
|
from c_parser import CParser
|
||||||
|
|
||||||
|
|
||||||
def parse_file( filename, use_cpp=False,
|
def parse_file( filename, use_cpp=False,
|
||||||
cpp_path='cpp', cpp_args=''):
|
cpp_path='cpp', cpp_args=''):
|
||||||
""" Parse a C file using pycparser.
|
""" Parse a C file using pycparser.
|
||||||
|
|
||||||
filename:
|
filename:
|
||||||
Name of the file you want to parse.
|
Name of the file you want to parse.
|
||||||
|
|
||||||
use_cpp:
|
use_cpp:
|
||||||
Set to True if you want to execute the C pre-processor
|
Set to True if you want to execute the C pre-processor
|
||||||
on the file prior to parsing it.
|
on the file prior to parsing it.
|
||||||
|
|
||||||
cpp_path:
|
cpp_path:
|
||||||
If use_cpp is True, this is the path to 'cpp' on your
|
If use_cpp is True, this is the path to 'cpp' on your
|
||||||
system. If no path is provided, it attempts to just
|
system. If no path is provided, it attempts to just
|
||||||
execute 'cpp', so it must be in your PATH.
|
execute 'cpp', so it must be in your PATH.
|
||||||
|
|
||||||
cpp_args:
|
cpp_args:
|
||||||
If use_cpp is True, set this to the command line
|
If use_cpp is True, set this to the command line
|
||||||
arguments strings to cpp. Be careful with quotes -
|
arguments strings to cpp. Be careful with quotes -
|
||||||
it's best to pass a raw string (r'') here.
|
it's best to pass a raw string (r'') here.
|
||||||
For example:
|
For example:
|
||||||
r'-I../utils/fake_libc_include'
|
r'-I../utils/fake_libc_include'
|
||||||
If several arguments are required, pass a list of
|
If several arguments are required, pass a list of
|
||||||
strings.
|
strings.
|
||||||
|
|
||||||
When successful, an AST is returned. ParseError can be
|
When successful, an AST is returned. ParseError can be
|
||||||
thrown if the file doesn't parse successfully.
|
thrown if the file doesn't parse successfully.
|
||||||
|
|
||||||
Errors from cpp will be printed out.
|
Errors from cpp will be printed out.
|
||||||
"""
|
"""
|
||||||
if use_cpp:
|
if use_cpp:
|
||||||
path_list = [cpp_path]
|
path_list = [cpp_path]
|
||||||
if isinstance(cpp_args, ListType):
|
if isinstance(cpp_args, ListType):
|
||||||
path_list += cpp_args
|
path_list += cpp_args
|
||||||
elif cpp_args != '':
|
elif cpp_args != '':
|
||||||
path_list += [cpp_args]
|
path_list += [cpp_args]
|
||||||
path_list += [filename]
|
path_list += [filename]
|
||||||
|
|
||||||
# Note the use of universal_newlines to treat all newlines
|
# Note the use of universal_newlines to treat all newlines
|
||||||
# as \n for Python's purpose
|
# as \n for Python's purpose
|
||||||
#
|
#
|
||||||
pipe = Popen( path_list,
|
pipe = Popen( path_list,
|
||||||
stdout=PIPE,
|
stdout=PIPE,
|
||||||
universal_newlines=True)
|
universal_newlines=True)
|
||||||
text = pipe.communicate()[0]
|
text = pipe.communicate()[0]
|
||||||
else:
|
else:
|
||||||
text = open(filename).read()
|
text = open(filename).read()
|
||||||
|
|
||||||
parser = CParser()
|
parser = CParser()
|
||||||
return parser.parse(text, filename)
|
return parser.parse(text, filename)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,21 +16,21 @@ from ply.lex import TOKEN
|
||||||
|
|
||||||
class CLexer(object):
|
class CLexer(object):
|
||||||
""" A lexer for the C language. After building it, set the
|
""" A lexer for the C language. After building it, set the
|
||||||
input text with input(), and call token() to get new
|
input text with input(), and call token() to get new
|
||||||
tokens.
|
tokens.
|
||||||
|
|
||||||
The public attribute filename can be set to an initial
|
The public attribute filename can be set to an initial
|
||||||
filaneme, but the lexer will update it upon #line
|
filaneme, but the lexer will update it upon #line
|
||||||
directives.
|
directives.
|
||||||
"""
|
"""
|
||||||
def __init__(self, error_func, type_lookup_func):
|
def __init__(self, error_func, type_lookup_func):
|
||||||
""" Create a new Lexer.
|
""" Create a new Lexer.
|
||||||
|
|
||||||
error_func:
|
error_func:
|
||||||
An error function. Will be called with an error
|
An error function. Will be called with an error
|
||||||
message, line and column as arguments, in case of
|
message, line and column as arguments, in case of
|
||||||
an error during lexing.
|
an error during lexing.
|
||||||
|
|
||||||
type_lookup_func:
|
type_lookup_func:
|
||||||
A type lookup function. Given a string, it must
|
A type lookup function. Given a string, it must
|
||||||
return True IFF this string is a name of a type
|
return True IFF this string is a name of a type
|
||||||
|
@ -39,7 +39,7 @@ class CLexer(object):
|
||||||
self.error_func = error_func
|
self.error_func = error_func
|
||||||
self.type_lookup_func = type_lookup_func
|
self.type_lookup_func = type_lookup_func
|
||||||
self.filename = ''
|
self.filename = ''
|
||||||
|
|
||||||
# Allow either "# line" or "# <num>" to support GCC's
|
# Allow either "# line" or "# <num>" to support GCC's
|
||||||
# cpp output
|
# cpp output
|
||||||
#
|
#
|
||||||
|
@ -47,8 +47,8 @@ class CLexer(object):
|
||||||
|
|
||||||
def build(self, **kwargs):
|
def build(self, **kwargs):
|
||||||
""" Builds the lexer from the specification. Must be
|
""" Builds the lexer from the specification. Must be
|
||||||
called after the lexer object is created.
|
called after the lexer object is created.
|
||||||
|
|
||||||
This method exists separately, because the PLY
|
This method exists separately, because the PLY
|
||||||
manual warns against calling lex.lex inside
|
manual warns against calling lex.lex inside
|
||||||
__init__
|
__init__
|
||||||
|
@ -62,13 +62,13 @@ class CLexer(object):
|
||||||
|
|
||||||
def input(self, text):
|
def input(self, text):
|
||||||
self.lexer.input(text)
|
self.lexer.input(text)
|
||||||
|
|
||||||
def token(self):
|
def token(self):
|
||||||
g = self.lexer.token()
|
g = self.lexer.token()
|
||||||
return g
|
return g
|
||||||
|
|
||||||
######################-- PRIVATE --######################
|
######################-- PRIVATE --######################
|
||||||
|
|
||||||
##
|
##
|
||||||
## Internal auxiliary methods
|
## Internal auxiliary methods
|
||||||
##
|
##
|
||||||
|
@ -76,26 +76,26 @@ class CLexer(object):
|
||||||
location = self._make_tok_location(token)
|
location = self._make_tok_location(token)
|
||||||
self.error_func(msg, location[0], location[1])
|
self.error_func(msg, location[0], location[1])
|
||||||
self.lexer.skip(1)
|
self.lexer.skip(1)
|
||||||
|
|
||||||
def _find_tok_column(self, token):
|
def _find_tok_column(self, token):
|
||||||
i = token.lexpos
|
i = token.lexpos
|
||||||
while i > 0:
|
while i > 0:
|
||||||
if self.lexer.lexdata[i] == '\n': break
|
if self.lexer.lexdata[i] == '\n': break
|
||||||
i -= 1
|
i -= 1
|
||||||
return (token.lexpos - i) + 1
|
return (token.lexpos - i) + 1
|
||||||
|
|
||||||
def _make_tok_location(self, token):
|
def _make_tok_location(self, token):
|
||||||
return (token.lineno, self._find_tok_column(token))
|
return (token.lineno, self._find_tok_column(token))
|
||||||
|
|
||||||
##
|
##
|
||||||
## Reserved keywords
|
## Reserved keywords
|
||||||
##
|
##
|
||||||
keywords = (
|
keywords = (
|
||||||
'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST', 'CONTINUE',
|
'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST', 'CONTINUE',
|
||||||
'DEFAULT', 'DO', 'DOUBLE', 'ELSE', 'ENUM', 'EXTERN',
|
'DEFAULT', 'DO', 'DOUBLE', 'ELSE', 'ENUM', 'EXTERN',
|
||||||
'FLOAT', 'FOR', 'GOTO', 'IF', 'INT', 'LONG', 'REGISTER',
|
'FLOAT', 'FOR', 'GOTO', 'IF', 'INT', 'LONG', 'REGISTER',
|
||||||
'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT',
|
'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT',
|
||||||
'SWITCH', 'TYPEDEF', 'UNION', 'UNSIGNED', 'VOID',
|
'SWITCH', 'TYPEDEF', 'UNION', 'UNSIGNED', 'VOID',
|
||||||
'VOLATILE', 'WHILE',
|
'VOLATILE', 'WHILE',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -108,35 +108,35 @@ class CLexer(object):
|
||||||
##
|
##
|
||||||
tokens = keywords + (
|
tokens = keywords + (
|
||||||
# Identifiers
|
# Identifiers
|
||||||
'ID',
|
'ID',
|
||||||
|
|
||||||
# Type identifiers (identifiers previously defined as
|
# Type identifiers (identifiers previously defined as
|
||||||
# types with typedef)
|
# types with typedef)
|
||||||
'TYPEID',
|
'TYPEID',
|
||||||
|
|
||||||
# constants
|
# constants
|
||||||
'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX',
|
'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX',
|
||||||
'FLOAT_CONST',
|
'FLOAT_CONST',
|
||||||
'CHAR_CONST',
|
'CHAR_CONST',
|
||||||
'WCHAR_CONST',
|
'WCHAR_CONST',
|
||||||
|
|
||||||
# String literals
|
# String literals
|
||||||
'STRING_LITERAL',
|
'STRING_LITERAL',
|
||||||
'WSTRING_LITERAL',
|
'WSTRING_LITERAL',
|
||||||
|
|
||||||
# Operators
|
# Operators
|
||||||
'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD',
|
'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD',
|
||||||
'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT',
|
'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT',
|
||||||
'LOR', 'LAND', 'LNOT',
|
'LOR', 'LAND', 'LNOT',
|
||||||
'LT', 'LE', 'GT', 'GE', 'EQ', 'NE',
|
'LT', 'LE', 'GT', 'GE', 'EQ', 'NE',
|
||||||
|
|
||||||
# Assignment
|
# Assignment
|
||||||
'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL',
|
'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL',
|
||||||
'PLUSEQUAL', 'MINUSEQUAL',
|
'PLUSEQUAL', 'MINUSEQUAL',
|
||||||
'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL',
|
'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL',
|
||||||
'OREQUAL',
|
'OREQUAL',
|
||||||
|
|
||||||
# Increment/decrement
|
# Increment/decrement
|
||||||
'PLUSPLUS', 'MINUSMINUS',
|
'PLUSPLUS', 'MINUSMINUS',
|
||||||
|
|
||||||
# Structure dereference (->)
|
# Structure dereference (->)
|
||||||
|
@ -144,18 +144,18 @@ class CLexer(object):
|
||||||
|
|
||||||
# Conditional operator (?)
|
# Conditional operator (?)
|
||||||
'CONDOP',
|
'CONDOP',
|
||||||
|
|
||||||
# Delimeters
|
# Delimeters
|
||||||
'LPAREN', 'RPAREN', # ( )
|
'LPAREN', 'RPAREN', # ( )
|
||||||
'LBRACKET', 'RBRACKET', # [ ]
|
'LBRACKET', 'RBRACKET', # [ ]
|
||||||
'LBRACE', 'RBRACE', # { }
|
'LBRACE', 'RBRACE', # { }
|
||||||
'COMMA', 'PERIOD', # . ,
|
'COMMA', 'PERIOD', # . ,
|
||||||
'SEMI', 'COLON', # ; :
|
'SEMI', 'COLON', # ; :
|
||||||
|
|
||||||
# Ellipsis (...)
|
# Ellipsis (...)
|
||||||
'ELLIPSIS',
|
'ELLIPSIS',
|
||||||
|
|
||||||
# pre-processor
|
# pre-processor
|
||||||
'PPHASH', # '#'
|
'PPHASH', # '#'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ class CLexer(object):
|
||||||
decimal_constant = '(0'+integer_suffix_opt+')|([1-9][0-9]*'+integer_suffix_opt+')'
|
decimal_constant = '(0'+integer_suffix_opt+')|([1-9][0-9]*'+integer_suffix_opt+')'
|
||||||
octal_constant = '0[0-7]*'+integer_suffix_opt
|
octal_constant = '0[0-7]*'+integer_suffix_opt
|
||||||
hex_constant = '0[xX][0-9a-fA-F]+'+integer_suffix_opt
|
hex_constant = '0[xX][0-9a-fA-F]+'+integer_suffix_opt
|
||||||
|
|
||||||
bad_octal_constant = '0[0-7]*[89]'
|
bad_octal_constant = '0[0-7]*[89]'
|
||||||
|
|
||||||
# character constants (K&R2: A.2.5.2)
|
# character constants (K&R2: A.2.5.2)
|
||||||
|
@ -185,14 +185,14 @@ class CLexer(object):
|
||||||
bad_escape = r"""([\\][^a-zA-Z\\?'"x0-7])"""
|
bad_escape = r"""([\\][^a-zA-Z\\?'"x0-7])"""
|
||||||
|
|
||||||
escape_sequence = r"""(\\("""+simple_escape+'|'+octal_escape+'|'+hex_escape+'))'
|
escape_sequence = r"""(\\("""+simple_escape+'|'+octal_escape+'|'+hex_escape+'))'
|
||||||
cconst_char = r"""([^'\\\n]|"""+escape_sequence+')'
|
cconst_char = r"""([^'\\\n]|"""+escape_sequence+')'
|
||||||
char_const = "'"+cconst_char+"'"
|
char_const = "'"+cconst_char+"'"
|
||||||
wchar_const = 'L'+char_const
|
wchar_const = 'L'+char_const
|
||||||
unmatched_quote = "('"+cconst_char+"*\\n)|('"+cconst_char+"*$)"
|
unmatched_quote = "('"+cconst_char+"*\\n)|('"+cconst_char+"*$)"
|
||||||
bad_char_const = r"""('"""+cconst_char+"""[^'\n]+')|('')|('"""+bad_escape+r"""[^'\n]*')"""
|
bad_char_const = r"""('"""+cconst_char+"""[^'\n]+')|('')|('"""+bad_escape+r"""[^'\n]*')"""
|
||||||
|
|
||||||
# string literals (K&R2: A.2.6)
|
# string literals (K&R2: A.2.6)
|
||||||
string_char = r"""([^"\\\n]|"""+escape_sequence+')'
|
string_char = r"""([^"\\\n]|"""+escape_sequence+')'
|
||||||
string_literal = '"'+string_char+'*"'
|
string_literal = '"'+string_char+'*"'
|
||||||
wstring_literal = 'L'+string_literal
|
wstring_literal = 'L'+string_literal
|
||||||
bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"'
|
bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"'
|
||||||
|
@ -207,15 +207,15 @@ class CLexer(object):
|
||||||
##
|
##
|
||||||
states = (
|
states = (
|
||||||
# ppline: preprocessor line directives
|
# ppline: preprocessor line directives
|
||||||
#
|
#
|
||||||
('ppline', 'exclusive'),
|
('ppline', 'exclusive'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def t_PPHASH(self, t):
|
def t_PPHASH(self, t):
|
||||||
r'[ \t]*\#'
|
r'[ \t]*\#'
|
||||||
m = self.line_pattern.match(
|
m = self.line_pattern.match(
|
||||||
t.lexer.lexdata, pos=t.lexer.lexpos)
|
t.lexer.lexdata, pos=t.lexer.lexpos)
|
||||||
|
|
||||||
if m:
|
if m:
|
||||||
t.lexer.begin('ppline')
|
t.lexer.begin('ppline')
|
||||||
self.pp_line = self.pp_filename = None
|
self.pp_line = self.pp_filename = None
|
||||||
|
@ -223,7 +223,7 @@ class CLexer(object):
|
||||||
else:
|
else:
|
||||||
t.type = 'PPHASH'
|
t.type = 'PPHASH'
|
||||||
return t
|
return t
|
||||||
|
|
||||||
##
|
##
|
||||||
## Rules for the ppline state
|
## Rules for the ppline state
|
||||||
##
|
##
|
||||||
|
@ -246,21 +246,21 @@ class CLexer(object):
|
||||||
|
|
||||||
def t_ppline_NEWLINE(self, t):
|
def t_ppline_NEWLINE(self, t):
|
||||||
r'\n'
|
r'\n'
|
||||||
|
|
||||||
if self.pp_line is None:
|
if self.pp_line is None:
|
||||||
self._error('line number missing in #line', t)
|
self._error('line number missing in #line', t)
|
||||||
else:
|
else:
|
||||||
self.lexer.lineno = int(self.pp_line)
|
self.lexer.lineno = int(self.pp_line)
|
||||||
|
|
||||||
if self.pp_filename is not None:
|
if self.pp_filename is not None:
|
||||||
self.filename = self.pp_filename
|
self.filename = self.pp_filename
|
||||||
|
|
||||||
t.lexer.begin('INITIAL')
|
t.lexer.begin('INITIAL')
|
||||||
|
|
||||||
def t_ppline_PPLINE(self, t):
|
def t_ppline_PPLINE(self, t):
|
||||||
r'line'
|
r'line'
|
||||||
pass
|
pass
|
||||||
|
|
||||||
t_ppline_ignore = ' \t'
|
t_ppline_ignore = ' \t'
|
||||||
|
|
||||||
def t_ppline_error(self, t):
|
def t_ppline_error(self, t):
|
||||||
|
@ -336,8 +336,8 @@ class CLexer(object):
|
||||||
t_ELLIPSIS = r'\.\.\.'
|
t_ELLIPSIS = r'\.\.\.'
|
||||||
|
|
||||||
t_STRING_LITERAL = string_literal
|
t_STRING_LITERAL = string_literal
|
||||||
|
|
||||||
# The following floating and integer constants are defined as
|
# The following floating and integer constants are defined as
|
||||||
# functions to impose a strict order (otherwise, decimal
|
# functions to impose a strict order (otherwise, decimal
|
||||||
# is placed before the others because its regex is longer,
|
# is placed before the others because its regex is longer,
|
||||||
# and this is bad)
|
# and this is bad)
|
||||||
|
@ -363,17 +363,17 @@ class CLexer(object):
|
||||||
def t_INT_CONST_DEC(self, t):
|
def t_INT_CONST_DEC(self, t):
|
||||||
return t
|
return t
|
||||||
|
|
||||||
# Must come before bad_char_const, to prevent it from
|
# Must come before bad_char_const, to prevent it from
|
||||||
# catching valid char constants as invalid
|
# catching valid char constants as invalid
|
||||||
#
|
#
|
||||||
@TOKEN(char_const)
|
@TOKEN(char_const)
|
||||||
def t_CHAR_CONST(self, t):
|
def t_CHAR_CONST(self, t):
|
||||||
return t
|
return t
|
||||||
|
|
||||||
@TOKEN(wchar_const)
|
@TOKEN(wchar_const)
|
||||||
def t_WCHAR_CONST(self, t):
|
def t_WCHAR_CONST(self, t):
|
||||||
return t
|
return t
|
||||||
|
|
||||||
@TOKEN(unmatched_quote)
|
@TOKEN(unmatched_quote)
|
||||||
def t_UNMATCHED_QUOTE(self, t):
|
def t_UNMATCHED_QUOTE(self, t):
|
||||||
msg = "Unmatched '"
|
msg = "Unmatched '"
|
||||||
|
@ -387,23 +387,23 @@ class CLexer(object):
|
||||||
@TOKEN(wstring_literal)
|
@TOKEN(wstring_literal)
|
||||||
def t_WSTRING_LITERAL(self, t):
|
def t_WSTRING_LITERAL(self, t):
|
||||||
return t
|
return t
|
||||||
|
|
||||||
# unmatched string literals are caught by the preprocessor
|
# unmatched string literals are caught by the preprocessor
|
||||||
|
|
||||||
@TOKEN(bad_string_literal)
|
@TOKEN(bad_string_literal)
|
||||||
def t_BAD_STRING_LITERAL(self, t):
|
def t_BAD_STRING_LITERAL(self, t):
|
||||||
msg = "String contains invalid escape code"
|
msg = "String contains invalid escape code"
|
||||||
self._error(msg, t)
|
self._error(msg, t)
|
||||||
|
|
||||||
@TOKEN(identifier)
|
@TOKEN(identifier)
|
||||||
def t_ID(self, t):
|
def t_ID(self, t):
|
||||||
t.type = self.keyword_map.get(t.value, "ID")
|
t.type = self.keyword_map.get(t.value, "ID")
|
||||||
|
|
||||||
if t.type == 'ID' and self.type_lookup_func(t.value):
|
if t.type == 'ID' and self.type_lookup_func(t.value):
|
||||||
t.type = "TYPEID"
|
t.type = "TYPEID"
|
||||||
|
|
||||||
return t
|
return t
|
||||||
|
|
||||||
def t_error(self, t):
|
def t_error(self, t):
|
||||||
msg = 'Illegal character %s' % repr(t.value[0])
|
msg = 'Illegal character %s' % repr(t.value[0])
|
||||||
self._error(msg, t)
|
self._error(msg, t)
|
||||||
|
@ -412,32 +412,32 @@ class CLexer(object):
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
filename = '../zp.c'
|
filename = '../zp.c'
|
||||||
text = open(filename).read()
|
text = open(filename).read()
|
||||||
|
|
||||||
#~ text = '"'+r"""ka \p ka"""+'"'
|
#~ text = '"'+r"""ka \p ka"""+'"'
|
||||||
text = r"""
|
text = r"""
|
||||||
546
|
546
|
||||||
#line 66 "kwas\df.h"
|
#line 66 "kwas\df.h"
|
||||||
id 4
|
id 4
|
||||||
# 5
|
# 5
|
||||||
dsf
|
dsf
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def errfoo(msg, a, b):
|
def errfoo(msg, a, b):
|
||||||
print msg
|
print msg
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
def typelookup(namd):
|
def typelookup(namd):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
clex = CLexer(errfoo, typelookup)
|
clex = CLexer(errfoo, typelookup)
|
||||||
clex.build()
|
clex.build()
|
||||||
clex.input(text)
|
clex.input(text)
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
tok = clex.token()
|
tok = clex.token()
|
||||||
if not tok: break
|
if not tok: break
|
||||||
|
|
||||||
#~ print type(tok)
|
#~ print type(tok)
|
||||||
print "-", tok.value, tok.type, tok.lineno, clex.filename, tok.lexpos
|
print "-", tok.value, tok.type, tok.lineno, clex.filename, tok.lexpos
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,67 +1,67 @@
|
||||||
#-----------------------------------------------------------------
|
#-----------------------------------------------------------------
|
||||||
# plyparser.py
|
# plyparser.py
|
||||||
#
|
#
|
||||||
# PLYParser class and other utilites for simplifying programming
|
# PLYParser class and other utilites for simplifying programming
|
||||||
# parsers with PLY
|
# parsers with PLY
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009, Eli Bendersky
|
# Copyright (C) 2008-2009, Eli Bendersky
|
||||||
# License: LGPL
|
# License: LGPL
|
||||||
#-----------------------------------------------------------------
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class Coord(object):
|
class Coord(object):
|
||||||
""" Coordinates of a syntactic element. Consists of:
|
""" Coordinates of a syntactic element. Consists of:
|
||||||
- File name
|
- File name
|
||||||
- Line number
|
- Line number
|
||||||
- (optional) column number, for the Lexer
|
- (optional) column number, for the Lexer
|
||||||
"""
|
"""
|
||||||
def __init__(self, file, line, column=None):
|
def __init__(self, file, line, column=None):
|
||||||
self.file = file
|
self.file = file
|
||||||
self.line = line
|
self.line = line
|
||||||
self.column = column
|
self.column = column
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
str = "%s:%s" % (self.file, self.line)
|
str = "%s:%s" % (self.file, self.line)
|
||||||
if self.column: str += ":%s" % self.column
|
if self.column: str += ":%s" % self.column
|
||||||
return str
|
return str
|
||||||
|
|
||||||
|
|
||||||
class ParseError(Exception): pass
|
class ParseError(Exception): pass
|
||||||
|
|
||||||
|
|
||||||
class PLYParser(object):
|
class PLYParser(object):
|
||||||
def _create_opt_rule(self, rulename):
|
def _create_opt_rule(self, rulename):
|
||||||
""" Given a rule name, creates an optional ply.yacc rule
|
""" Given a rule name, creates an optional ply.yacc rule
|
||||||
for it. The name of the optional rule is
|
for it. The name of the optional rule is
|
||||||
<rulename>_opt
|
<rulename>_opt
|
||||||
"""
|
"""
|
||||||
optname = rulename + '_opt'
|
optname = rulename + '_opt'
|
||||||
|
|
||||||
def optrule(self, p):
|
def optrule(self, p):
|
||||||
p[0] = p[1]
|
p[0] = p[1]
|
||||||
|
|
||||||
optrule.__doc__ = '%s : empty\n| %s' % (optname, rulename)
|
optrule.__doc__ = '%s : empty\n| %s' % (optname, rulename)
|
||||||
optrule.__name__ = 'p_%s' % optname
|
optrule.__name__ = 'p_%s' % optname
|
||||||
setattr(self.__class__, optrule.__name__, optrule)
|
setattr(self.__class__, optrule.__name__, optrule)
|
||||||
|
|
||||||
def _coord(self, lineno, column=None):
|
def _coord(self, lineno, column=None):
|
||||||
return Coord(
|
return Coord(
|
||||||
file=self.clex.filename,
|
file=self.clex.filename,
|
||||||
line=lineno,
|
line=lineno,
|
||||||
column=column)
|
column=column)
|
||||||
|
|
||||||
def _parse_error(self, msg, coord):
|
def _parse_error(self, msg, coord):
|
||||||
raise ParseError("%s: %s" % (coord, msg))
|
raise ParseError("%s: %s" % (coord, msg))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
pp = PLYParser()
|
pp = PLYParser()
|
||||||
pp._create_opt_rule('java')
|
pp._create_opt_rule('java')
|
||||||
|
|
||||||
ar = [4, 6]
|
ar = [4, 6]
|
||||||
pp.p_java_opt(ar)
|
pp.p_java_opt(ar)
|
||||||
|
|
||||||
print ar
|
print ar
|
||||||
print pp.p_java_opt.__doc__
|
print pp.p_java_opt.__doc__
|
||||||
|
|
||||||
print dir(pp)
|
print dir(pp)
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@ from util import hook
|
||||||
|
|
||||||
|
|
||||||
@hook.sieve
|
@hook.sieve
|
||||||
def sieve_suite(bot, input, func, kind, args):
|
def sieve_suite(bot, input, func, kind, args):
|
||||||
if input.command == 'PRIVMSG' and input.nick.lower()[-3:] == 'bot' \
|
if input.command == 'PRIVMSG' and input.nick.lower()[-3:] == 'bot' \
|
||||||
and args.get('ignorebots', True):
|
and args.get('ignorebots', True):
|
||||||
return None
|
return None
|
||||||
|
@ -17,5 +17,5 @@ def sieve_suite(bot, input, func, kind, args):
|
||||||
denied_channels = map(unicode.lower, acl['allow-except'])
|
denied_channels = map(unicode.lower, acl['allow-except'])
|
||||||
if input.chan.lower() in denied_channels:
|
if input.chan.lower() in denied_channels:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return input
|
return input
|
||||||
|
|
|
@ -24,20 +24,20 @@ def add_tag(db, chan, nick, subject):
|
||||||
(nick, chan, subject)).fetchall()
|
(nick, chan, subject)).fetchall()
|
||||||
if match:
|
if match:
|
||||||
return 'already tagged'
|
return 'already tagged'
|
||||||
|
|
||||||
db.execute('replace into tag(chan, subject, nick) values(?,?,?)',
|
db.execute('replace into tag(chan, subject, nick) values(?,?,?)',
|
||||||
(chan, subject, nick))
|
(chan, subject, nick))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
return 'tag added'
|
return 'tag added'
|
||||||
|
|
||||||
|
|
||||||
def delete_tag(db, chan, nick, del_tag):
|
def delete_tag(db, chan, nick, del_tag):
|
||||||
count = db.execute('delete from tag where lower(nick)=lower(?) and'
|
count = db.execute('delete from tag where lower(nick)=lower(?) and'
|
||||||
' chan=? and lower(subject)=lower(?)',
|
' chan=? and lower(subject)=lower(?)',
|
||||||
(nick, chan, del_tag)).rowcount
|
(nick, chan, del_tag)).rowcount
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
if count:
|
if count:
|
||||||
return 'deleted'
|
return 'deleted'
|
||||||
else:
|
else:
|
||||||
|
@ -69,7 +69,7 @@ def get_nicks_by_tag(db, chan, subject):
|
||||||
nicks = db.execute("select nick from tag where lower(subject)=lower(?)"
|
nicks = db.execute("select nick from tag where lower(subject)=lower(?)"
|
||||||
" and chan=?"
|
" and chan=?"
|
||||||
" order by lower(nick)", (subject, chan)).fetchall()
|
" order by lower(nick)", (subject, chan)).fetchall()
|
||||||
|
|
||||||
nicks = [munge(x[0], 3) for x in nicks]
|
nicks = [munge(x[0], 3) for x in nicks]
|
||||||
if not nicks:
|
if not nicks:
|
||||||
return 'tag not found'
|
return 'tag not found'
|
||||||
|
@ -108,9 +108,9 @@ def tag(inp, chan='', db=None):
|
||||||
if not tags:
|
if not tags:
|
||||||
return get_nicks_by_tag(db, chan, inp)
|
return get_nicks_by_tag(db, chan, inp)
|
||||||
else:
|
else:
|
||||||
return 'tags for "%s": ' % munge(inp, 3) + ', '.join(
|
return 'tags for "%s": ' % munge(inp, 1) + ', '.join(
|
||||||
tag[0] for tag in tags)
|
tag[0] for tag in tags)
|
||||||
|
|
||||||
|
|
||||||
character_replacements = {
|
character_replacements = {
|
||||||
'a': 'ä',
|
'a': 'ä',
|
||||||
|
|
|
@ -36,7 +36,8 @@ def tellinput(paraml, input=None, db=None, bot=None):
|
||||||
user_from, message, time, chan = tells[0]
|
user_from, message, time, chan = tells[0]
|
||||||
reltime = timesince.timesince(time)
|
reltime = timesince.timesince(time)
|
||||||
|
|
||||||
reply = "%s said %s ago in %s: %s" % (user_from, reltime, chan, message)
|
reply = "%s said %s ago in %s: %s" % (user_from, reltime, chan,
|
||||||
|
message)
|
||||||
if len(tells) > 1:
|
if len(tells) > 1:
|
||||||
reply += " (+%d more, .showtells to view)" % (len(tells) - 1)
|
reply += " (+%d more, .showtells to view)" % (len(tells) - 1)
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,10 @@ def _hook_add(func, add, name=''):
|
||||||
args.append(0) # means kwargs present
|
args.append(0) # means kwargs present
|
||||||
func._args = args
|
func._args = args
|
||||||
|
|
||||||
if not hasattr(func, '_thread'): # does function run in its own thread?
|
if not hasattr(func, '_thread'): # does function run in its own thread?
|
||||||
func._thread = False
|
func._thread = False
|
||||||
|
|
||||||
|
|
||||||
def sieve(func):
|
def sieve(func):
|
||||||
if func.func_code.co_argcount != 5:
|
if func.func_code.co_argcount != 5:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -86,7 +87,7 @@ def singlethread(func):
|
||||||
|
|
||||||
def regex(regex, flags=0, **kwargs):
|
def regex(regex, flags=0, **kwargs):
|
||||||
args = kwargs
|
args = kwargs
|
||||||
|
|
||||||
def regex_wrapper(func):
|
def regex_wrapper(func):
|
||||||
args['name'] = func.func_name
|
args['name'] = func.func_name
|
||||||
args['regex'] = regex
|
args['regex'] = regex
|
||||||
|
|
Loading…
Reference in New Issue