From 652a3ae92d50e4150ae49a69e3dbbaac05436e28 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 10 Feb 2004 21:54:23 +0000 Subject: [PATCH] Partiaal range support -- parsing foos up at this point. --- mad | 129 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 72 insertions(+), 57 deletions(-) diff --git a/mad b/mad index 189a38d..c638cff 100755 --- a/mad +++ b/mad @@ -6,8 +6,8 @@ reserved = ('BOOLEAN', 'CONDITIONAL', 'CONTINUE', 'DATA', 'DIMENSION', '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', @@ -47,6 +47,7 @@ t_EQUALS = r'=' t_LPAREN = r'\(' t_RPAREN = r'\)' t_STRING = r'\$[^$]*\$' +t_DOTRANGE= r'\.\.\.' reserved_map = { } for r in reserved: @@ -114,8 +115,6 @@ funcnames = [] # List of function names 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? @@ -234,7 +233,7 @@ def p_internal(t): ## 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' @@ -249,23 +248,33 @@ def p_pause(t): ## 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',) @@ -274,9 +283,13 @@ def p_remark2(t): 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]] @@ -291,7 +304,7 @@ def p_restore_return(t): ## 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' @@ -461,6 +474,8 @@ def croak(t, msg): # 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." @@ -623,7 +638,7 @@ def mode(t): 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: @@ -632,59 +647,59 @@ def prin1(t): 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 @@ -763,7 +778,7 @@ def fmt_convert(str, write=True): #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', @@ -805,22 +820,22 @@ def print_statement(statement): 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 @@ -831,17 +846,17 @@ def print_statement(statement): 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:])) + ');' @@ -859,23 +874,23 @@ def print_statement(statement): 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) @@ -899,7 +914,7 @@ def generate(out): 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: @@ -991,7 +1006,7 @@ if __name__ == '__main__': # Generate code if arguments == ['-']: - generate(sys.stdout) + generate_C_code(sys.stdout) sys.exit(0) if not target and len(arguments) == 1: @@ -1000,7 +1015,7 @@ if __name__ == '__main__': 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 -- 2.43.0