Add paren.py module (shows precedence of expressions by adding parentheses)

TODO: Add 'show_nick' factoid/module key so nickname logic doesn't need to be
      added to module sources
This commit is contained in:
Pragmatic Software 2013-11-14 06:29:22 +00:00
parent 155c01f8f2
commit 805215ce81
5 changed files with 429 additions and 2 deletions

View File

@ -13,8 +13,8 @@ use warnings;
# These are set automatically by the build/commit script
use constant {
BUILD_NAME => "PBot",
BUILD_REVISION => 461,
BUILD_DATE => "2013-10-27",
BUILD_REVISION => 463,
BUILD_DATE => "2013-11-13",
};
1;

1
modules/paren/INSTALL Normal file
View File

@ -0,0 +1 @@
pip install 'pycparser==2.10'

71
modules/paren/paren.py Executable file
View File

@ -0,0 +1,71 @@
#!/usr/bin/env python
from __future__ import print_function
import sys
from pycparser import c_parser, c_generator, c_ast, plyparser
from pycparser.ply import yacc
with open("paren/stddef") as f:
STDDEF = f.read()
class CParser(c_parser.CParser):
def __init__(self, *a, **kw):
super(CParser, self).__init__(*a, **kw)
self.p_expression_hack = self._expression_hack
self.cparser = yacc.yacc(
module=self,
start='expression_hack',
debug=kw.get('yacc_debug', False),
errorlog=yacc.NullLogger(),
optimize=kw.get('yacc_optimize', True),
tabmodule=kw.get('yacctab', 'yacctab'))
def parse(self, text, filename='', debuglevel=0):
self.clex.filename = filename
self.clex.reset_lineno()
self._scope_stack = [dict()]
self._last_yielded_token = None
for name in STDDEF.split('\n'):
if name:
self._add_typedef_name(name, None)
return self.cparser.parse(
input=text,
lexer=self.clex,
debug=debuglevel)
def _expression_hack(self, p):
""" expression_hack : translation_unit expression
| expression
"""
p[0] = c_ast.ExprList([p[2] if len(p) == 3 else p[1]])
class CGenerator(c_generator.CGenerator):
def visit_UnaryOp(self, n):
# don't parenthesize an operand to sizeof if it's not a type
if n.op == 'sizeof':
if isinstance(n.expr, c_ast.Typename):
return 'sizeof (%s)' % self.visit(n.expr)
else:
return 'sizeof %s' % self._parenthesize_unless_simple(n.expr)
return super(CGenerator, self).visit_UnaryOp(n)
def translate_to_c(input):
parser = CParser(yacc_optimize=False)
try:
ast = parser.parse(input, '<input>')
except plyparser.ParseError as e:
print(sys.argv[1] + ': ' + "Error: {0}".format(e.args[0]))
return
generator = CGenerator()
print(sys.argv[1] + ': ' + generator.visit(ast))
if __name__ == "__main__":
if len(sys.argv) > 2:
translate_to_c(' '.join(sys.argv[2:]))
else:
print(sys.argv[1] + ': ' + "Usage: paren <expression>")

67
modules/paren/stddef Normal file
View File

@ -0,0 +1,67 @@
FILE
bool
caddr_t
clock_t
clockid_t
cookie_close_function_t
cookie_io_functions_t
cookie_read_function_t
cookie_seek_function_t
cookie_write_function_t
daddr_t
dev_t
div_t
fd_mask
fpos_t
gid_t
ino_t
int16_t
int32_t
int64_t
int8_t
jmp_buf
key_t
ldiv_t
lldiv_t
mbstate_t
mode_t
nlink_t
off_t
pid_t
pthread_attr_t
pthread_barrier_t
pthread_barrierattr_t
pthread_cond_t
pthread_condattr_t
pthread_key_t
pthread_mutex_t
pthread_mutexattr_t
pthread_once_t
pthread_rwlock_t
pthread_rwlockattr_t
pthread_spinlock_t
pthread_t
ptrdiff_t
sem_t
sig_atomic_t
sigset_t
size_t
ssize_t
suseconds_t
time_t
timer_t
u_char
u_int
u_long
u_short
uid_t
uint
uint16_t
uint32_t
uint64_t
uint8_t
useconds_t
ushort
va_list
wchar_t
wint_t

288
modules/paren/yacctab.py Normal file

File diff suppressed because one or more lines are too long