self.content = content
def __repr__(self):
if self.type_ == 'constant':
- return ' '.join(['%02x' % ord(x) for x in self.content])
+ return ' '.join(['%02x' % maybe_ord(x) for x in self.content])
elif self.content:
return "%s(%s)" % (self.type_, self.content)
else:
content = parse_choice()
must_match(')')
else:
- print token
+ print(token)
fatal('syntax error expecting item')
n = 1
or items[0].type_ != 'constant'
or len(items[0].content) != 1):
fatal("choice must begin with xx (or 'else')")
- choice = '%02x' % ord(items[0].content)
+ choice = '%02x' % maybe_ord(items[0].content)
if choice in choices:
fatal("duplicate choice %s" % choice)
else:
n_stars += 1
- print "%s%s %s%s%s;" % (indent, typename, '*' * n_stars,
+ print("%s%s %s%s%s;" % (indent, typename, '*' * n_stars,
name_to_id(item.name),
- array_suffix)
+ array_suffix))
elif item.type_ in ('v1', 'v3', 'vAF', 'vB0',
'count', 'becount', '()'):
print_members(item.content, indent)
for choice in item.content:
print_members(choice, indent)
elif item.type_ == 'case':
- print "%sint %s;" % (indent, item.name)
- print "%sunion {" % indent
+ print("%sint %s;" % (indent, item.name))
+ print("%sunion {" % indent)
for name, choice in sorted(item.content.items()):
- print "%s struct {" % indent
+ print("%s struct {" % indent)
print_members(choice, indent + ' ' * 8)
- print "%s } %s;" % (indent, name)
- print "%s};" % indent
+ print("%s } %s;" % (indent, name))
+ print("%s};" % indent)
elif item.type_ == 'constant':
if item.name:
- print "%sbool %s;" % (indent, item.name)
+ print("%sbool %s;" % (indent, item.name))
elif item.type_ not in ("constant", "variable"):
fatal("unhandled type %s" % item.type_)
+def maybe_ord(x):
+ """
+ In Python 2, the elements of byte strings b'asdf' are char.
+ In Python 3, the elements are int.
+ This converts chars to ints.
+ """
+ return x if type(x) is int else ord(x)
+
+
def bytes_to_hex(s):
- return ''.join(['"'] + ["\\x%02x" % ord(x) for x in s] + ['"'])
+ return ''.join(['"'] + ["\\x%02x" % maybe_ord(x) for x in s] + ['"'])
class Parser_Context(object):
return '%s%d' % (prefix, n) if n > 1 else prefix
def save_pos(self, indent):
pos = self.gen_name('pos')
- print "%sstruct spvbin_position %s = spvbin_position_save (input);" % (indent, pos)
+ print("%sstruct spvbin_position %s = spvbin_position_save (input);" % (indent, pos))
return pos
def save_error(self, indent):
error = self.gen_name('save_n_errors')
- print "%ssize_t %s = input->n_errors;" % (indent, error)
+ print("%ssize_t %s = input->n_errors;" % (indent, error))
return error
def parse_limit(self, endian, indent):
limit = self.gen_name('saved_limit')
- print """\
+ print("""\
%sstruct spvbin_limit %s;
%sif (!spvbin_limit_parse%s (&%s, input))
%s goto %s;""" % (
indent, limit,
indent, '_be' if endian == 'big' else '', limit,
- indent, self.bail)
+ indent, self.bail))
return limit
item = production[item_idx]
if item.type_ == 'constant':
- print """%sif (!spvbin_match_bytes (input, %s, %d))
+ print("""%sif (!spvbin_match_bytes (input, %s, %d))
%s goto %s;""" % (
indent, bytes_to_hex(item.content), len(item.content),
- indent, ctx.bail)
+ indent, ctx.bail))
ctx.need_error_handler = True
if item.name:
- print "%sp->%s = true;" % (indent, item.name)
+ print("%sp->%s = true;" % (indent, item.name))
elif item.type_ == 'variable':
if item.content[0] == 'nonterminal':
func = '%sparse_%s' % (prefix, name_to_id(item.content[1]))
else:
dst = "NULL"
if item.n == 1:
- print """%sif (!%s (input, %s))
+ print("""%sif (!%s (input, %s))
%s goto %s;""" % (indent, func, dst,
- indent, ctx.bail)
+ indent, ctx.bail))
if item.content[0] != 'nonterminal' and item.name == 'version':
- print "%sinput->version = p->%s%s;" % (
- indent, accessor, name_to_id(item.name))
+ print("%sinput->version = p->%s%s;" % (
+ indent, accessor, name_to_id(item.name)))
else:
if isinstance(item.n, int):
count = item.n
i_name = ctx.gen_name('i')
if item.name:
if not isinstance(item.n, int):
- print "%sp->%s%s = xcalloc (%s, sizeof *p->%s%s);" % (
+ print("%sp->%s%s = xcalloc (%s, sizeof *p->%s%s);" % (
indent,
accessor, name_to_id(item.name), count,
- accessor, name_to_id(item.name))
+ accessor, name_to_id(item.name)))
dst += '[%s]' % i_name
- print "%sfor (int %s = 0; %s < %s; %s++)" % (
- indent, i_name, i_name, count, i_name)
- print """%s if (!%s (input, %s))
+ print("%sfor (int %s = 0; %s < %s; %s++)" % (
+ indent, i_name, i_name, count, i_name))
+ print("""%s if (!%s (input, %s))
%s goto %s;""" % (indent, func, dst,
- indent, ctx.bail)
+ indent, ctx.bail))
ctx.need_error_handler = True
elif item.type_ == '()':
# Not yet implemented
raise AssertionError
- print "%sif (input->version == 0x%s) {" % (indent, item.type_[1:])
+ print("%sif (input->version == 0x%s) {" % (indent, item.type_[1:]))
print_parser_items(name, item.content, indent + ' ', accessor, ctx)
- print "%s}" % indent
+ print("%s}" % indent)
elif item.type_ in ('count', 'becount'):
if item.n != 1:
# Not yet implemented
save_bail = ctx.bail
ctx.bail = ctx.gen_name('backtrack')
- print "%sdo {" % indent
+ print("%sdo {" % indent)
indent += ' '
if (item.content
and item.content[-1].type_ == 'variable'
print_parser_items(name, content, indent, accessor, ctx)
if ellipsis:
- print "%sinput->ofs = input->size;" % indent
+ print("%sinput->ofs = input->size;" % indent)
else:
- print """%sif (!spvbin_input_at_end (input))
+ print("""%sif (!spvbin_input_at_end (input))
%s goto %s;""" % (indent,
- indent, ctx.bail)
- print '%sspvbin_limit_pop (&%s, input);' % (indent, limit)
- print '%sbreak;' % indent
- print
- print '%s%s:' % (indent[4:], ctx.bail)
+ indent, ctx.bail))
+ print('%sspvbin_limit_pop (&%s, input);' % (indent, limit))
+ print('%sbreak;' % indent)
+ print('')
+ print('%s%s:' % (indent[4:], ctx.bail))
# In theory, we should emit code to clear whatever we're
# backtracking from. In practice, it's not important to
# do that.
- print "%sspvbin_position_restore (&%s, input);" % (indent, pos)
- print '%sspvbin_limit_pop (&%s, input);' % (indent, limit)
- print '%sgoto %s;' % (indent, save_bail)
+ print("%sspvbin_position_restore (&%s, input);" % (indent, pos))
+ print('%sspvbin_limit_pop (&%s, input);' % (indent, limit))
+ print('%sgoto %s;' % (indent, save_bail))
indent = indent[4:]
- print "%s} while (0);" % indent
+ print("%s} while (0);" % indent)
ctx.bail = save_bail
elif item.type_ == '|':
save_bail = ctx.bail
- print "%sdo {" % indent
+ print("%sdo {" % indent)
indent += ' '
pos = ctx.save_pos(indent)
error = ctx.save_error(indent)
i = 0
for choice in item.content:
if i:
- print "%sspvbin_position_restore (&%s, input);" % (indent, pos)
- print "%sinput->n_errors = %s;" % (indent, error)
+ print("%sspvbin_position_restore (&%s, input);" % (indent, pos))
+ print("%sinput->n_errors = %s;" % (indent, error))
i += 1
if i != len(item.content):
else:
ctx.bail = save_bail
print_parser_items(name, choice, indent, accessor, ctx)
- print "%sbreak;" % indent
+ print("%sbreak;" % indent)
if i != len(item.content):
- print
- print '%s%s:' % (indent[4:], ctx.bail)
+ print('')
+ print('%s%s:' % (indent[4:], ctx.bail))
# In theory, we should emit code to clear whatever we're
# backtracking from. In practice, it's not important to
# do that.
indent = indent[4:]
- print "%s} while (0);" % indent
+ print("%s} while (0);" % indent)
elif item.type_ == 'case':
i = 0
for choice_name, choice in sorted(item.content.items()):
if choice_name.endswith('else'):
- print "%s} else {" % indent
- print "%s p->%s%s = -1;" % (indent, accessor, item.name)
- print
+ print("%s} else {" % indent)
+ print("%s p->%s%s = -1;"
+ % (indent, accessor, item.name))
+ print('')
else:
- print "%s%sif (spvbin_match_byte (input, 0x%s)) {" % (
- indent, '} else ' if i else '', choice_name[-2:])
- print "%s p->%s%s = 0x%s;" % (
- indent, accessor, item.name, choice_name[-2:])
- print
+ print("%s%sif (spvbin_match_byte (input, 0x%s)) {" % (
+ indent, '} else ' if i else '', choice_name[-2:]))
+ print("%s p->%s%s = 0x%s;" % (
+ indent, accessor, item.name, choice_name[-2:]))
+ print('')
choice = choice[1:]
print_parser_items(name, choice, indent + ' ',
accessor + choice_name + '.', ctx)
i += 1
- print "%s}" % indent
+ print("%s}" % indent)
else:
# Not implemented
raise AssertionError
def print_parser(name, production, indent):
- print '''
+ print('''
bool
%(prefix)sparse_%(name)s (struct spvbin_input *input, struct %(prefix)s%(name)s **p_)
{
struct %(prefix)s%(name)s *p = xzalloc (sizeof *p);
p->start = input->ofs;
''' % {'prefix': prefix,
- 'name': name_to_id(name)}
+ 'name': name_to_id(name)})
ctx = Parser_Context()
print_parser_items(name, production, indent, '', ctx)
- print '''
+ print('''
p->len = input->ofs - p->start;
*p_ = p;
- return true;'''
+ return true;''')
if ctx.need_error_handler:
- print """
+ print("""
error:
spvbin_error (input, "%s", p->start);
%sfree_%s (p);
- return false;""" % (name, prefix, name_to_id(name))
+ return false;""" % (name, prefix, name_to_id(name)))
- print "}"
+ print("}")
def print_free_items(name, production, indent, accessor, ctx):
for item in production:
if item.n == 1:
if free_func:
- print "%s%s (%s);" % (indent, free_func, dst)
+ print("%s%s (%s);" % (indent, free_func, dst))
else:
if isinstance(item.n, int):
count = item.n
i_name = ctx.gen_name('i')
if free_func:
- print "%sfor (int %s = 0; %s < %s; %s++)" % (
- indent, i_name, i_name, count, i_name)
- print "%s %s (%s[%s]);" % (
- indent, free_func, dst, i_name)
+ print("%sfor (int %s = 0; %s < %s; %s++)" % (
+ indent, i_name, i_name, count, i_name))
+ print("%s %s (%s[%s]);" % (
+ indent, free_func, dst, i_name))
if not isinstance(item.n, int):
- print "%sfree (p->%s%s);" % (
- indent, accessor, name_to_id(item.name))
+ print("%sfree (p->%s%s);" % (
+ indent, accessor, name_to_id(item.name)))
elif item.type_ in ('()', 'v1', 'v3', 'vAF', 'vB0',
'count', 'becount'):
if item.n != 1:
else:
value_name = '0x%s' % choice_name[-2:]
- print '%s%sif (p->%s%s == %s) {' % (
+ print('%s%sif (p->%s%s == %s) {' % (
indent, '} else ' if i else '', accessor, item.name,
- value_name)
+ value_name))
print_free_items(name, choice, indent + ' ',
accessor + choice_name + '.', ctx)
i += 1
- print "%s}" % indent
+ print("%s}" % indent)
else:
# Not implemented
raise AssertionError
def print_free(name, production, indent):
- print '''
+ print('''
void
%(prefix)sfree_%(name)s (struct %(prefix)s%(name)s *p)
{
if (p == NULL)
return;
''' % {'prefix': prefix,
- 'name': name_to_id(name)}
+ 'name': name_to_id(name)})
print_free_items(name, production, indent, '', Parser_Context())
- print " free (p);"
- print "}"
+ print(" free (p);")
+ print("}")
def print_print_items(name, production, indent, accessor, ctx):
for item_idx in range(len(production)):
if item_idx > 0:
- print
+ print('')
item = production[item_idx]
if item.type_ == 'constant':
if item.name:
- print '%sspvbin_print_presence ("%s", indent + 1, p->%s);' % (
- indent, item.name, item.name)
+ print('%sspvbin_print_presence ("%s", indent + 1, p->%s);' % (
+ indent, item.name, item.name))
elif item.type_ == 'variable':
if not item.name:
continue
dst = "p->%s%s" % (accessor, name_to_id(item.name))
if item.n == 1:
- print '%s%s ("%s", indent + 1, %s);' % (indent, func,
- item.name, dst)
+ print('%s%s ("%s", indent + 1, %s);' % (indent, func,
+ item.name, dst))
else:
if isinstance(item.n, int):
count = item.n
i_name = ctx.gen_name('i')
elem_name = ctx.gen_name('elem_name')
dst += '[%s]' % i_name
- print """\
+ print("""\
%(indent)sfor (int %(index)s = 0; %(index)s < %(count)s; %(index)s++) {
%(indent)s char *%(elem_name)s = xasprintf ("%(item.name)s[%%d]", %(index)s);
%(indent)s %(func)s (%(elem_name)s, indent + 1, %(dst)s);
'elem_name' : elem_name,
'item.name': item.name,
'func': func,
- 'dst': dst}
+ 'dst': dst})
elif item.type_ == '()':
if item.n != 1:
# Not yet implemented
print_print_items(name, choice, indent, accessor, ctx)
elif item.type_ == 'case':
i = 0
- print """\
+ print("""\
%sspvbin_print_case ("%s", indent + 1, p->%s%s);""" % (
- indent, item.name, accessor, name_to_id(item.name))
+ indent, item.name, accessor, name_to_id(item.name)))
for choice_name, choice in sorted(item.content.items()):
if choice_name.endswith('else'):
value_name = '-1'
else:
value_name = '0x%s' % choice_name[-2:]
- print '%s%sif (p->%s%s == %s) {' % (
+ print('%s%sif (p->%s%s == %s) {' % (
indent, '} else ' if i else '', accessor, item.name,
- value_name)
+ value_name))
print_print_items(name, choice, indent + ' ',
accessor + choice_name + '.', ctx)
i += 1
- print "%s}" % indent
+ print("%s}" % indent)
else:
# Not implemented
raise AssertionError
def print_print(name, production, indent):
- print '''
+ print('''
void
%(prefix)sprint_%(name)s (const char *title, int indent, const struct %(prefix)s%(name)s *p)
{
putchar ('\\n');
''' % {'prefix': prefix,
'rawname': name,
- 'name': name_to_id(name)}
+ 'name': name_to_id(name)})
ctx = Parser_Context()
print_print_items(name, production, indent, '', ctx)
- print "}"
+ print("}")
def name_to_id(s):
return s[0].lower() + ''.join(['_%c' % x.lower() if x.isupper() else x
fatal("%s: duplicate production" % name)
productions[name] = production
- print '/* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */'
+ print('/* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */')
if output_type == 'code' and len(args) == 4:
header_name = args[3]
- print """\
+ print("""\
#include <config.h>
#include %s
#include <stdio.h>
#include <stdlib.h>
#include "libpspp/str.h"
#include "gl/xalloc.h"\
-""" % header_name
+""" % header_name)
for name, production in productions.items():
print_parser(name, production, ' ' * 4)
print_free(name, production, ' ' * 4)
print_print(name, production, ' ' * 4)
elif output_type == 'header' and len(args) == 3:
- print """\
+ print("""\
#ifndef %(PREFIX)sPARSER_H
#define %(PREFIX)sPARSER_H
#include <stdint.h>
#include <stdbool.h>
#include "output/spv/spvbin-helpers.h"\
-""" % {'PREFIX': prefix.upper()}
+""" % {'PREFIX': prefix.upper()})
for name, production in productions.items():
- print '\nstruct %s%s {' % (prefix, name_to_id(name))
- print " size_t start, len;"
+ print('\nstruct %s%s {' % (prefix, name_to_id(name)))
+ print(" size_t start, len;")
print_members(production, ' ' * 4)
- print '''};
+ print('''};
bool %(prefix)sparse_%(name)s (struct spvbin_input *, struct %(prefix)s%(name)s **);
void %(prefix)sfree_%(name)s (struct %(prefix)s%(name)s *);
void %(prefix)sprint_%(name)s (const char *title, int indent, const struct %(prefix)s%(name)s *);\
''' % {'prefix': prefix,
- 'name': name_to_id(name)}
- print """\
+ 'name': name_to_id(name)})
+ print("""\
-#endif /* %(PREFIX)sPARSER_H */""" % {'PREFIX': prefix.upper()}
+#endif /* %(PREFIX)sPARSER_H */""" % {'PREFIX': prefix.upper()})
else:
sys.stderr.write("%s: bad usage (use --help for help)" % argv0)
for enum_name in new_enums:
used_enums.add(enum_name)
c_name = name_to_id(enum_name)
- print '\nenum %s%s {' % (prefix, c_name)
+ print('\nenum %s%s {' % (prefix, c_name))
i = 0
for value in sorted(enums[enum_name]):
- print ' %s%s_%s%s,' % (prefix.upper(),
+ print(' %s%s_%s%s,' % (prefix.upper(),
c_name.upper(),
name_to_id(value).upper(),
- ' = 1' if i == 0 else '')
+ ' = 1' if i == 0 else ''))
i += 1
- print '};'
- print 'const char *%s%s_to_string (enum %s%s);' % (
- prefix, c_name, prefix, c_name)
+ print('};')
+ print('const char *%s%s_to_string (enum %s%s);' % (
+ prefix, c_name, prefix, c_name))
- print '\nstruct %s%s {' % (prefix, name_to_id(name))
- print '%sstruct spvxml_node node_;' % indent
+ print('\nstruct %s%s {' % (prefix, name_to_id(name)))
+ print('%sstruct spvxml_node node_;' % indent)
if attrs:
- print '\n%s/* Attributes. */' % indent
+ print('\n%s/* Attributes. */' % indent)
for decl, comment in attrs:
line = '%s%s' % (indent, decl)
if comment:
n_spaces = max(35 - len(line), 1)
line += '%s/* %s. */' % (' ' * n_spaces, comment)
- print line
+ print(line)
if rhs['type'] == 'etc' or rhs['type'] == 'empty':
return
- print '\n%s/* Content. */' % indent
+ print('\n%s/* Content. */' % indent)
if rhs['type'] == 'text':
- print '%schar *text; /* Always nonnull. */' % indent
+ print('%schar *text; /* Always nonnull. */' % indent)
return
for a in rhs['items'] if rhs['type'] == '|' else (rhs,):
elif term['type'] == 'nonterminal':
nt_name = name_to_id(term['nonterminal_name'])
member_name = name_to_id(term['member_name'])
- print '%sstruct %s%s *%s; /* Always nonnull. */' % (
- indent, prefix, nt_name, member_name)
+ print('%sstruct %s%s *%s; /* Always nonnull. */' % (
+ indent, prefix, nt_name, member_name))
elif term['type'] == '?' and term['item']['type'] == 'nonterminal':
nt_name = name_to_id(term['item']['nonterminal_name'])
member_name = name_to_id(term['item']['member_name'])
- print '%sstruct %s%s *%s; /* Possibly null. */' % (
- indent, prefix, nt_name, member_name)
+ print('%sstruct %s%s *%s; /* Possibly null. */' % (
+ indent, prefix, nt_name, member_name))
elif (term['type'] in ('*', '+')
and term['item']['type'] == 'nonterminal'):
nt_name = name_to_id(term['item']['nonterminal_name'])
member_name = name_to_id(term['item']['member_name'])
- print '%sstruct %s%s **%s;' % (indent, prefix,
- nt_name, member_name)
- print '%ssize_t n_%s;' % (indent, member_name)
+ print('%sstruct %s%s **%s;' % (indent, prefix,
+ nt_name, member_name))
+ print('%ssize_t n_%s;' % (indent, member_name))
else:
seq_name = term['seq_name']
- print '%sstruct spvxml_node **%s;' % (indent, seq_name)
- print '%ssize_t n_%s;' % (indent, seq_name)
+ print('%sstruct spvxml_node **%s;' % (indent, seq_name))
+ print('%ssize_t n_%s;' % (indent, seq_name))
def bytes_to_hex(s):
*p_ = p;
return true;''')
- print "}"
+ print("}")
def print_free_members(attributes, rhs, indent):
def print_free(name, production, indent):
xml_name, attributes, rhs = production
- print '''
+ print('''
void
%(prefix)sfree_%(name)s (struct %(prefix)s%(name)s *p)
{
if (!p)
return;
''' % {'prefix': prefix,
- 'name': name_to_id(name)}
+ 'name': name_to_id(name)})
print_free_members(attributes, rhs, ' ' * 4)
def print_collect_ids(name, production):
xml_name, attributes, rhs = production
- print '''
+ print('''
void
%(prefix)scollect_ids_%(name)s (struct spvxml_context *ctx, struct %(prefix)s%(name)s *p)
{
spvxml_node_collect_id (ctx, &p->node_);
''' % {'prefix': prefix,
- 'name': name_to_id(name)}
+ 'name': name_to_id(name)})
print_recurse_members(attributes, rhs, 'collect_ids')
def print_resolve_refs(name, production):
xml_name, attributes, rhs = production
- print '''
+ print('''
bool
%(prefix)sis_%(name)s (const struct spvxml_node *node)
{
if (!p)
return;
''' % {'prefix': prefix,
- 'name': name_to_id(name)}
+ 'name': name_to_id(name)})
i = 0
for unique_name, (xml_name, value, required) in sorted(attributes.items()):
fatal("%s: duplicate production" % name)
productions[name] = (xml_name, attributes, rhs)
- print '/* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */'
+ print('/* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */')
if output_type == 'code' and len(args) == 4:
header_name = args[3]
- print """\
+ print("""\
#include <config.h>
#include %s
#include <limits.h>
#include "libpspp/str.h"
#include "gl/xalloc.h"
-""" % header_name
+""" % header_name)
for enum_name, values in sorted(enums.items()):
if len(values) <= 1:
continue
'class': (name if name == production[0]
else '%s (%s)' % (name, production[0]))})
elif output_type == 'header' and len(args) == 3:
- print """\
+ print("""\
#ifndef %(PREFIX)sPARSER_H
#define %(PREFIX)sPARSER_H
#include <stdint.h>
#include <stdbool.h>
#include "output/spv/spvxml-helpers.h"\
-""" % {'PREFIX': prefix.upper()}
+""" % {'PREFIX': prefix.upper()})
for name, (xml_name, attributes, rhs) in sorted(productions.items()):
print_members(attributes, rhs, ' ' * 4)
print('''};
struct %(prefix)s%(name)s *%(prefix)scast_%(name)s (const struct spvxml_node *);'''
% {'prefix': prefix,
'name': name_to_id(name)})
- print """\
+ print("""\
-#endif /* %(PREFIX)sPARSER_H */""" % {'PREFIX': prefix.upper()}
+#endif /* %(PREFIX)sPARSER_H */""" % {'PREFIX': prefix.upper()})
else:
sys.stderr.write("%s: bad usage (use --help for help)" % argv0)