home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Demo / p2c / p2c.py next >
Text File  |  1993-11-11  |  11KB  |  446 lines

  1. # Python to C -- from the parser output
  2.  
  3.  
  4. import parser
  5. import token
  6. import symbol
  7. import sys
  8. import getopt
  9.  
  10.  
  11. def main():
  12.     opts, args = getopt.getopt(sys.argv[1:], '')
  13.     if args:
  14.     filename = args[0]
  15.     else:
  16.     filename = 'testf.py'
  17.     root = parser.parsefile(filename)
  18.     g = Generator(root)
  19.     g.go()
  20.  
  21.  
  22. class Formatter:
  23.  
  24.     def __init__(self):
  25.     self.file = sys.stdout
  26.     self.atbol = 0
  27.     self.level = 0
  28.  
  29.     def indent(self):
  30.     self.level = self.level + 1
  31.  
  32.     def dedent(self):
  33.     self.level = self.level - 1
  34.  
  35.     def puts(self, fmt, *args):
  36.     self.vputs(fmt, args)
  37.  
  38.     def vputs(self, fmt, args):
  39.     if self.atbol: self.file.write('    ' * self.level)
  40.     self.file.write(fmt % args)
  41.     self.atbol = (fmt[-1:] == '\n')
  42.  
  43.  
  44. class Generator(Formatter):
  45.  
  46.     def __init__(self, root):
  47.     Formatter.__init__(self)
  48.     self.stdc = 0
  49.     self.root = root
  50.  
  51.     def go(self):
  52.     self.dispatch(self.root)
  53.  
  54.     def llputs(self, fmt, *args):
  55.     Formatter.vputs(self, fmt, args)
  56.  
  57.     def vputs(self, fmt, args):
  58.     # Like Formatter.vputs but recognizes %n to dispatch a node
  59.     # and handles { } \b \t \n differently
  60.     iarg = 0
  61.     i = 0
  62.     n = len(fmt)
  63.     start = 0
  64.     while i < n:
  65.         c = fmt[i]
  66.         if c not in '%{}\n\b\t':
  67.         i = i+1
  68.         continue
  69.         if start < i:
  70.         self.llputs(fmt[start:i])
  71.         start = i
  72.         if c != '%':
  73.         if c in '\b}': self.dedent()
  74.         if c not in '\b\t': self.llputs(c)
  75.         if c in '{\t': self.indent()
  76.         start = i = i+1
  77.         continue
  78.         i = i+1
  79.         while i < n and fmt[i] in '+-*#.0123456789 ':
  80.         i = i+1
  81.         if i >= n:
  82.         break
  83.         c = fmt[i]
  84.         i = i+1
  85.         if c == '%':
  86.         self.llputs('%%')
  87.         elif c == 'n':
  88.         self.dispatch(args[iarg])
  89.         iarg = iarg + 1
  90.         else:
  91.         self.llputs(fmt[start:i], args[iarg])
  92.         iarg = iarg + 1
  93.         start = i
  94.     if start < n:
  95.         self.llputs(fmt[start:n])
  96.  
  97.     def dispatch(self, node):
  98.     sym = node[0]
  99.     if sym < token.N_TOKENS:
  100.         name = token.tok_name[sym]
  101.     else:
  102.         name = symbol.sym_name[sym]
  103.     if hasattr(self, name):
  104.         apply(getattr(self, name), node[1:])
  105.     else:
  106.         self.puts('/* %s unknown */\n', name)
  107.  
  108.     def nop(self, *children):
  109.     pass
  110.  
  111.     NEWLINE = nop
  112.     INDENT = nop
  113.     DEDENT = nop
  114.     ENDMARKER = nop
  115.     pass_stmt = nop
  116.  
  117.     def passthru(self, *children):
  118.     for child in children:
  119.         self.dispatch(child)
  120.  
  121.     file_input = passthru
  122.     stmt = passthru
  123.     compound_stmt = passthru
  124.     suite = passthru
  125.     simple_stmt = passthru
  126.     small_stmt = passthru
  127.     flow_stmt = passthru
  128.  
  129.     def funcdef(self, *children):
  130.     (namesymbol, namestring) = children[1]
  131.     parms = children[2]
  132.     body = children[4]
  133.     parmchildren = parms[1:]
  134.     if len(parmchildren) == 3:
  135.         self.scan_arguments(parmchildren[1])
  136.     else:
  137.         self.args = []        # list of (name, type) pairs
  138.     self.puts('\nint %s(', namestring)
  139.     if self.stdc:
  140.         sep = ''
  141.         for argname, argtype in self.args:
  142.         self.puts('%s%s %s', sep, argtype, argname)
  143.         sep = ', '
  144.         self.puts(')\n')
  145.     else:
  146.         sep = ''
  147.         for argname, argtype in self.args:
  148.         self.puts('%s%s', sep, argname)
  149.         sep = ', '
  150.         self.puts(')\n\t')
  151.         for argname, argtype in self.args:
  152.         self.puts('%s %s;\n', argtype, argname)
  153.         self.puts('\b')
  154.     self.puts('{\n')
  155.     self.vars = []
  156.     self.find_variables(body)
  157.     for varname, vartype in self.vars:
  158.         self.puts('%s %s;\n', vartype, varname)
  159.     self.puts('%n}\n', body)
  160.  
  161.     def scan_arguments(self, node):
  162.     self.args = []
  163.     children = node[1:]
  164.     for child in children:
  165.         if child[0] == symbol.fpdef:
  166.         subchildren = child[1:]
  167.         if len(subchildren) != 1:
  168.             self.puts('/* nested parameters not supported */')
  169.         else:
  170.             subchild = subchildren[0]
  171.             namestring = subchild[1]
  172.             self.args.append((namestring, 'int'))
  173.  
  174.     def find_variables(self, node):
  175.     sym = node[0]
  176.     if sym < token.N_TOKENS:
  177.         return
  178.     children = node[1:]
  179.     if sym == symbol.expr_stmt:
  180.         for i in range(0, len(children)-2, 2):
  181.         self.add_variables(children[i], 'int')
  182.     elif sym == symbol.for_stmt:
  183.         self.add_variables(children[1], 'int')
  184.         for child in children[5:]:
  185.         self.find_variables(child)
  186.     elif sym == symbol.funcdef:
  187.         pass
  188.     elif sym == symbol.classdef:
  189.         pass
  190.     else:
  191.         for child in children:
  192.         self.find_variables(child)
  193.  
  194.     def add_variables(self, node, vartype):
  195.     node = self.strip_trivial(node)
  196.     if node[0] == token.NAME:
  197.         entry = (node[1], vartype)
  198.         if entry not in self.vars and entry not in self.args:
  199.         self.vars.append(entry)
  200.  
  201.     def print_stmt(self, *children):
  202.     args = []
  203.     format = ''
  204.     i = 1
  205.     while i < len(children):
  206.         s = self.test_string_literal(children[i])
  207.         if s is not None:
  208.         s = eval(s)        # Not quite, but close enough for now
  209.         format = format + s + ' '
  210.         else:
  211.         args.append(children[i])
  212.         format = format + '%d '
  213.         i = i+2
  214.     if children[-1][0] != token.COMMA:
  215.         if format[-1:] == ' ': format = format[:-1]
  216.         format = format + '\\n'
  217.     self.puts('printf("%s"', format)
  218.     for arg in args:
  219.         self.puts(', %n', arg)
  220.     self.puts(');\n')
  221.  
  222.     def strip_trivial(self, node):
  223.     while 1:
  224.         sym = node[0]
  225.         children = node[1:]
  226.         if sym == symbol.atom and children[0][0] == token.LPAR and \
  227.           len(children) == 3:
  228.         node = children[1]
  229.         elif sym > token.N_TOKENS and len(children) == 1:
  230.         node = children[0]
  231.         else:
  232.         break
  233.     return node
  234.  
  235.     def test_string_literal(self, node):
  236.     node = self.strip_trivial(node)
  237.     if node[0] == token.STRING:
  238.         return node[1]
  239.     else:
  240.         return None
  241.  
  242.     def operator_list(self, children):
  243.     for child in children:
  244.         if child[0] < token.N_TOKENS:
  245.         self.puts(' %s ', child[1])
  246.         else:
  247.         self.dispatch(child)
  248.  
  249.     def va_operator_list(self, *children):
  250.     self.operator_list(children)
  251.  
  252.     def separated_list(self, children, sep):
  253.     for i in range(0, len(children), 2):
  254.         if i > 0: self.puts(sep)
  255.         self.dispatch(children[i])
  256.  
  257.     def return_stmt(self, *children):
  258.     if len(children) == 1:
  259.         self.puts('return;\n')
  260.     else:
  261.         self.puts('return %n;\n', children[1])
  262.  
  263.     def break_stmt(self, *children):
  264.     self.puts('break;\n')
  265.  
  266.     def continue_stmt(self, *children):
  267.     self.puts('continue;\n')
  268.  
  269.     def expr_stmt(self, *children):
  270.     self.separated_list(children, ' = ')
  271.     self.puts(';\n')
  272.  
  273.     def if_stmt(self, *children):
  274.     i = 0
  275.     while i+3 < len(children):
  276.         test = children[i+1]
  277.         suite = children[i+3]
  278.         if i > 0: self.puts('else ')
  279.         self.puts('if (%n) {\n%n}\n', test, suite)
  280.         i = i+4
  281.     if i+2 < len(children):
  282.         suite = children[i+2]
  283.         self.puts('else {\n%n}\n', suite)
  284.  
  285.     def while_stmt(self, *children):
  286.     test = children[1]
  287.     suite = children[3]
  288.     if len(children) > 6:        # while...else form
  289.         elsuite = children[6]
  290.         self.puts(
  291.           'while (1) {\nif (%n) {\n%n}\nelse {\n%nbreak;\n}\n}\n',
  292.           test, suite, elsuite)
  293.     else:
  294.         self.puts('while (%n) {\n%n}\n', test, suite)
  295.  
  296.     def for_stmt(self, *children):
  297.     variable = children[1]
  298.     sequence = children[3]
  299.     suite = children[5]
  300.     if len(children) > 8:        # for...else form
  301.         elsuite = children[8]
  302.     else:
  303.         elsuite = None
  304.     control = self.test_range(sequence)
  305.     if not control:
  306.         self.puts('/* too complicated for loop */\n')
  307.     elif not elsuite:
  308.         start, stop, step = control
  309.         if not step:
  310.         self.puts('for (%n = %n; %n < %n; %n++) ',
  311.               variable, start, variable, stop, variable)
  312.         else:
  313.         self.puts('for (%n = %n; %n * (%n) < (%n) * (%n); %n += %n) ',
  314.               variable, start,
  315.               variable, step, stop, step,
  316.               variable, step)
  317.         self.puts('{\n%n}\n', suite)
  318.     else:
  319.         start, stop, step = control
  320.         self.puts('%n = %n;\nwhile (1) {\n', variable, start)
  321.         if not step:
  322.         self.puts('if (%n < %n) ', variable, stop)
  323.         else:
  324.         self.puts('if (%n * (%n) < (%n) * (%n)) ',
  325.               variable, step, stop, step)
  326.         self.puts('{\n%n', suite)
  327.         if not step:
  328.         self.puts('%n++;\n', variable)
  329.         else:
  330.         self.puts('%n = %n + %n\n', variable, variable, step)
  331.         self.puts('}\nelse {\n%nbreak;\n}\n}\n', elsuite)
  332.  
  333.     def test_range(self, node):
  334.     node = self.strip_trivial(node)
  335.     if node[0] == symbol.factor:
  336.         children = node[1:]
  337.         if len(children) == 2 and children[0][0] == symbol.atom and \
  338.           children[1][0] == symbol.trailer:
  339.         atom, trailer = children
  340.         atom = self.strip_trivial(atom)
  341.         if atom[0] == token.NAME and atom[1] == 'range':
  342.             children = trailer[1:]
  343.             if children[0][0] == token.LPAR and len(children) == 3:
  344.             testlist = children[1]
  345.             sym = testlist[0]
  346.             children = testlist[1:]
  347.             n = (len(testlist)+1) / 2
  348.             if 1 <= n <= 3:
  349.                 start = (token.NUMBER, '0')
  350.                 step = None    # Special case
  351.                 if n == 1:
  352.                 stop = children[0]
  353.                 elif n == 2:
  354.                 start = children[0]
  355.                 stop = children[2]
  356.                 elif n == 3:
  357.                 start = children[0]
  358.                 stop = children[2]
  359.                 step = children[4]
  360.                 return start, stop, step
  361.     return None
  362.  
  363.     def testlist(self, *children):
  364.     self.separated_list(children, ', ')
  365.  
  366.     def test(self, *children):
  367.     self.separated_list(children, ' || ')
  368.  
  369.     def and_test(self, *children):
  370.     self.separated_list(children, ' && ')
  371.  
  372.     def not_test(self, *children):
  373.     if len(children) == 2:
  374.         self.puts('!(%n)', children[1])
  375.     else:
  376.         self.dispatch(children[0])
  377.  
  378.     def comparison(self, *children):
  379.     if len(children) > 3:
  380.         self.puts('/* non-trivial comparison */')
  381.     else:
  382.         self.operator_list(children)
  383.  
  384.     def comp_op(self, *children):
  385.     child = children[0]
  386.     if len(children) > 1 or child[0] == token.NAME:
  387.         self.puts(' /* unhandled comparison */ ')
  388.     else:
  389.         s = child[1]
  390.         if s == '<>': s = '!='
  391.         self.puts(' %s ', s)
  392.  
  393.     exprlist = testlist
  394.     expr = va_operator_list
  395.     xor_expr = va_operator_list
  396.     and_expr = va_operator_list
  397.     shift_expr = va_operator_list
  398.     arith_expr = va_operator_list
  399.     factor = va_operator_list
  400.     term = va_operator_list
  401.  
  402.     def atom(self, *children):
  403.     child = children[0]
  404.     childsymbol = child[0]
  405.     if childsymbol in (token.NAME, token.NUMBER, token.STRING):
  406.         self.dispatch(child)
  407.     elif childsymbol == token.LPAR and len(children) == 3:
  408.         self.puts('(%n)', children[1])
  409.     else:
  410.         self.puts('/* unhandled atom */')
  411.  
  412.     def trailer(self, *children):
  413.     child = children[0]
  414.     csym = child[0]
  415.     if csym == token.LPAR:
  416.         if len(children) == 3:
  417.         self.puts('(%n)', children[1])
  418.         else:
  419.         self.puts('()')
  420.     elif csym == token.LSQB:
  421.         if len(children) == 3:
  422.         self.puts('[%n]', children[1])
  423.         else:
  424.         self.puts('[]')
  425.     elif csym == token.DOT:
  426.         self.puts('.%n', children[1])
  427.     else:
  428.         self.puts('/* XXX unexpected trailer */')
  429.  
  430.     def subscript(self, *children):
  431.     if len(children) == 1:
  432.         self.dispatch(children[0])
  433.     else:
  434.         self.puts('/* slice not supported */')
  435.  
  436.     def STRING(self, child):
  437.     self.puts('%s', child)
  438.  
  439.     def NUMBER(self, child):
  440.     self.puts('%s', child)
  441.  
  442.     def NAME(self, child):
  443.     self.puts('%s', child)
  444.  
  445. main()
  446.