#!/usr/bin/env python
reserved = ('CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', 'EXECUTE',
- 'FOR', 'FORMAT', 'FUNCTION', 'INTEGER', 'INTERNAL', 'OF',
- 'PAUSE', 'PRINT', 'PROGRAM', 'READ', 'COMMENT', 'THROUGH',
- 'TO', 'TRANSFER', 'VALUES', 'VECTOR', 'WHENEVER')
+ 'EXTERNAL', 'FOR', 'FORMAT', 'FUNCTION', 'INTEGER',
+ 'INTERNAL', 'OF', 'PAUSE', 'PRINT', 'PROGRAM', 'READ',
+ 'RETURN', 'THROUGH', 'TO', 'TRANSFER', 'VALUES', 'VECTOR',
+ 'WHENEVER',
+ # This is a pseudo-keyword generated early in compilation.
+ 'COMMENT')
tokens = reserved + (
'SEMI', 'COMMA',
'statement : EXECUTE FUNCALL'
t[0] = ('execute', ('apply', t[2], []))
+## EXTERNAL FUNCTION
+def p_external(t):
+ "statement : INTERNAL FUNCTION FUNCALL application"
+ t[0] = ('external', t[3], tuple(t[4]))
+
+## FUNCTION RETURN
+def p_function_return(t):
+ "statement : FUNCTION RETURN expression"
+ t[0] = ('return', t[3])
+def p_function_return_void(t):
+ "statement : FUNCTION RETURN"
+ t[0] = ('return')
+
## INTEGER
def p_integer(t):
'statement : INTEGER varlist'
## INTERNAL FUNCTION
def p_internal(t):
"statement : INTERNAL FUNCTION FUNCALL application EQUALS expression"
- t[0] = ('function', t[3], tuple(t[4]), t[6])
+ t[0] = ('internal', t[3], tuple(t[4]), t[6])
## PAUSE
def p_pause(t):
untyped.remove(var)
lst.append(var)
-def analyze(deck):
- "Gather variable types."
- global integers, floats, bools
+def analyze():
+ "Gather variable types and determine function boundaries."
+ global integers, floats, bools, deck
# Mine the code for compile-time directives
for (line, label, statement) in deck:
if statement[0] == 'integer':
untyped.remove(var)
else:
format[var] = statement[2]
+ # We may need to generate a pseudo-function call
+ if deck[3][0] != 'external':
+ deck = [(0, None, ('external', 'main.', ()))] + deck
def print_expr(t):
if t[0] == 'variable':
def print_statement(statement):
if statement[0] in ('dimension',
- 'end_program',
- 'function',
+ 'internal',
'integer',
'values'):
pass
elif statement[0] == 'continue':
return "/* continue */;"
- elif statement[0] == 'end_conditional':
+ elif statement[0] in ('end_program', 'end_function', 'end_conditional'):
return "}"
elif statement[0] == 'execute':
- return print_expr(statement[1]) + ";"
+ return print_expr(statement[1]) + ";"
+ elif statement[0] == 'external':
+ return "\n" + print_expr(('apply', statement[1], statement[2])) + " {"
elif statement[0] == 'for':
(keyword, label, dummy, start, increment, predicate) = statement
return 'for (%s = %s; %s; %s += %s) {' % (dummy, print_expr(start), print_expr(predicate), dummy, print_expr(increment))
if len(statement) == 1:
return "\n"
else:
- return "/* %s */\n" % statement[1].strip()
+ return "/* %s */" % statement[1].strip()
+ elif statement[0] == 'return':
+ if len(statement) == 1:
+ return "return;"
+ else:
+ return "return %s" % peint_expr(statement[1])
elif statement[0] == 'or':
return 'else if (' + print_expr(statement[2]) + ') {'
elif statement[0] == 'otherwise':
def generate(out):
out.write('#include <math.h>\n\n')
- for (line, label, statement) in deck:
- if statement[0] == 'function':
- # FIXME: someday, deduce when return is of integral type
- out.write('float %s {return %s;}\n' % \
- (print_expr(('apply', statement[1], statement[2])), print_expr(statement[3])))
-
- out.write('\nmain(int argc, char *argv[])\n')
- out.write('{\n')
if integers:
- out.write('\tint ' + ', '.join(integers) + ';\t/* INTEGER */\n')
+ out.write('int ' + ', '.join(integers) + ';\t/* INTEGER */\n')
if bools:
- out.write('\tint ' + ', '.join(bools) + ';\t/* boolean */\n')
+ out.write('int ' + ', '.join(bools) + ';\t/* boolean */\n')
if untyped:
- out.write('\tfloat ' + ', '.join(untyped) + ';\t/* untyped */\n')
+ out.write('float ' + ', '.join(untyped) + ';\t/* untyped */\n')
if floats:
- out.write('\tfloat ' + ', '.join(floats) + ';\n')
+ out.write('float ' + ', '.join(floats) + ';\n')
for (id, value) in static.items():
- out.write('\tstatic const char *%s\t= "%s";\n' % (id, fmt_convert(value)))
+ out.write('static const char *%s\t= "%s";\n' % (id, fmt_convert(value)))
+ for (line, label, statement) in deck:
+ if statement[0] == 'internal':
+ # FIXME: someday, deduce when return is of integral type
+ out.write('float %s {return %s;}\n' % \
+ (print_expr(('apply', statement[1], statement[2])), print_expr(statement[3])))
+
indent = 0
global sourceline
for (sourceline, label, statement) in deck:
if label in targets:
- out.write(label+':')
+ out.write(" " + label+':\n')
rep = print_statement(statement)
if rep:
- out.write('\t' + ' '*indent + rep + '\n')
+ if rep[-1] == '}':
+ indent -= 1
+ out.write(' '*indent + rep + '\n')
if rep[-1] == '{':
indent += 1
if label in scopes:
indent -= 1
- out.write(('\t' + ' '*indent) + '}\n')
- out.write('}\n')
+ out.write((' '*indent) + '}\n')
if __name__ == '__main__':
import os, getopt
yacc.parse(source, debug=mad_debug)
# Perform global analysis
- analyze(deck)
+ analyze()
if (dump_tuples):
for t in deck: