'OF', 'PAUSE', 'PRINT_FORMAT', 'PROGRAM', 'READ_FORMAT',
'RESTORE', 'RETURN', 'SAVE', 'SET_LIST_TO', 'THROUGH',
'TO', 'TRANSFER', 'VALUES', 'VECTOR', 'WHENEVER',
- # This is a pseudo-keyword generated early in compilation.
- 'COMMENT')
+ # COMMENT is a pseudo-keyword generated early in compilation.
+ 'COMMENT', 'DOTRANGE')
tokens = reserved + (
'SEMI', 'COMMA',
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_STRING = r'\$[^$]*\$'
+t_DOTRANGE= r'\.\.\.'
reserved_map = { }
for r in reserved:
dimensions = {} # Dictionary of array depths
arraydepths = {} # Dictionary of array dimensions
returntypes = {} # Dictionary of function returntypes
-normalmode = 'double' # Default type as set by NORMAL statement
-dummycount = 0 # Count of FOR VALUES statements
static = {} # Dictionary of static char variables
format = {} # Dictionary of format strings
hasmain = False # Does this program have a main line?
## NORMAL MODE IS
def p_normal(t):
"statement : NORMAL MODE IS typeval"
- t[0] = ('normal', t[1])
+ t[0] = ('normal', t[4])
def p_typeval_int(t):
"typeval : INTEGER"
t[0] = 'int'
## PRINT_FORMAT
def p_print_format(t):
- 'statement : PRINT_FORMAT NAME COMMA exprlist'
+ 'statement : PRINT_FORMAT NAME COMMA outlist'
t[0] = ('print', t[2]) + tuple(t[4])
-def p_exprlist(t):
- 'exprlist : expression'
- t[0] = [t[1]]
-def p_exprlist_continue(t):
- 'exprlist : exprlist COMMA expression'
- t[0] = t[1] + [t[3]]
def p_print_format0(t):
'statement : PRINT_FORMAT NAME'
t[0] = ('print', t[2])
+ # This is shared with SAVE DATA
+def p_outlist(t):
+ 'outlist : outval'
+ t[0] = [t[1]]
+def p_outlist_continue(t):
+ 'outlist : outlist COMMA outval'
+ t[0] = t[1] + [t[3]]
+def p_outval(t):
+ '''outval : range
+ | expression'''
+ t[0] = t[1]
+def p_range(t):
+ 'range : NAME application DOTRANGE NAME application'
+ t[0] = ('slice', t[1], t[2], t[5])
+ if t[1] != t[4]:
+ sys.stderr.write("variable names in range don't match!")
+ sys.exit(1)
## R
def p_remark1(t):
'statement : COMMENT STRING'
t[0] = ('remark', t[2][1:-1])
-
def p_remark2(t):
'statement : COMMENT'
t[0] = ('remark',)
def p_read_format(t):
'statement : READ_FORMAT NAME COMMA varlist'
t[0] = ('read', t[2]) + tuple(t[4])
+ # This is shared with RESTORE_DATA
def p_varlist(t):
'varlist : NAME'
t[0] = [t[1]]
+def p_varlist_range(t):
+ 'varlist : varlist COMMA range'
+ t[0] = t[1] + [t[3]]
def p_varlist_continue(t):
'varlist : varlist COMMA NAME'
t[0] = t[1] + [t[3]]
## SAVE
def p_save_data(t):
- 'statement : SAVE DATA exprlist'
+ 'statement : SAVE DATA outlist'
t[0] = ('save', tuple(t[3]))
def p_save_return(t):
'statement : SAVE RETURN'
# functions deliberately shared a global, but this doesn't happen in
# any of the examples.
typedict = {} # Dictionary of per-function dictionaries of locals
+normalmode = 'double' # Default type as set by NORMAL statement
+dummycount = 0 # Count of FOR VALUES statements
def analyze():
"Gather variable types and determine function boundaries."
sys.write.stderr("mad: internal error while computing mode of %s\n"%t)
sys.exit(1)
-def prin1(t):
+def prinC1(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(prin1, t[2])) + ')'
+ return madfunc_map.get(madfunc, madfunc) + '(' + ', '.join(map(prinC1, t[2])) + ')'
elif t[0] == '+':
if len(t) == 2:
- return '%s' % prin1(t[1])
+ return '%s' % prinC1(t[1])
else:
- return '(%s + %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s + %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == '-':
if len(t) == 2:
- return '-%s' % prin1(t[1])
+ return '-%s' % prinC1(t[1])
else:
- return '(%s - %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s - %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'not':
- return "!%s" % prin1(t[1])
+ return "!%s" % prinC1(t[1])
elif t[0] == '*':
- return '(%s * %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s * %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == '/':
- return '(%s / %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s / %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'l':
- return '(%s < %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s < %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'g':
- return '(%s > %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s > %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'le':
- return '(%s <= %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s <= %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'ge':
- return '(%s >= %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s >= %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'e':
- return '(%s == %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s == %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'ne':
- return '(%s != %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s != %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'p':
- return 'pow(%s, %s)' % (prin1(t[1]), prin1(t[2]))
+ return 'pow(%s, %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'and':
- return '(%s && %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s && %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'or':
- return '(%s || %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s || %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'then':
- return '!(%s && !(%s))' % (prin1(t[1]), prin1(t[2]))
+ return '!(%s && !(%s))' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'eqv':
- return '(%s == %s)' % (prin1(t[1]), prin1(t[2]))
+ return '(%s == %s)' % (prinC1(t[1]), prinC1(t[2]))
elif t[0] == 'abs':
argmode = mode(t[1])
if argmode == 'double':
- return 'fabs(%s)' % prin1(t[1])
+ return 'fabs(%s)' % prinC1(t[1])
else:
- return 'abs(%s)' % prin1(t[1]) # int or bool
+ return 'abs(%s)' % prinC1(t[1]) # int or bool
elif t[0] in ('intnum', 'doublenum'):
return t[1]
else:
return '***'+`t`
-def print_expr(t):
- "Cosmetic wrapper round prin1"
- res = prin1(t)
+def print_C_expr(t):
+ "Cosmetic wrapper round prinC1"
+ res = prinC1(t)
if res[0] == "(" and res[-1] == ")":
res = res[1:-1]
return res
#print "<-fmt_convert() = %s" % res
return (res, types)
-def print_statement(statement):
+def print_C_statement(statement):
global currentfunc
if statement[0] in ('boolean',
'dimension',
rep += " " + declarations[:-1] + "\n"
return rep
elif statement[0] == 'execute':
- return print_expr(statement[1]) + ";"
+ return print_C_expr(statement[1]) + ";"
elif statement[0] == 'external_call':
- return "\n" + print_expr(('apply', statement[1], statement[2])) + ";"
+ return "\n" + print_C_expr(('apply', statement[1], statement[2])) + ";"
elif statement[0] == 'for':
(keyword, label, dummy, start, increment, predicate) = statement
- return 'for (%s = %s; %s; %s += %s) { /* label %s */ ' % (dummy, print_expr(start), print_expr(predicate), dummy, print_expr(increment), label)
+ return 'for (%s = %s; %s; %s += %s) { /* label %s */ ' % (dummy, print_C_expr(start), print_C_expr(predicate), dummy, print_C_expr(increment), label)
elif statement[0] == 'goto':
return 'goto ' + statement[1] + ';'
elif statement[0] == 'if':
- return 'if (' + print_expr(statement[1]) + ') ' + print_statement(statement[2])
+ return 'if (' + print_C_expr(statement[1]) + ') ' + print_C_statement(statement[2])
elif statement[0] == 'internal':
rep = returntypes.get(statement[1], normalmode) + " " + statement[1][:-1] +"("
for (dummy, var) in statement[2]:
rep += mode((dummy, var)) + " " + var + ", "
rep = rep[:-2]
- rep += ') {return %s;}' % print_expr(statement[3])
+ rep += ') {return %s;}' % print_C_expr(statement[3])
return rep
elif statement[0] == 'map':
global dummycount
rep += "((%s [%d]){%s})[%s];" % (statement[3][0][0][:-3], count, ", ".join(map(lambda x: `x[1]`, statement[3])), dummy)
return rep
elif statement[0] == 'or':
- return 'else if (' + print_expr(statement[2]) + ') {'
+ return 'else if (' + print_C_expr(statement[2]) + ') {'
elif statement[0] == 'otherwise':
return 'else {'
elif statement[0] == 'pause':
- return('printf("%o", ' + print_expr(statement[1]) + '); getchar();')
+ return('printf("%o", ' + print_C_expr(statement[1]) + '); getchar();')
elif statement[0] == 'print':
(fmt, types) = fmt_convert(format[statement[1]])
if len(statement) < 3:
return 'printf("' + fmt + '");'
else:
- return 'printf("' + fmt + '", ' + ', '.join(map(print_expr, statement[2:])) + ');'
+ return 'printf("' + fmt + '", ' + ', '.join(map(print_C_expr, statement[2:])) + ');'
elif statement[0] == 'read':
(fmt, types) = fmt_convert(format[statement[1]], write=False)
return 'scanf("' + fmt + '", ' + ', '.join(map(lambda x: '&'+x, statement[2:])) + ');'
if len(statement) == 1:
return "return;"
else:
- return "return %s;" % print_expr(statement[1])
+ return "return %s;" % print_C_expr(statement[1])
elif statement[0] == 'save':
rep = ''
for expr in statement[1]:
- rep += '*recursor++ = (double)(%s); ' % print_expr(expr)
+ rep += '*recursor++ = (double)(%s); ' % print_C_expr(expr)
return rep
elif statement[0] == 'set_list_to':
var = statement[1]
- return normalmode + " " + prin1(('variable', var, dimensions[var])) + ", *recursor = " + var + ";"
+ return normalmode + " " + prinC1(('variable', var, dimensions[var])) + ", *recursor = " + var + ";"
elif statement[0] == 'substitution':
- return statement[1] + ' = ' + print_expr(statement[2]) + ';'
+ return statement[1] + ' = ' + print_C_expr(statement[2]) + ';'
elif statement[0] == 'whenever':
- return 'if (' + print_expr(statement[1]) + ') {'
+ return 'if (' + print_C_expr(statement[1]) + ') {'
else:
return('// ' + `statement`)
-def generate(out):
+def generate_C_code(out):
out.write("/* generated by the MAD compiler */\n")
for header in headers:
out.write('#include <%s.h>\n' % header)
out.write(" " + label+':\n')
if statement[0] in ('for', 'map'):
scopes.append(statement[1])
- rep = print_statement(statement)
+ rep = print_C_statement(statement)
if rep:
indentchange = rep.count('{') - rep.count('}')
if indentchange < 0:
# Generate code
if arguments == ['-']:
- generate(sys.stdout)
+ generate_C_code(sys.stdout)
sys.exit(0)
if not target and len(arguments) == 1:
sys.stderr.write("mad: -o is required with multiple sourcefiles.\n")
sys.exit(1)
out = open(target + ".c", "w")
- generate(out)
+ generate_C_code(out)
out.close()
if binary:
# Must be gcc, else compilation of internal functions will fail