]> thyrsus.com Git - mad.git/commitdiff
First version of working format converter.
authorEric S. Raymond <esr@thyrsus,com>
Tue, 20 Jan 2004 11:20:59 +0000 (11:20 +0000)
committerEric S. Raymond <esr@thyrsus,com>
Tue, 20 Jan 2004 11:20:59 +0000 (11:20 +0000)
mad

diff --git a/mad b/mad
index 805448cb591fb9f1312d5eac81574db47ded6ab4..d5614de585ef630efa803de6693b9684b69d0a21 100755 (executable)
--- a/mad
+++ b/mad
@@ -166,7 +166,6 @@ def p_map_continue(t):
 def p_transfer(t):
     "statement : TRANSFER TO NAME"
     t[0] = ('goto', t[3])
-    print "Foo!", t[3]
     targets.append(t[3])
 
 ## WHENEVER
@@ -263,7 +262,10 @@ def p_expression_tail_nonempty(t):
 
 def p_expression_name(t):
     'expression : NAME'
-    t[0] = ('variable', t[1])
+    var = t[1]
+    t[0] = ('variable', var)
+    if var not in integers + bools + floats + untyped:
+        untyped.append(var)
 
 # Error handling
 
@@ -279,6 +281,7 @@ integers = []
 floats = []
 bools = []
 dimensions = {}
+static = {}
 
 # Map MAD intrinsics to C library functions
 madfunc_map = {'elog':'log'}
@@ -291,6 +294,7 @@ def declare(var, lst):
 def analyze(deck):
     "Gather variable types."
     global integers, floats, bools
+    # Mine the code for compile-time directives
     for (label, statement) in deck:
         if statement[0] == 'integer':
             print "Bar!", statement
@@ -303,6 +307,8 @@ def analyze(deck):
             var = statement[1]
             if var not in integers + bools + floats + untyped:
                 untyped.append(var)
+        if statement[0] == 'values':
+            static[statement[1]] = statement[2]
 
 def print_expr(t):
     if t[0] == 'variable':
@@ -358,7 +364,7 @@ def print_expr(t):
         return "***"+`t`
 
 def print_statement(statement):
-    if statement[0] in ('dimension', 'end_program', 'integer'):
+    if statement[0] in ('dimension', 'end_program', 'integer', 'values'):
         pass
     elif statement[0] == 'for':
         (keyword, label, dummy, start, increment, predicate) = statement
@@ -374,7 +380,48 @@ def print_statement(statement):
     elif statement[0] == 'substitution':
         return statement[1] + " = " + print_expr(statement[2]) + ";"
     else:
-        return(`statement`)
+        return("// " + `statement`)
+
+def fmt_convert(str):
+    "Convert MAD format string to C printf/scanf"
+    res = ""
+    str = str[1:-1]
+    while True:
+        if str[0] == "*":
+            break
+        elif str[0] == 'S':
+            i = 0
+            while str[i].isdigit():
+                i += 1
+            if i <= 0:
+                sys.stderr.write("invalid spacer in %s\n" % str)
+                sys.exit(1)
+            count = int(str[:i])
+            res += " " * count
+            str = str[i:]
+            break
+        # 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.exit(1)
+        count = int(str[:i])
+        str = str[i:]
+        if str[0] == 'F':
+            i = 1
+            while str[i] in "0123456789.":
+                i += 1
+            res += ("%" + str[1:i] + "f") * count
+            str = str[i:]
+        elif str[0] == 'H':
+            res += str[1:count+1]
+            str = str[count+1:]
+        else:
+            sys.stderr.write("invalid field code in format string!")
+            sys.exit(1)
+    return res
 
 if __name__ == '__main__':
     source = sys.stdin.read()
@@ -392,9 +439,11 @@ if __name__ == '__main__':
     if bools:
         print "\tint " + ", ".join(bools) + ";\t/* boolean */"
     if untyped:
-        print "\tint " + ", ".join(untyped) + ";\t/* untyped */"
+        print "\tfloat " + ", ".join(untyped) + ";\t/* untyped */"
     if 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: