From: Eric S. Raymond Date: Wed, 14 Jan 2004 17:39:06 +0000 (+0000) Subject: We can emit code for three statement types now. X-Git-Tag: 1.0~198 X-Git-Url: http://thyrsus.com/gitweb/?a=commitdiff_plain;h=7ad5289f2c992acdb48ca3e99ba5e3f9b63f6632;p=mad.git We can emit code for three statement types now. --- diff --git a/mad b/mad index a508c96..79226b0 100755 --- a/mad +++ b/mad @@ -12,7 +12,7 @@ tokens = reserved + ( 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', 'NOT', 'OR', 'AND', 'THEN', 'EQV', 'EQ', 'NE', 'LT', 'LE', 'GT', 'GE', - 'ABS', 'EXP', + 'ABS', 'POW', ) # Tokens @@ -21,7 +21,7 @@ t_SEMI = r';' t_TAB = r'\t' t_COMMA = r'\,' t_ABS = r'\.ABS\.' -t_EXP = r'\.P\.' +t_POW = r'\.P\.' t_NOT = r'\.NOT\.' t_OR = r'\.OR\.' t_AND = r'\.AND\.' @@ -52,6 +52,7 @@ def t_NAME(t): 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" @@ -76,11 +77,13 @@ precedence = ( ('left','PLUS','MINUS'), ('left','TIMES','DIVIDE'), ('right','UMINUS'), - ('left','EXP'), + ('left','POW'), ('right', 'ABS', 'UPLUS') ) cards = [] +scopes = [] +targets = [] # Program level @@ -101,7 +104,7 @@ def p_labeled_card(t): ## DIMENSION def p_statement_dimension(t): 'statement : DIMENSION dimension_list' - t[0] = ('dimension', t[1], t[2]) + t[0] = ('dimension', t[2]) def p_dimension_list(t): 'dimension_list : NAME application' t[0] = [[t[1], tuple(t[2])]] @@ -112,13 +115,13 @@ def p_dimension_list_continue(t): ## END def p_end_of_program(t): "statement : END OF PROGRAM" - t[0] = ('end_program') + t[0] = ('end_program',) def p_end_of_conditional(t): "statement : END OF CONDITIONAL" - t[0] = ('end_conditional') + t[0] = ('end_conditional',) def p_end_of_functions(t): "statement : END OF FUNCTION" - t[0] = ('end_function') + t[0] = ('end_function',) ## INTEGER def p_integer(t): @@ -144,10 +147,12 @@ def p_print_format(t): ## THROUGH def p_through_for(t): 'statement : THROUGH NAME COMMA FOR NAME EQUALS expression COMMA expression COMMA expression' - t[0] = ('for', t[2], t[7], t[9], t[11]) + t[0] = ('for', t[2], t[5], t[7], t[9], t[11]) + scopes.append(t[2]) def p_through_map(t): 'statement : THROUGH NAME COMMA FOR VALUES OF NAME EQUALS value_list' t[0] = ('map', t[2], t[7], t[9]) + scopes.append(t[2]) def p_map(t): 'value_list : expression' t[0] = [t[1]] @@ -159,6 +164,7 @@ def p_map_continue(t): def p_transfer(t): "statement : TRANSFER TO NAME" t[0] = ('goto', t[3]) + targets.append(t[3]) ## WHENEVER def p_whenever_simple(t): @@ -173,7 +179,6 @@ def p_whenever_complex(t): # "statement : VECTOR VALUES assignlist" # t[0] = ('values',) + tuple(t[3]) - ## Assignment def p_statement_substitution(t): 'statement : NAME EQUALS expression' @@ -199,7 +204,7 @@ def p_expression_binop2(t): | expression GE expression | expression EQ expression | expression NE expression - | expression EXP expression + | expression POW expression ''' t[0] = (t[2][1:-1].lower(), t[1], t[3]) @@ -225,7 +230,7 @@ def p_expression_group(t): def p_expression_integer(t): 'expression : INTNUM' - t[0] = ('integer', t[1]) + t[0] = ('intnum', t[1]) def p_expression_float(t): 'expression : FLOATNUM' @@ -265,9 +270,110 @@ yacc.yacc() import sys, re -source = sys.stdin.read() -# Grotty hack to add end-of-statement delimiters -source = re.sub("\n([A-Z]|\t)", " ;\n\\1", source).rstrip() + " ;\n" -yacc.parse(source, debug=1) -for card in cards: - print card +indent = 0 + +def recode(cards): + "Rewrite the statement list." + # Find first INTEGER declaration, move it to the front. + for statement in cards: + if statement[1][0] == 'integer': + declaration = statement + cards.remove(declaration) + cards = [declaration] + cards + break + return cards + +def print_expr(t): + if t[0] == 'variable': + res = t[1] + if len(t) > 2: + for dim in t[2]: + res += "[" + dim[1] + "]" + return res + elif t[0] == 'apply': + return t[1] + `t[2]` + elif t[0] == 'plus': + return "(%s + %s)" % (print_expr(t[1]), print_expr(t[2])) + elif t[0] == 'minus': + return "(%s - %s)" % (print_expr(t[1]), print_expr(t[2])) + elif t[0] == 'times': + return "(%s * %s)" % (print_expr(t[1]), print_expr(t[2])) + elif t[0] == 'divide': + 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])) + elif t[0] == 'g': + 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])) + elif t[0] == 'ge': + 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])) + elif t[0] == 'ne': + return "(%s != %s)" % (print_expr(t[1]), print_expr(t[2])) + elif t[0] == 'pow': + 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])) + elif t[0] == 'or': + 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])) + elif t[0] == 'eqv': + return "(%s == %s)" % (print_expr(t[1]), print_expr(t[2])) + elif t[0] == 'abs': + return "abs(%s)" % print_expr(t[1]) + elif t[0] == '+': + return "%s" % print_expr(t[1]) + elif t[0] == '-': + return "(-%s)" % print_expr(t[1]) + elif t[0] in ('variable', 'intnum'): + return "%s" % print_expr(t[1]) + else: + return "***"+`t` + +def print_statement(statement): + global indent + if statement[0] == 'end_program': + return "/* END OF PROGRAM */" + elif statement[0] == 'dimension': + declaration = "int"; + for (var, dimlist) in statement[1]: + declaration += " " + var + for dim in dimlist: + declaration += "[" + dim[1] + "]" + declaration += ", " + return(declaration[:-2] + ";") + elif statement[0] == 'for': + print statement + (keyword, label, dummy, start, increment, predicate) = statement + indent += 1 + return "for (%s = %s; %s; %s += %s) {" % (dummy, print_expr(start), print_expr(predicate), dummy, print_expr(increment)) + elif statement[0] == 'if': + return "if (" + print_expr(statement[1]) + ") " + print_statement(statement[2]) + ";" + elif statement[0] == 'integer': + return "int " + ", ".join(statement[1:]) + ";" + 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" + yacc.parse(source) + cards = recode(cards) + + print "#include " + print "main(int argc, char *argv[])" + print "{" + for (label, statement) in cards: + if label in targets: + sys.stdout.write(label+":") + sys.stdout.write("\t" + " "*indent +print_statement(statement) + "\n") + if label in scopes: + indent -= 1 + print ("\t" + " "*indent) + "}" + print "}"