reserved_map = { }
for r in reserved:
reserved_map[r] = r
+refcount = {}
def t_NAME(t):
r'[A-Z][A-Z0-9]*\.?'
- t.type = reserved_map.get(t.value, "NAME")
+ t.type = reserved_map.get(t.value, 'NAME')
if t.type and t.value[-1] == '.':
t.type = 'FUNCALL'
t.value = t.value.lower()
return t
-t_ignore = " \n"
+t_ignore = ' \n'
def t_error(t):
- print "Illegal character %s" % `t.value[0]`
+ print 'Illegal character %s' % `t.value[0]`
t.skip(1)
# Build the lexer
## END
def p_end_of_program(t):
- "statement : END OF PROGRAM"
+ 'statement : END OF PROGRAM'
t[0] = ('end_program',)
def p_end_of_conditional(t):
- "statement : END OF CONDITIONAL"
+ 'statement : END OF CONDITIONAL'
t[0] = ('end_conditional',)
def p_end_of_functions(t):
- "statement : END OF FUNCTION"
+ 'statement : END OF FUNCTION'
t[0] = ('end_function',)
## INTEGER
def p_integer(t):
- "statement : INTEGER varlist"
+ 'statement : INTEGER varlist'
t[0] = ('integer',) + tuple(t[2])
def p_varlist(t):
'varlist : NAME'
## READ FORMAT
def p_read_format(t):
- "statement : READ FORMAT varlist"
+ 'statement : READ FORMAT varlist'
t[0] = ('read',) + tuple(t[3])
## PRINT FORMAT
def p_print_format(t):
- "statement : PRINT FORMAT varlist"
+ 'statement : PRINT FORMAT varlist'
t[0] = ('print',) + tuple(t[3])
## THROUGH
## TRANSFER TO
def p_transfer(t):
- "statement : TRANSFER TO NAME"
+ 'statement : TRANSFER TO NAME'
t[0] = ('goto', t[3])
targets.append(t[3])
# VECTOR VALUES
def p_vector_values(t):
- "statement : VECTOR VALUES NAME EQUALS STRING"
+ 'statement : VECTOR VALUES NAME EQUALS STRING'
t[0] = ('values',) + (t[3], t[5])
## Assignment
def p_expression_subscript(t):
'expression : NAME application'
t[0] = ('variable', t[1], tuple(t[2]))
+ refcount[var] = refcount.get(var, 0) + 1
def p_function_application(t):
'expression : FUNCALL application'
t[0] = ('apply', t[1], tuple(t[2]))
def p_expression_application(t):
- "application : LPAREN inner_expression RPAREN"
+ 'application : LPAREN inner_expression RPAREN'
t[0] = t[2]
def p_expression_tail_empty(t):
- "inner_expression : expression"
+ 'inner_expression : expression'
t[0] = [t[1]]
def p_expression_tail_nonempty(t):
- "inner_expression : inner_expression COMMA expression"
+ 'inner_expression : inner_expression COMMA expression'
t[0] = t[1] + [t[3]]
def p_expression_name(t):
'expression : NAME'
var = t[1]
t[0] = ('variable', var)
+ refcount[var] = refcount.get(var, 0) + 1
if var not in integers + bools + floats + untyped:
untyped.append(var)
# Error handling
def p_error(t):
- print "Syntax error at '%s'" % t.value
+ print 'Syntax error at "%s"' % t.value
import yacc
yacc.yacc()
bools = []
dimensions = {}
static = {}
+format = {}
# Map MAD intrinsics to C library functions
madfunc_map = {'elog':'log'}
# Mine the code for compile-time directives
for (label, statement) in deck:
if statement[0] == 'integer':
- print "Bar!", statement
for var in statement[1:]:
declare(var, integers)
elif statement[0] == 'dimension':
var = statement[1]
if var not in integers + bools + floats + untyped:
untyped.append(var)
- if statement[0] == 'values':
- static[statement[1]] = statement[2]
+ elif statement[0] in ('read', 'print'):
+ pass
+ elif statement[0] == 'values':
+ var = statement[1]
+ if var in refcount:
+ static[var] = statement[2]
+ else:
+ format[var] = statement[2]
def print_expr(t):
if t[0] == 'variable':
res = t[1]
if len(t) > 2:
for dim in t[2]:
- res += "[" + dim[1] + "]"
+ res += '[' + dim[1] + ']'
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])
+ return '%s' % print_expr(t[1])
else:
- return "(%s + %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s + %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == '-':
if len(t) == 2:
- return "-%s" % print_expr(t[1])
+ return '-%s' % print_expr(t[1])
else:
- return "(%s - %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s - %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == '*':
- return "(%s * %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s * %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == '/':
- return "(%s / %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s / %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'l':
- return "(%s < %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s < %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'g':
- return "(%s > %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s > %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'le':
- return "(%s <= %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s <= %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'ge':
- return "(%s >= %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s >= %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'e':
- return "(%s == %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s == %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'ne':
- return "(%s != %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s != %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'p':
- return "pow(%s, %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return 'pow(%s, %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'and':
- return "(%s && %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s && %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'or':
- return "(%s || %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s || %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'then':
- return "!(%s && !(%s))" % (print_expr(t[1]), print_expr(t[2]))
+ return '!(%s && !(%s))' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'eqv':
- return "(%s == %s)" % (print_expr(t[1]), print_expr(t[2]))
+ return '(%s == %s)' % (print_expr(t[1]), print_expr(t[2]))
elif t[0] == 'abs':
- return "abs(%s)" % print_expr(t[1])
+ return 'abs(%s)' % print_expr(t[1])
elif t[0] in ('intnum', 'floatnum'):
return t[1]
else:
- return "***"+`t`
-
-def print_statement(statement):
- if statement[0] in ('dimension', 'end_program', 'integer', 'values'):
- pass
- 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))
- elif statement[0] == 'goto':
- return "goto " + statement[1] + ";"
- elif statement[0] == 'if':
- return "if (" + print_expr(statement[1]) + ") " + print_statement(statement[2])
- elif statement[0] == 'read':
- return 'scanf(' + statement[1] + ', ' + ", ".join(map(lambda x: "&"+x, statement[2:])) + ");"
- elif statement[0] == 'print':
- return 'printf(' + statement[1] + ', ' + ", ".join(statement[2:]) + ");"
- elif statement[0] == 'substitution':
- return statement[1] + " = " + print_expr(statement[2]) + ";"
- else:
- return("// " + `statement`)
+ return '***'+`t`
-def fmt_convert(str):
+def fmt_convert(str, write=True):
"Convert MAD format string to C printf/scanf"
- res = ""
+ res = ''
str = str[1:-1]
while True:
- if str[0] == "*":
+ if str[0] == '*':
break
elif str[0] == 'S':
- i = 0
- while str[i].isdigit():
+ i = 1
+ while str[i] != ',':
i += 1
if i <= 0:
- sys.stderr.write("invalid spacer in %s\n" % str)
+ sys.stderr.write('invalid spacer in %s\n' % str)
sys.exit(1)
- count = int(str[:i])
- res += " " * count
- str = str[i:]
- break
+ count = int(str[1:i])
+ if write:
+ res += ' ' * count
+ str = str[i+1:]
# All other format codes require a prefix.
i = 0
while str[i].isdigit():
i += 1
if i <= 0:
- sys.stderr.write("invalid format string %s\n" % str)
+ sys.stderr.write('invalid format string %s\n' % str)
sys.exit(1)
count = int(str[:i])
str = str[i:]
if str[0] == 'F':
i = 1
- while str[i] in "0123456789.":
+ while str[i] in '0123456789.':
i += 1
- res += ("%" + str[1:i] + "f") * count
+ res += ('%' + str[1:i] + 'f') * count
str = str[i:]
elif str[0] == 'H':
- res += str[1:count+1]
+ if write:
+ res += str[1:count+1]
str = str[count+1:]
else:
- sys.stderr.write("invalid field code in format string!")
+ sys.stderr.write('invalid field code in format string!')
sys.exit(1)
+ # Clip off format character
+ if write:
+ res = res[1:]
+ res = res + '\\n'
return res
+def print_statement(statement):
+ if statement[0] in ('dimension', 'end_program', 'integer', 'values'):
+ pass
+ 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))
+ elif statement[0] == 'goto':
+ return 'goto ' + statement[1] + ';'
+ elif statement[0] == 'if':
+ return 'if (' + print_expr(statement[1]) + ') ' + print_statement(statement[2])
+ elif statement[0] == 'read':
+ return 'scanf("' + fmt_convert(format[statement[1]], write=False) + '", ' + ', '.join(map(lambda x: '&'+x, statement[2:])) + ');'
+ elif statement[0] == 'print':
+ return 'printf("' + fmt_convert(format[statement[1]]) + '", ' + ', '.join(statement[2:]) + ');'
+ elif statement[0] == 'substitution':
+ return statement[1] + ' = ' + print_expr(statement[2]) + ';'
+ else:
+ return('// ' + `statement`)
+
if __name__ == '__main__':
source = sys.stdin.read()
# Grotty hack to add end-of-statement delimiters
- source = re.sub("\n([A-Z]|\t)", " ;\n\\1", source).rstrip() + " ;\n"
+ source = re.sub('\n([A-Z]|\t)', ' ;\n\\1', source).rstrip() + ' ;\n'
yacc.parse(source)
analyze(deck)
- print "#include <math.h>"
- print "main(int argc, char *argv[])"
- print "{"
+ print '#include <math.h>'
+ print 'main(int argc, char *argv[])'
+ print '{'
if integers:
- print "\tint " + ", ".join(integers) + ";\t/* INTEGER */"
+ print '\tint ' + ', '.join(integers) + ';\t/* INTEGER */'
if bools:
- print "\tint " + ", ".join(bools) + ";\t/* boolean */"
+ print '\tint ' + ', '.join(bools) + ';\t/* boolean */'
if untyped:
- print "\tfloat " + ", ".join(untyped) + ";\t/* untyped */"
+ print '\tfloat ' + ', '.join(untyped) + ';\t/* untyped */'
if floats:
- print "\tfloat " + ", ".join(floats) + ";"
+ print '\tfloat ' + ', '.join(floats) + ';'
for (id, value) in static.items():
print '\tstatic const char *%s\t= "%s";' % (id, fmt_convert(value))
indent = 0
for (label, statement) in deck:
if label in targets:
- sys.stdout.write(label+":")
+ sys.stdout.write(label+':')
rep = print_statement(statement)
if rep:
- sys.stdout.write("\t" + " "*indent + rep + "\n")
+ sys.stdout.write('\t' + ' '*indent + rep + '\n')
if rep[-1] == '{':
indent += 1
if label in scopes:
indent -= 1
- print ("\t" + " "*indent) + "}"
- print "}"
+ print ('\t' + ' '*indent) + '}'
+ print '}'