#!/usr/bin/env python
-reserved = ('CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', 'EXECUTE',
+reserved = ('CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', 'ENTRY', 'EXECUTE',
'EXTERNAL', 'FOR', 'FORMAT', 'FUNCTION', 'INTEGER',
'INTERNAL', 'OF', 'PAUSE', 'PRINT', 'PROGRAM', 'READ',
'RETURN', 'THROUGH', 'TO', 'TRANSFER', 'VALUES', 'VECTOR',
def p_card(t):
'card : statement SEMI'
- deck.append((t.lineno(1), None, t[1]))
+ deck.append((sourcefile, t.lineno(1), None, t[1]))
def p_labeled_card(t):
'card : NAME statement SEMI'
- deck.append((t.lineno(1), t[1], t[2]))
+ deck.append((sourcefile, t.lineno(1), t[1], t[2]))
# Statement level
'statement : END OF FUNCTION'
t[0] = ('end_function',)
+## ENTRY
+def p_entry(t):
+ "statement : ENTRY TO FUNCALL"
+ t[0] = ('entry', t[3])
+
## EXECUTE
def p_execute(t):
'statement : EXECUTE FUNCALL application'
'statement : EXECUTE FUNCALL'
t[0] = ('execute', ('apply', t[2], []))
+## EXTERNAL
+def p_external_call(t):
+ "statement : EXTERNAL FUNCALL application"
+ t[0] = ('external_call', t[2], tuple(t[3]))
+
## EXTERNAL FUNCTION
-def p_external(t):
- "statement : INTERNAL FUNCTION FUNCALL application"
- t[0] = ('external', t[3], tuple(t[4]))
+def p_external_function(t):
+ "statement : EXTERNAL FUNCTION application"
+ t[0] = ('external_function', tuple(t[3]))
## FUNCTION RETURN
def p_function_return(t):
def analyze():
"Gather variable types and determine function boundaries."
global integers, floats, bools, deck
+ # We may need to generate a pseudo-function call
+ if deck[0][3][0] != 'external_function':
+ deck = [(deck[0][0], 0, None, ('entry', ('apply', 'main.',())))] + deck
+ else:
+ for i in range(len(deck)):
+ (file, line, label, statement) = deck[i]
+ if statement[0] == 'end_function' and i < len(deck)-1 and deck[i+1][2][0] != 'extern':
+ deck.insert(i, (file, line, None, ('entry', ('apply', 'main.', ()))))
# Mine the code for compile-time directives
- for (line, label, statement) in deck:
- if statement[0] == 'integer':
- for var in statement[1:]:
- declare(var, integers)
- elif statement[0] == 'dimension':
+ for (file, line, label, statement) in deck:
+ if statement[0] == 'dimension':
for (var, dimlist) in statement[1]:
dimensions[var] = dimlist
+ elif statement[0] == 'integer':
+ for var in statement[1:]:
+ declare(var, integers)
elif statement[0] == 'substitution':
var = statement[1]
if var not in integers + bools + floats + untyped:
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
+ # Now associate entry point names with function definitions:
+ for i in range(len(deck)):
+ (file, line, label, statement) = deck[i]
+ if statement[0] == 'entry' and type(statement[1]) == type(""):
+ name = statement[1]
+ for j in range(i):
+ if deck[i-j-1][3][0] == 'external_function':
+ deck[i] = (file, line, label,
+ ('entry', ('apply', name, deck[i-j-1][3][1])))
+ break
+ else:
+ sys.stderr.write('"%s", line %d: no EXTERNAL declaration matches this ENTRY\n' % (file, line))
-def print_expr(t):
+def prin1(t):
if t[0] == 'variable':
res = t[1]
if len(t) > 2:
return res
elif t[0] == 'apply':
madfunc = t[1][:-1]
- return madfunc_map.get(madfunc, madfunc) + '(' + ' ,'.join(map(print_expr, t[2])) + ')'
+ return madfunc_map.get(madfunc, madfunc) + '(' + ', '.join(map(print_expr, t[2])) + ')'
elif t[0] == '+':
if len(t) == 2:
return '%s' % print_expr(t[1])
else:
return '***'+`t`
+def print_expr(t):
+ "Cosmetic wrapper round prin1"
+ res = prin1(t)
+ if res[0] == "(" and res[-1] == ")":
+ res = res[1:-1]
+ return res
+
def fmt_convert(fmt, write=True):
"Convert MAD format string to C printf/scanf"
res = ''
def print_statement(statement):
if statement[0] in ('dimension',
+ 'external_function',
'internal',
'integer',
'values'):
return "/* continue */;"
elif statement[0] in ('end_program', 'end_function', 'end_conditional'):
return "}"
+ elif statement[0] == 'entry':
+ return "\n" + print_expr(statement[1]) + " {"
elif statement[0] == 'execute':
return print_expr(statement[1]) + ";"
- elif statement[0] == 'external':
- return "\n" + print_expr(('apply', statement[1], statement[2])) + " {"
+ elif statement[0] == 'external_call':
+ 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 "return;"
else:
- return "return %s" % peint_expr(statement[1])
+ return "return %s" % print_expr(statement[1])
elif statement[0] == 'or':
return 'else if (' + print_expr(statement[2]) + ') {'
elif statement[0] == 'otherwise':
if floats:
out.write('float ' + ', '.join(floats) + ';\n')
for (id, value) in static.items():
- out.write('static const char *%s\t= "%s";\n' % (id, fmt_convert(value)))
- for (line, label, statement) in deck:
+ out.write('static const char *%s\t= "%s";\n' % (id,fmt_convert(value)))
+ for (file, 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' % \
indent = 0
global sourceline
- for (sourceline, label, statement) in deck:
+ for (file, sourceline, label, statement) in deck:
if label in targets:
out.write(" " + label+':\n')
rep = print_statement(statement)