t_EQUALS = r'='
t_LPAREN = r'\('
t_RPAREN = r'\)'
-t_STRING = r'\$[^$]*\$'
t_DOTRANGE= r'\.\.\.'
reserved_map = { }
for r in reserved:
reserved_map[r] = r
+def t_STRING(t):
+ r'\$[^$]*\$'
+ t.value = t.value[1:-1]
+ return t
+
def t_NAME(t):
r'[A-Z][A-Z0-9_]*(\.(?!P))?'
t.type = reserved_map.get(t.value, 'NAME')
## PRINT_FORMAT
def p_print_format(t):
- 'statement : PRINT_FORMAT outlist'
- t[0] = ('print',) + tuple(t[2])
+ 'statement : PRINT_FORMAT NAME COMMA outlist'
+ t[0] = ('print', t[2]) + tuple(t[4])
+def p_print_format0(t):
+ 'statement : PRINT_FORMAT NAME'
+ t[0] = ('print', t[2])
# This is shared with SAVE DATA
def p_outlist_continue(t):
'outlist : outlist COMMA outval'
t[0] = t[1]
def p_range(t):
'range : NAME application DOTRANGE NAME application'
- t[0] = ('range', t[1], t[2], t[5])
+ t[0] = ('range', t[1], t[2][0], t[5][0])
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])
+ t[0] = ('remark', t[2])
def p_remark2(t):
'statement : COMMENT'
t[0] = ('remark',)
## READ_FORMAT
def p_read_format(t):
- 'statement : READ_FORMAT varlist'
- t[0] = ('read',) + tuple(t[2])
+ 'statement : READ_FORMAT NAME COMMA varlist'
+ t[0] = ('read', t[2]) + tuple(t[4])
# This is shared with RESTORE_DATA
def p_varlist_continue(t):
'varlist : varlist COMMA lval'
if var in refcount:
static[var] = statement[2]
else:
- format[var] = statement[2][1:-1]
+ format[var] = statement[2]
# Reorder code tuples so internal functions are just after entry points
for i in range(len(deck)):
(file, line, label, statement) = deck[i]
croak(card, "uninitialized format string" +`statement[1]`)
else:
(fmt, types) = fmt_convert(format[statement[1]])
- for (type, var) in zip(types, statement[2:]):
- typedict[currentfunc][var] = type
+ for (vtype, var) in zip(types, statement[2:]):
+ if type(var) == type(()) and var[0] == 'range':
+ if type == 'string':
+ typedict[currentfunc][var[1]] = 'char'
+ else:
+ typedict[currentfunc][var[1]] = vtype
+ else:
+ typedict[currentfunc][var] = vtype
# Type inference loop. We initialized for this by deducing types
# from READ FORMAT statements. INTEGER, and BOOLEAN declarations
# above. Now propagate markers of non-normalmode type through
"Compute the return type of an expression"
#print "->mode", t
if t[0] == 'variable':
- #print "<-mode of ", t[1]
+ #print "<-mode of ", t[1], typedict[currentfunc].get(t[1], normalmode)
return typedict[currentfunc].get(t[1], normalmode)
- elif t[0] in ('UMINUS', 'UPLUS', 'POW', 'ABS'):
+ elif t[0] in ('p', 'abs') or t[0] in ('+', '-') and len(t) == 2:
#print "<-mode of ", t[1]
return mode(t[1])
elif t[0] == 'intnum':
else:
left = mode(t[1])
right = mode(t[2])
+ #print "left mode %s, right mode %s" % (left, right)
if left == 'double' or right == 'double':
#print "<-mode of binary operand"
return 'double'
if left == 'int' or right == 'int':
#print "<-mode of binary operand"
return 'int'
- sys.write.stderr("mad: internal error while computing mode of %s\n"%t)
+ sys.stderr.write("mad: internal error while computing mode of %s\n" % `t`)
sys.exit(1)
def prinC1(t):
str = str[i+1:]
for i in range(count):
types += innertypes * count
+ elif str[0] == 'C':
+ i = 1
+ while str[i] in '0123456789':
+ i += 1
+ res += "%" + `count * int(str[1:i])` + "s"
+ str = str[i:]
+ types += ['string']
elif str[0] == 'F':
i = 1
while str[i] in '0123456789.':
#if defaulted:
# sys.stderr.write("warning: defaulted base type for %s\n" % ", ".join(defaulted))
declarations = ""
- for type in ('double', 'int', 'bool'):
- vars = filter(lambda x: types[x] == type, types.keys())
+ for vtype in ('double', 'int', 'bool'):
+ vars = filter(lambda x: types[x] == vtype, types.keys())
if vars:
- declarations += type + " " + ", ".join(vars) + "; "
+ declarations += vtype + " " + ", ".join(vars) + "; "
if declarations:
rep += " " + declarations[:-1] + "\n"
return rep
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:])) + ');'
+ inlist = []
+ for (inspec, intype) in zip(statement[2:], types):
+ if type(inspec) == type(""):
+ inlist.append("&" + inspec)
+ elif type(inspec) == type(()) and inspec[0] == 'range' and intype == 'string':
+ if inspec[2] == ('intnum', '1'):
+ inlist.append(print_C_expr(('variable', inspec[1])))
+ else:
+ inlist.append(print_C_expr(('+',('variable', inspec[1]),('-',inspec[2],('intnum', '1')))))
+ else:
+ sys.stderr.write("unsupported type in READ FORMAT\n")
+ sys.exit(1)
+ return 'scanf("' + fmt + '", ' + ', '.join(inlist) + ');'
elif statement[0] == 'remark':
if len(statement) == 1:
return "\n"
# Put them after every newline, then remove if they're followed
# by whitespace and a continuation digit
source = source.replace("\n", " eos\n")
- source = re.sub(';\n(\s*)[0-9]+', '\n\\1', source)
+ source = re.sub('eos\n(\s*)[0-9]+', '\n\\1', source)
# Transform some adjacent groups of keywords into
# agglomerates. This lets us get away with stuff like SET LIST
# TO LIST that the parser would otherwise choke on, because