diff options
author | 1138-4EB <1138-4EB@users.noreply.github.com> | 2019-06-17 07:57:59 +0200 |
---|---|---|
committer | tgingold <tgingold@users.noreply.github.com> | 2019-06-17 07:57:59 +0200 |
commit | f6379989022c1e71017f4151392a300534d2007a (patch) | |
tree | 783ba27543a32a5c009a5cdc92952809a1436728 /python | |
parent | 159e0bfdbb135e74aac10e54c7a499e9e34aa5a2 (diff) | |
download | ghdl-f6379989022c1e71017f4151392a300534d2007a.tar.gz ghdl-f6379989022c1e71017f4151392a300534d2007a.tar.bz2 ghdl-f6379989022c1e71017f4151392a300534d2007a.zip |
fix: move src/xtools to python/xtools (#846)
* fix: move src/xtools to python/xtools
* fix Makefiles affected by xtools and pnodes being moved
Diffstat (limited to 'python')
-rwxr-xr-x | python/xtools/pnodes.py | 929 |
1 files changed, 929 insertions, 0 deletions
diff --git a/python/xtools/pnodes.py b/python/xtools/pnodes.py new file mode 100755 index 000000000..62d5362d3 --- /dev/null +++ b/python/xtools/pnodes.py @@ -0,0 +1,929 @@ +#!/usr/bin/env python + +import re +import sys +import argparse + +field_file = "nodes.ads" +kind_file = "iirs.ads" +node_file = "iirs.ads" +template_file = "iirs.adb.in" +meta_base_file = "nodes_meta" +prefix_name = "Iir_Kind_" +prefix_range_name = "Iir_Kinds_" +type_name = "Iir_Kind" +node_type = "Iir" +conversions = ['uc', 'pos', 'grp'] + + +class FuncDesc: + def __init__(self, name, fields, conv, acc, + pname, ptype, rname, rtype): + self.name = name + self.fields = fields # List of physical fields used + self.conv = conv + self.acc = acc # access: Chain, Chain_Next, Ref, Of_Ref, Maybe_Ref, + # Forward_Ref, Maybe_Forward_Ref + self.pname = pname # Parameter mame + self.ptype = ptype # Parameter type + self.rname = rname # value name (for procedure) + self.rtype = rtype # value type + + +class NodeDesc: + def __init__(self, name, format, fields, attrs): + self.name = name + self.format = format + self.fields = fields # {field: FuncDesc} dict, defined for all fields + self.attrs = attrs # A {attr: FuncDesc} dict + self.order = [] # List of fields name, in order of appearance. + + +class line: + def __init__(self, string, no): + self.l = string + self.n = no + + +class EndOfFile(Exception): + def __init__(self, filename): + self.filename = filename + + def __str__(self): + return "end of file " + self.filename + + +class linereader: + def __init__(self, filename): + self.filename = filename + self.f = open(filename) + self.lineno = 0 + self.l = '' + + def get(self): + self.l = self.f.readline() + if not self.l: + raise EndOfFile(self.filename) + self.lineno = self.lineno + 1 + return self.l + + +class ParseError(Exception): + def __init__(self, lr, msg): + self.lr = lr + self.msg = msg + + def __str__(self): + return 'Error: ' + self.msg + return 'Parse error at ' + self.lr.filname + ':' + self.lr.lineno + \ + ': ' + self.msg + + +# Return fields description. +# This is a dictionary. The keys represent the possible format of a node. +# The values are dictionnaries representing fields. Keys are fields name, and +# values are fields type. +def read_fields(file): + fields = {} + formats = [] + lr = linereader(file) + + # Search for 'type Format_Type is' + while lr.get() != ' type Format_Type is\n': + pass + + # Skip '(' + if lr.get() != ' (\n': + raise 'no open parenthesis after Format_Type' + + # Read formats + l = lr.get() + pat_field_name = re.compile(' Format_(\w+),?\n') + while l != ' );\n': + m = pat_field_name.match(l) + if m is None: + print l + raise 'bad literal within Format_Type' + name = m.group(1) + formats.append(name) + fields[name] = {} + l = lr.get() + + # Read fields + l = lr.get() + pat_fields = re.compile(' -- Fields of Format_(\w+):\n') + pat_field_desc = re.compile(' -- (\w+) : (\w+).*\n') + format_name = '' + common_desc = {} + + # Read until common fields. + while l != ' -- Common fields are:\n': + l = lr.get() + format_name = 'Common' + nbr_formats = 0 + + while True: + # 1) Read field description + l = lr.get() + desc = common_desc.copy() + while True: + m = pat_field_desc.match(l) + if m is None: + break + desc[m.group(1)] = m.group(2) + l = lr.get() + # print 'For: ' + format_name + ': ' + m.group(1) + + # 2) Disp + if format_name == 'Common': + common_desc = desc + else: + fields[format_name] = desc + + # 3) Read next format + if l == '\n': + if nbr_formats == len(fields): + break + else: + l = lr.get() + + # One for a format + m = pat_fields.match(l) + if m is not None: + format_name = m.group(1) + if format_name not in fields: + raise ParseError( + lr, 'Format ' + format_name + ' is unknown') + nbr_formats = nbr_formats + 1 + else: + raise ParseError(lr, 'unhandled format line') + + return (formats, fields) + + +# Read kinds and kinds ranges. +def read_kinds(filename): + lr = linereader(filename) + kinds = [] + # Search for 'type Iir_Kind is' + while lr.get() != ' type ' + type_name + ' is\n': + pass + # Skip '(' + if lr.get() != ' (\n': + raise ParseError( + lr, 'no open parenthesis after "type ' + type_name + '"') + + # Read literals + pat_node = re.compile(' ' + prefix_name + '(\w+),?( +-- .*)?\n') + pat_comment = re.compile('( +-- .*)?\n') + while True: + l = lr.get() + if l == ' );\n': + break + m = pat_node.match(l) + if m: + kinds.append(m.group(1)) + continue + m = pat_comment.match(l) + if not m: + raise ParseError(lr, 'Unknown line within kind declaration') + + # Check subtypes + pat_subtype = re.compile(' subtype ' + r'(\w+) is ' + + type_name + ' range\n') + pat_first = re.compile(' ' + prefix_name + r'(\w+) ..\n') + pat_last = re.compile(' ' + prefix_name + r'(\w+);\n') + pat_middle = re.compile(' --' + prefix_name + r'(\w+)\n') + kinds_ranges = {} + while True: + l = lr.get() + # Start of methods is also end of subtypes. + if l == ' -- General methods.\n': + break + # Found a subtype. + m = pat_subtype.match(l) + if m: + # Check first bound + name = m.group(1) + if not name.startswith(prefix_range_name): + raise ParseError(lr, 'incorrect prefix for subtype') + name = name[len(prefix_range_name):] + l = lr.get() + mf = pat_first.match(l) + if not mf: + raise ParseError(lr, 'badly formated first bound of subtype') + first = kinds.index(mf.group(1)) + idx = first + has_middle = None + # Read until last bound + while True: + l = lr.get() + ml = pat_middle.match(l) + if ml: + # Check element in the middle + n = ml.group(1) + if n not in kinds: + raise ParseError( + lr, "unknown kind " + n + " in subtype") + if kinds.index(n) != idx + 1: + raise ParseError( + lr, "missing " + kinds[idx + 1] + " in subtype") + has_middle = True + idx = idx + 1 + else: + # Check last bound + ml = pat_last.match(l) + if ml: + last = kinds.index(ml.group(1)) + if last != idx + 1 and has_middle: + raise ParseError( + lr, "missing " + kinds[idx] + " in subtype") + break + raise ParseError(lr, "unhandled line in subtype") + kinds_ranges[name] = kinds[first:last+1] + return (kinds, kinds_ranges) + +# Read functions +def read_methods(filename): + lr = linereader(filename) + funcs = [] + pat_field = re.compile(r' -- Field: ([\w,]+)( \w+)?( \(\w+\))?\n') + pat_conv = re.compile(r'^ \((\w+)\)$') + pat_func = re.compile( + r' function Get_(\w+) \((\w+) : (\w+)\) return (\w+);\n') + pat_proc = re.compile( + r' procedure Set_(\w+) \((\w+) : (\w+); (\w+) : (\w+)\);\n') + pat_end = re.compile('end [A-Za-z.]+;\n') + while True: + l = lr.get() + # Start of methods + if l == ' -- General methods.\n': + break + while True: + l = lr.get() + if pat_end.match(l): + break + m = pat_field.match(l) + if m: + fields = m.group(1).split(',') + # Extract access modifier + acc = m.group(2) + if acc: + acc = acc.strip() + # Extract conversion + conv = m.group(3) + if conv: + mc = pat_conv.match(conv) + if not mc: + raise ParseError(lr, 'conversion ill formed') + conv = mc.group(1) + if conv not in conversions: + raise ParseError(lr, 'unknown conversion ' + conv) + else: + conv = None + if len(fields) > 1 and conv != 'grp': + raise ParseError(lr, 'bad conversion for multiple fields') + # Read function + l = lr.get() + mf = pat_func.match(l) + if not mf: + raise ParseError( + lr, 'function declaration expected after Field') + # Read procedure + l = lr.get() + mp = pat_proc.match(l) + if not mp: + raise ParseError( + lr, 'procedure declaration expected after function') + # Consistency check between function and procedure + if mf.group(1) != mp.group(1): + raise ParseError(lr, 'function and procedure name mismatch') + if mf.group(2) != mp.group(2): + raise ParseError(lr, 'parameter name mismatch with function') + if mf.group(3) != mp.group(3): + raise ParseError(lr, 'parameter type mismatch with function') + if mf.group(4) != mp.group(5): + raise ParseError(lr, 'result type mismatch with function') + funcs.append(FuncDesc(mf.group(1), fields, conv, acc, + mp.group(2), mp.group(3), + mp.group(4), mp.group(5))) + + return funcs + + +# Read description for one node +# LR is the line reader. NAMES is the list of (node name, format) +# (one description may describe several nodes). +def read_nodes_fields(lr, names, fields, nodes, funcs_dict): + pat_only = re.compile(' -- Only for ' + prefix_name + '(\w+):\n') + pat_only_bad = re.compile (' -- *Only for.*\n') + pat_field = re.compile(' -- Get/Set_(\w+) \((Alias )?([\w,]+)\)\n') + pat_comment = re.compile(' --.*\n') + pat_start = re.compile(' -- \w.*\n') + + # Create nodes + cur_nodes = [] + for (nm, fmt) in names: + if fmt not in fields: + raise ParseError(lr, 'unknown format "{}"'.format(fmt)) + n = NodeDesc(nm, fmt, {x: None for x in fields[fmt]}, {}) + nodes[nm] = n + cur_nodes.append(n) + + # Look for fields + only_nodes = cur_nodes + l = lr.l + while l != '\n': + # Handle 'Only ...' + while True: + m = pat_only.match(l) + if not m: + break + name = m.group(1) + if name not in [x.name for x in cur_nodes]: + raise ParseError(lr, 'node not currently described') + if only_nodes == cur_nodes: + only_nodes = [] + only_nodes.append(nodes[name]) + l = lr.get() + # Handle field: '-- Get/Set_FUNC (Alias? FIELD)' + m = pat_field.match(l) + if m: + # 1) Check the function exists + func = m.group(1) + alias = m.group(2) + fields = m.group(3).split(',') + if func not in funcs_dict: + raise ParseError(lr, 'unknown function') + func = funcs_dict[func] + if func.fields != fields: + raise ParseError(lr, 'fields mismatch') + for c in only_nodes: + for f in fields: + if f not in c.fields: + raise ParseError( + lr, 'field ' + f + ' does not exist in node') + if not alias: + for f in fields: + if c.fields[f]: + raise ParseError( + lr, 'field ' + f + ' already used') + c.fields[f] = func + c.order.append(f) + c.attrs[func.name] = func + only_nodes = cur_nodes + elif pat_start.match(l): + raise ParseError(lr, 'bad line in node description') + elif pat_only_bad.match(l): + raise ParseError(lr, "misleading 'Only for' comment") + elif not pat_comment.match(l): + raise ParseError(lr, 'bad line in node description') + l = lr.get() + + +def read_nodes(filename, kinds, kinds_ranges, fields, funcs): + """Read description for all nodes.""" + lr = linereader(filename) + funcs_dict = {x.name: x for x in funcs} + nodes = {} + + # Skip until start + while lr.get() != ' -- Start of ' + type_name + '.\n': + pass + + pat_decl = re.compile(' -- ' + prefix_name + '(\w+) \((\w+)\)\n') + pat_decls = re.compile(' -- ' + prefix_range_name + '(\w+) \((\w+)\)\n') + pat_comment_line = re.compile(' --+\n') + pat_comment_box = re.compile(' --( .*)?\n') + while True: + l = lr.get() + if l == ' -- End of ' + type_name + '.\n': + break + if l == '\n': + continue + m = pat_decl.match(l) + if m: + # List of nodes being described by the current description. + names = [] + + # Declaration of the first node + while True: + name = m.group(1) + if name not in kinds: + raise ParseError(lr, 'unknown node') + fmt = m.group(2) + names.append((name, fmt)) + if name in nodes: + raise ParseError( + lr, 'node {} already described'.format(name)); + # There might be several nodes described at once. + l = lr.get() + m = pat_decl.match(l) + if not m: + break + read_nodes_fields(lr, names, fields, nodes, funcs_dict) + continue + m = pat_decls.match(l) + if m: + # List of nodes being described by the current description. + name = m.group(1) + fmt = m.group(2) + names = [(k, fmt) for k in kinds_ranges[name]] + l = lr.get() + read_nodes_fields(lr, names, fields, nodes, funcs_dict) + continue + if pat_comment_line.match(l) or pat_comment_box.match(l): + continue + raise ParseError(lr, 'bad line in node description') + + for k in kinds: + if k not in nodes: + raise ParseError(lr, 'no desription for "{}"'.format(k)) + return nodes + + +def gen_choices(choices): + """Generate a choice 'when A | B ... Z =>' using elements of CHOICES.""" + is_first = True + for c in choices: + if is_first: + print ' ', + print 'when', + else: + print + print ' ', + print ' |', + print prefix_name + c, + is_first = False + print '=>' + + +def gen_get_format(formats, nodes, kinds): + """Generate the Get_Format function.""" + print ' function Get_Format (Kind : ' + type_name + ') ' + \ + 'return Format_Type is' + print ' begin' + print ' case Kind is' + for f in formats: + choices = [k for k in kinds if nodes[k].format == f] + gen_choices(choices) + print ' return Format_' + f + ';' + print ' end case;' + print ' end Get_Format;' + + +def gen_subprg_header(decl): + if len(decl) < 76: + print decl + ' is' + else: + print decl + print ' is' + print ' begin' + + +def gen_assert(func): + print ' pragma Assert (' + func.pname + ' /= Null_' + node_type + ');' + cond = '(Has_' + func.name + ' (Get_Kind (' + func.pname + ')),' + msg = '"no field ' + func.name + '");' + if len(cond) < 60: + print ' pragma Assert ' + cond + print ' ' + msg + else: + print ' pragma Assert' + print ' ' + cond + print ' ' + msg + + +def get_field_type(fields, f): + for fld in fields.values(): + if f in fld: + return fld[f] + return None + + +def gen_get_set(func, nodes, fields): + """Generate Get_XXX/Set_XXX subprograms for FUNC.""" + rtype = func.rtype + # If the function needs several fields, it must be user defined + if func.conv == 'grp': + print ' type %s_Conv is record' % rtype + for f in func.fields: + print ' %s: %s;' % (f, get_field_type(fields, f)) + print ' end record;' + print ' pragma Pack (%s_Conv);' % rtype + print " pragma Assert (%s_Conv'Size = %s'Size);" % (rtype, rtype) + print + else: + f = func.fields[0] + g = 'Get_' + f + ' (' + func.pname + ')' + + s = func.rname + if func.conv: + if func.conv == 'uc': + field_type = get_field_type(fields, f) + g = field_type + '_To_' + rtype + ' (' + g + ')' + s = rtype + '_To_' + field_type + ' (' + s + ')' + elif func.conv == 'pos': + g = rtype + "'Val (" + g + ')' + s = rtype + "'Pos (" + s + ')' + + subprg = ' function Get_' + func.name + ' (' + func.pname \ + + ' : ' + func.ptype + ') return ' + rtype + if func.conv == 'grp': + print subprg + print ' is' + print ' function To_%s is new Ada.Unchecked_Conversion' % \ + func.rtype + print ' (%s_Conv, %s);' % (rtype, rtype) + print ' Conv : %s_Conv;' % rtype + print ' begin' + else: + gen_subprg_header(subprg) + gen_assert(func) + if func.conv == 'grp': + for f in func.fields: + print ' Conv.%s := Get_%s (%s);' % (f, f, func.pname) + g = 'To_%s (Conv)' % rtype + print ' return ' + g + ';' + print ' end Get_' + func.name + ';' + print + + subprg = ' procedure Set_' + func.name + ' (' \ + + func.pname + ' : ' + func.ptype + '; ' \ + + func.rname + ' : ' + func.rtype + ')' + if func.conv == 'grp': + print subprg + print ' is' + print ' function To_%s_Conv is new Ada.Unchecked_Conversion' % \ + func.rtype + print ' (%s, %s_Conv);' % (rtype, rtype) + print ' Conv : %s_Conv;' % rtype + print ' begin' + else: + gen_subprg_header(subprg) + gen_assert(func) + if func.conv == 'grp': + print ' Conv := To_%s_Conv (%s);' % (rtype, func.rname) + for f in func.fields: + print ' Set_%s (%s, Conv.%s);' % (f, func.pname, f) + else: + print ' Set_' + f + ' (' + func.pname + ', ' + s + ');' + print ' end Set_' + func.name + ';' + print + + +def funcs_of_node(n): + return sorted([fv.name for fv in n.fields.values() if fv]) + + +def gen_has_func_spec(name, suff): + spec = ' function Has_' + name + ' (K : ' + type_name + ')' + ret = ' return Boolean' + suff + if len(spec) < 60: + print spec + ret + else: + print spec + print ' ' + ret + + +def do_disp_formats(): + for fmt in fields: + print "Fields of Format_"+fmt + fld = fields[fmt] + for k in fld: + print ' ' + k + ' (' + fld[k] + ')' + + +def do_disp_kinds(): + print "Kinds are:" + for k in kinds: + print ' ' + prefix_name + k + + +def do_disp_funcs(): + print "Functions are:" + for f in funcs: + s = '{0} ({1}: {2}'.format(f.name, f.field, f.rtype) + if f.acc: + s += ' acc:' + f.acc + if f.conv: + s += ' conv:' + f.conv + s += ')' + print s + + +def do_disp_types(): + print "Types are:" + s = set([]) + for f in funcs: + s |= set([f.rtype]) + for t in sorted(s): + print ' ' + t + + +def do_disp_nodes(): + for k in kinds: + v = nodes[k] + print prefix_name + k + ' (' + v.format + ')' + flds = [fk for fk, fv in v.fields.items() if fv] + for fk in sorted(flds): + print ' ' + fk + ': ' + v.fields[fk].name + + +def do_get_format(): + gen_get_format(formats, nodes) + + +def do_body(): + lr = linereader(template_file) + while True: + l = lr.get().rstrip() + print l + if l == ' -- Subprograms': + gen_get_format(formats, nodes, kinds) + print + for f in funcs: + gen_get_set(f, nodes, fields) + if l[0:3] == 'end': + break + + +def get_types(): + s = set([]) + for f in funcs: + s |= set([f.rtype]) + return [t for t in sorted(s)] + + +def get_attributes(): + s = set([]) + for f in funcs: + if f.acc: + s |= set([f.acc]) + res = [t for t in sorted(s)] + res.insert(0, 'None') + return res + + +def gen_enum(prefix, vals): + last = None + for v in vals: + if last: + print last + ',' + last = prefix + v + print last + + +def do_meta_specs(): + lr = linereader(meta_base_file + '.ads.in') + types = get_types() + while True: + l = lr.get().rstrip() + if l == ' -- TYPES': + gen_enum(' Type_', types) + elif l == ' -- FIELDS': + gen_enum(' Field_', [f.name for f in funcs]) + elif l == ' -- ATTRS': + gen_enum(' Attr_', get_attributes()) + elif l == ' -- FUNCS': + for t in types: + print ' function Get_' + t + print ' (N : ' + node_type + '; F : Fields_Enum) return '\ + + t + ';' + print ' procedure Set_' + t + print ' (N : ' + node_type + '; F : Fields_Enum; V: ' \ + + t + ');' + print + for f in funcs: + gen_has_func_spec(f.name, ';') + elif l[0:3] == 'end': + print l + break + else: + print l + + +def do_meta_body(): + lr = linereader(meta_base_file + '.adb.in') + while True: + l = lr.get().rstrip() + if l == ' -- FIELDS_TYPE': + last = None + for f in funcs: + if last: + print last + ',' + last = ' Field_' + f.name + ' => Type_' + f.rtype + print last + elif l == ' -- FIELD_IMAGE': + for f in funcs: + print ' when Field_' + f.name + ' =>' + print ' return "' + f.name.lower() + '";' + elif l == ' -- IIR_IMAGE': + for k in kinds: + print ' when ' + prefix_name + k + ' =>' + print ' return "' + k.lower() + '";' + elif l == ' -- FIELD_ATTRIBUTE': + for f in funcs: + print ' when Field_' + f.name + ' =>' + if f.acc: + attr = f.acc + else: + attr = 'None' + print ' return Attr_' + attr + ';' + elif l == ' -- FIELDS_ARRAY': + last = None + nodes_types = [node_type, + node_type + '_List', node_type + '_Flist'] + for k in kinds: + v = nodes[k] + if last: + print last + ',' + last = None + print ' -- ' + prefix_name + k + # Get list of physical fields for V, in some order. + if flag_keep_order: + flds = v.order + else: + # First non Iir and no Iir_List. + flds = sorted([fk for fk, fv in v.fields.items() + if fv and fv.rtype not in nodes_types]) + # Then Iir and Iir_List in order of appearance + flds += (fv for fv in v.order + if v.fields[fv].rtype in nodes_types) + # Print the corresponding node field, but remove duplicate due + # to 'grp'. + fldsn = [] + for fk in flds: + if last: + print last + ',' + # Remove duplicate + fn = v.fields[fk].name + if fn not in fldsn: + last = ' Field_' + fn + fldsn.append(fn) + else: + last = None + if last: + print last + elif l == ' -- FIELDS_ARRAY_POS': + pos = -1 + last = None + for k in kinds: + v = nodes[k] + # Create a set to remove duplicate for 'grp'. + flds = set([fv.name for fk, fv in v.fields.items() if fv]) + pos += len(flds) + if last: + print last + ',' + last = ' ' + prefix_name + k + ' => {}'.format(pos) + print last + elif l == ' -- FUNCS_BODY': + # Build list of types + s = set([]) + for f in funcs: + s |= set([f.rtype]) + types = [t for t in sorted(s)] + for t in types: + print ' function Get_' + t + print ' (N : ' + node_type + '; F : Fields_Enum) return '\ + + t + ' is' + print ' begin' + print ' pragma Assert (Fields_Type (F) = Type_' + t + ');' + print ' case F is' + for f in funcs: + if f.rtype == t: + print ' when Field_' + f.name + ' =>' + print ' return Get_' + f.name + ' (N);' + print ' when others =>' + print ' raise Internal_Error;' + print ' end case;' + print ' end Get_' + t + ';' + print + print ' procedure Set_' + t + print ' (N : ' + node_type + '; F : Fields_Enum; V: ' \ + + t + ') is' + print ' begin' + print ' pragma Assert (Fields_Type (F) = Type_' + t + ');' + print ' case F is' + for f in funcs: + if f.rtype == t: + print ' when Field_' + f.name + ' =>' + print ' Set_' + f.name + ' (N, V);' + print ' when others =>' + print ' raise Internal_Error;' + print ' end case;' + print ' end Set_' + t + ';' + print + for f in funcs: + gen_has_func_spec(f.name, ' is') + choices = [k for k in kinds if f.name in nodes[k].attrs] + if len(choices) == 0: + print ' pragma Unreferenced (K);' + print ' begin' + if len(choices) == 0: + print ' return False;' + elif len(choices) == 1: + print ' return K = ' + prefix_name + choices[0] + ';' + else: + print ' case K is' + gen_choices(choices) + print ' return True;' + print ' when others =>' + print ' return False;' + print ' end case;' + print ' end Has_' + f.name + ';' + print + elif l[0:3] == 'end': + print l + break + else: + print l + + +actions = {'disp-nodes': do_disp_nodes, + 'disp-kinds': do_disp_kinds, + 'disp-formats': do_disp_formats, + 'disp-funcs': do_disp_funcs, + 'disp-types': do_disp_types, + 'get_format': do_get_format, + 'body': do_body, + 'meta_specs': do_meta_specs, + 'meta_body': do_meta_body} + + +def main(): + parser = argparse.ArgumentParser(description='Meta-grammar processor') + parser.add_argument('action', choices=actions.keys(), + default='disp-nodes') + parser.add_argument('--field-file', dest='field_file', + default='nodes.ads', + help='specify file which defines fields') + parser.add_argument('--kind-file', dest='kind_file', + default='iirs.ads', + help='specify file which defines nodes kind') + parser.add_argument('--node-file', dest='node_file', + default='iirs.ads', + help='specify file which defines nodes and methods') + parser.add_argument('--template-file', dest='template_file', + default='iirs.adb.in', + help='specify template body file') + parser.add_argument('--meta-basename', dest='meta_basename', + default='nodes_meta', + help='specify base name of meta files') + parser.add_argument('--kind-type', dest='kind_type', + default='Iir_Kind', + help='name of kind type') + parser.add_argument('--kind-prefix', dest='kind_prefix', + default='Iir_Kind_', + help='prefix for kind literals') + parser.add_argument('--kind-range-prefix', dest='kind_range_prefix', + default='Iir_Kinds_', + help='prefix for kind subtype (range)') + parser.add_argument('--node-type', dest='node_type', + default='Iir', + help='name of the node type') + parser.add_argument('--keep-order', dest='flag_keep_order', + action='store_true', + help='keep field order of nodes') + parser.set_defaults(flag_keep_order=False) + args = parser.parse_args() + + # At some point, it would be simpler to create a class... + global formats, fields, nodes, kinds, kinds_ranges, funcs + + global type_name, prefix_name, template_file, node_type, meta_base_file + global prefix_range_name, flag_keep_order, kind_file + + type_name = args.kind_type + prefix_name = args.kind_prefix + prefix_range_name = args.kind_range_prefix + template_file = args.template_file + node_type = args.node_type + meta_base_file = args.meta_basename + flag_keep_order = args.flag_keep_order + + field_file = args.field_file + kind_file = args.kind_file + node_file = args.node_file + + try: + (formats, fields) = read_fields(field_file) + (kinds, kinds_ranges) = read_kinds(kind_file) + funcs = read_methods(node_file) + nodes = read_nodes(node_file, kinds, kinds_ranges, fields, funcs) + + except ParseError as e: + print >> sys.stderr, e + print >> sys.stderr, \ + "in {0}:{1}:{2}".format(e.lr.filename, e.lr.lineno, e.lr.l) + sys.exit(1) + + f = actions.get(args.action, None) + if not f: + print >> sys.stderr, "Action {0} is unknown".format(args.action) + sys.exit(1) + f() + + +if __name__ == '__main__': + main() |