Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 1 | """An implementation of the Zephyr Abstract Syntax Definition Language. |
| 2 | |
| 3 | See http://asdl.sourceforge.net/ and |
Senthil Kumaran | 2b80fa6 | 2010-05-18 13:48:45 +0000 | [diff] [blame] | 4 | http://www.cs.princeton.edu/research/techreps/TR-554-97 |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 5 | |
| 6 | Only supports top level module decl, not view. I'm guessing that view |
| 7 | is intended to support the browser and I'm not interested in the |
| 8 | browser. |
Martin v. Löwis | eae93b7 | 2006-02-28 00:12:47 +0000 | [diff] [blame] | 9 | |
| 10 | Changes for Python: Add support for module versions |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 11 | """ |
| 12 | |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 13 | import os |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 14 | import sys |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 15 | import traceback |
| 16 | |
| 17 | import spark |
| 18 | |
Eli Bendersky | b788a38 | 2013-09-26 06:31:32 -0700 | [diff] [blame] | 19 | def output(*strings): |
| 20 | for s in strings: |
| 21 | sys.stdout.write(str(s) + "\n") |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 22 | |
| 23 | |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 24 | class Token(object): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 25 | # spark seems to dispatch in the parser based on a token's |
| 26 | # type attribute |
| 27 | def __init__(self, type, lineno): |
| 28 | self.type = type |
| 29 | self.lineno = lineno |
| 30 | |
| 31 | def __str__(self): |
| 32 | return self.type |
| 33 | |
| 34 | def __repr__(self): |
| 35 | return str(self) |
| 36 | |
| 37 | class Id(Token): |
| 38 | def __init__(self, value, lineno): |
| 39 | self.type = 'Id' |
| 40 | self.value = value |
| 41 | self.lineno = lineno |
| 42 | |
| 43 | def __str__(self): |
| 44 | return self.value |
Tim Peters | 710ab3b | 2006-02-28 18:30:36 +0000 | [diff] [blame] | 45 | |
Martin v. Löwis | eae93b7 | 2006-02-28 00:12:47 +0000 | [diff] [blame] | 46 | class String(Token): |
| 47 | def __init__(self, value, lineno): |
| 48 | self.type = 'String' |
| 49 | self.value = value |
| 50 | self.lineno = lineno |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 51 | |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 52 | class ASDLSyntaxError(Exception): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 53 | |
| 54 | def __init__(self, lineno, token=None, msg=None): |
| 55 | self.lineno = lineno |
| 56 | self.token = token |
| 57 | self.msg = msg |
| 58 | |
| 59 | def __str__(self): |
| 60 | if self.msg is None: |
| 61 | return "Error at '%s', line %d" % (self.token, self.lineno) |
| 62 | else: |
| 63 | return "%s, line %d" % (self.msg, self.lineno) |
| 64 | |
| 65 | class ASDLScanner(spark.GenericScanner, object): |
| 66 | |
| 67 | def tokenize(self, input): |
| 68 | self.rv = [] |
| 69 | self.lineno = 1 |
| 70 | super(ASDLScanner, self).tokenize(input) |
| 71 | return self.rv |
| 72 | |
| 73 | def t_id(self, s): |
| 74 | r"[\w\.]+" |
| 75 | # XXX doesn't distinguish upper vs. lower, which is |
| 76 | # significant for ASDL. |
| 77 | self.rv.append(Id(s, self.lineno)) |
Tim Peters | 710ab3b | 2006-02-28 18:30:36 +0000 | [diff] [blame] | 78 | |
Martin v. Löwis | eae93b7 | 2006-02-28 00:12:47 +0000 | [diff] [blame] | 79 | def t_string(self, s): |
| 80 | r'"[^"]*"' |
| 81 | self.rv.append(String(s, self.lineno)) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 82 | |
| 83 | def t_xxx(self, s): # not sure what this production means |
| 84 | r"<=" |
| 85 | self.rv.append(Token(s, self.lineno)) |
| 86 | |
| 87 | def t_punctuation(self, s): |
| 88 | r"[\{\}\*\=\|\(\)\,\?\:]" |
| 89 | self.rv.append(Token(s, self.lineno)) |
| 90 | |
| 91 | def t_comment(self, s): |
| 92 | r"\-\-[^\n]*" |
| 93 | pass |
| 94 | |
| 95 | def t_newline(self, s): |
| 96 | r"\n" |
| 97 | self.lineno += 1 |
| 98 | |
| 99 | def t_whitespace(self, s): |
| 100 | r"[ \t]+" |
| 101 | pass |
| 102 | |
| 103 | def t_default(self, s): |
| 104 | r" . +" |
Collin Winter | 4902e69 | 2007-08-30 18:18:27 +0000 | [diff] [blame] | 105 | raise ValueError("unmatched input: %r" % s) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 106 | |
| 107 | class ASDLParser(spark.GenericParser, object): |
| 108 | def __init__(self): |
| 109 | super(ASDLParser, self).__init__("module") |
| 110 | |
| 111 | def typestring(self, tok): |
| 112 | return tok.type |
| 113 | |
| 114 | def error(self, tok): |
| 115 | raise ASDLSyntaxError(tok.lineno, tok) |
| 116 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 117 | def p_module_0(self, info): |
Benjamin Peterson | 6cb2b92 | 2011-03-12 18:28:16 -0600 | [diff] [blame] | 118 | " module ::= Id Id { } " |
| 119 | module, name, _0, _1 = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 120 | if module.value != "module": |
| 121 | raise ASDLSyntaxError(module.lineno, |
| 122 | msg="expected 'module', found %s" % module) |
Benjamin Peterson | 6cb2b92 | 2011-03-12 18:28:16 -0600 | [diff] [blame] | 123 | return Module(name, None) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 124 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 125 | def p_module(self, info): |
Benjamin Peterson | 6cb2b92 | 2011-03-12 18:28:16 -0600 | [diff] [blame] | 126 | " module ::= Id Id { definitions } " |
| 127 | module, name, _0, definitions, _1 = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 128 | if module.value != "module": |
| 129 | raise ASDLSyntaxError(module.lineno, |
| 130 | msg="expected 'module', found %s" % module) |
Benjamin Peterson | 6cb2b92 | 2011-03-12 18:28:16 -0600 | [diff] [blame] | 131 | return Module(name, definitions) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 132 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 133 | def p_definition_0(self, definition): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 134 | " definitions ::= definition " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 135 | return definition[0] |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 136 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 137 | def p_definition_1(self, definitions): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 138 | " definitions ::= definition definitions " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 139 | return definitions[0] + definitions[1] |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 140 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 141 | def p_definition(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 142 | " definition ::= Id = type " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 143 | id, _, type = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 144 | return [Type(id, type)] |
| 145 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 146 | def p_type_0(self, product): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 147 | " type ::= product " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 148 | return product[0] |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 149 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 150 | def p_type_1(self, sum): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 151 | " type ::= sum " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 152 | return Sum(sum[0]) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 153 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 154 | def p_type_2(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 155 | " type ::= sum Id ( fields ) " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 156 | sum, id, _0, attributes, _1 = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 157 | if id.value != "attributes": |
| 158 | raise ASDLSyntaxError(id.lineno, |
| 159 | msg="expected attributes, found %s" % id) |
| 160 | return Sum(sum, attributes) |
| 161 | |
Benjamin Peterson | cda75be | 2013-03-18 10:48:58 -0700 | [diff] [blame] | 162 | def p_product_0(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 163 | " product ::= ( fields ) " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 164 | _0, fields, _1 = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 165 | return Product(fields) |
| 166 | |
Benjamin Peterson | cda75be | 2013-03-18 10:48:58 -0700 | [diff] [blame] | 167 | def p_product_1(self, info): |
| 168 | " product ::= ( fields ) Id ( fields ) " |
| 169 | _0, fields, _1, id, _2, attributes, _3 = info |
| 170 | if id.value != "attributes": |
| 171 | raise ASDLSyntaxError(id.lineno, |
| 172 | msg="expected attributes, found %s" % id) |
| 173 | return Product(fields, attributes) |
| 174 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 175 | def p_sum_0(self, constructor): |
Georg Brandl | 1f01deb | 2009-01-03 22:47:39 +0000 | [diff] [blame] | 176 | " sum ::= constructor " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 177 | return [constructor[0]] |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 178 | |
Neal Norwitz | bda355f | 2008-03-17 18:03:56 +0000 | [diff] [blame] | 179 | def p_sum_1(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 180 | " sum ::= constructor | sum " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 181 | constructor, _, sum = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 182 | return [constructor] + sum |
| 183 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 184 | def p_sum_2(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 185 | " sum ::= constructor | sum " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 186 | constructor, _, sum = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 187 | return [constructor] + sum |
| 188 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 189 | def p_constructor_0(self, id): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 190 | " constructor ::= Id " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 191 | return Constructor(id[0]) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 192 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 193 | def p_constructor_1(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 194 | " constructor ::= Id ( fields ) " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 195 | id, _0, fields, _1 = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 196 | return Constructor(id, fields) |
| 197 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 198 | def p_fields_0(self, field): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 199 | " fields ::= field " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 200 | return [field[0]] |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 201 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 202 | def p_fields_1(self, info): |
Benjamin Peterson | 481ae50 | 2012-07-31 21:41:56 -0700 | [diff] [blame] | 203 | " fields ::= fields , field " |
| 204 | fields, _, field = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 205 | return fields + [field] |
| 206 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 207 | def p_field_0(self, type_): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 208 | " field ::= Id " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 209 | return Field(type_[0]) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 210 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 211 | def p_field_1(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 212 | " field ::= Id Id " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 213 | type, name = info |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 214 | return Field(type, name) |
| 215 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 216 | def p_field_2(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 217 | " field ::= Id * Id " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 218 | type, _, name = info |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 219 | return Field(type, name, seq=True) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 220 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 221 | def p_field_3(self, info): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 222 | " field ::= Id ? Id " |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 223 | type, _, name = info |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 224 | return Field(type, name, opt=True) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 225 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 226 | def p_field_4(self, type_): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 227 | " field ::= Id * " |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 228 | return Field(type_[0], seq=True) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 229 | |
Guido van Rossum | 1bc535d | 2007-05-15 18:46:22 +0000 | [diff] [blame] | 230 | def p_field_5(self, type_): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 231 | " field ::= Id ? " |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 232 | return Field(type[0], opt=True) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 233 | |
Benjamin Peterson | 442f209 | 2012-12-06 17:41:04 -0500 | [diff] [blame] | 234 | builtin_types = ("identifier", "string", "bytes", "int", "object", "singleton") |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 235 | |
| 236 | # below is a collection of classes to capture the AST of an AST :-) |
| 237 | # not sure if any of the methods are useful yet, but I'm adding them |
| 238 | # piecemeal as they seem helpful |
| 239 | |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 240 | class AST(object): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 241 | pass # a marker class |
| 242 | |
| 243 | class Module(AST): |
Benjamin Peterson | 6cb2b92 | 2011-03-12 18:28:16 -0600 | [diff] [blame] | 244 | def __init__(self, name, dfns): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 245 | self.name = name |
| 246 | self.dfns = dfns |
| 247 | self.types = {} # maps type name to value (from dfns) |
| 248 | for type in dfns: |
| 249 | self.types[type.name.value] = type.value |
| 250 | |
| 251 | def __repr__(self): |
| 252 | return "Module(%s, %s)" % (self.name, self.dfns) |
| 253 | |
| 254 | class Type(AST): |
| 255 | def __init__(self, name, value): |
| 256 | self.name = name |
| 257 | self.value = value |
| 258 | |
| 259 | def __repr__(self): |
| 260 | return "Type(%s, %s)" % (self.name, self.value) |
| 261 | |
| 262 | class Constructor(AST): |
| 263 | def __init__(self, name, fields=None): |
| 264 | self.name = name |
| 265 | self.fields = fields or [] |
| 266 | |
| 267 | def __repr__(self): |
| 268 | return "Constructor(%s, %s)" % (self.name, self.fields) |
| 269 | |
| 270 | class Field(AST): |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 271 | def __init__(self, type, name=None, seq=False, opt=False): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 272 | self.type = type |
| 273 | self.name = name |
| 274 | self.seq = seq |
| 275 | self.opt = opt |
| 276 | |
| 277 | def __repr__(self): |
| 278 | if self.seq: |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 279 | extra = ", seq=True" |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 280 | elif self.opt: |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 281 | extra = ", opt=True" |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 282 | else: |
| 283 | extra = "" |
| 284 | if self.name is None: |
| 285 | return "Field(%s%s)" % (self.type, extra) |
| 286 | else: |
| 287 | return "Field(%s, %s%s)" % (self.type, self.name, extra) |
| 288 | |
| 289 | class Sum(AST): |
| 290 | def __init__(self, types, attributes=None): |
| 291 | self.types = types |
| 292 | self.attributes = attributes or [] |
| 293 | |
| 294 | def __repr__(self): |
| 295 | if self.attributes is None: |
| 296 | return "Sum(%s)" % self.types |
| 297 | else: |
| 298 | return "Sum(%s, %s)" % (self.types, self.attributes) |
| 299 | |
| 300 | class Product(AST): |
Benjamin Peterson | cda75be | 2013-03-18 10:48:58 -0700 | [diff] [blame] | 301 | def __init__(self, fields, attributes=None): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 302 | self.fields = fields |
Benjamin Peterson | cda75be | 2013-03-18 10:48:58 -0700 | [diff] [blame] | 303 | self.attributes = attributes or [] |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 304 | |
| 305 | def __repr__(self): |
Benjamin Peterson | cda75be | 2013-03-18 10:48:58 -0700 | [diff] [blame] | 306 | if self.attributes is None: |
| 307 | return "Product(%s)" % self.fields |
| 308 | else: |
| 309 | return "Product(%s, %s)" % (self.fields, self.attributes) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 310 | |
| 311 | class VisitorBase(object): |
| 312 | |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 313 | def __init__(self, skip=False): |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 314 | self.cache = {} |
| 315 | self.skip = skip |
| 316 | |
| 317 | def visit(self, object, *args): |
| 318 | meth = self._dispatch(object) |
| 319 | if meth is None: |
| 320 | return |
| 321 | try: |
| 322 | meth(object, *args) |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 323 | except Exception: |
Alexandre Vassalotti | df6f3fd | 2009-07-17 05:35:59 +0000 | [diff] [blame] | 324 | output("Error visiting" + repr(object)) |
| 325 | output(str(sys.exc_info()[1])) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 326 | traceback.print_exc() |
| 327 | # XXX hack |
| 328 | if hasattr(self, 'file'): |
| 329 | self.file.flush() |
| 330 | os._exit(1) |
| 331 | |
| 332 | def _dispatch(self, object): |
| 333 | assert isinstance(object, AST), repr(object) |
| 334 | klass = object.__class__ |
| 335 | meth = self.cache.get(klass) |
| 336 | if meth is None: |
| 337 | methname = "visit" + klass.__name__ |
| 338 | if self.skip: |
| 339 | meth = getattr(self, methname, None) |
| 340 | else: |
| 341 | meth = getattr(self, methname) |
| 342 | self.cache[klass] = meth |
| 343 | return meth |
| 344 | |
| 345 | class Check(VisitorBase): |
| 346 | |
| 347 | def __init__(self): |
Benjamin Peterson | 87c8d87 | 2009-06-11 22:54:11 +0000 | [diff] [blame] | 348 | super(Check, self).__init__(skip=True) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 349 | self.cons = {} |
| 350 | self.errors = 0 |
| 351 | self.types = {} |
| 352 | |
| 353 | def visitModule(self, mod): |
| 354 | for dfn in mod.dfns: |
| 355 | self.visit(dfn) |
| 356 | |
| 357 | def visitType(self, type): |
| 358 | self.visit(type.value, str(type.name)) |
| 359 | |
| 360 | def visitSum(self, sum, name): |
| 361 | for t in sum.types: |
| 362 | self.visit(t, name) |
| 363 | |
| 364 | def visitConstructor(self, cons, name): |
| 365 | key = str(cons.name) |
| 366 | conflict = self.cons.get(key) |
| 367 | if conflict is None: |
| 368 | self.cons[key] = name |
| 369 | else: |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 370 | output("Redefinition of constructor %s" % key) |
| 371 | output("Defined in %s and %s" % (conflict, name)) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 372 | self.errors += 1 |
| 373 | for f in cons.fields: |
| 374 | self.visit(f, key) |
| 375 | |
| 376 | def visitField(self, field, name): |
| 377 | key = str(field.type) |
| 378 | l = self.types.setdefault(key, []) |
| 379 | l.append(name) |
| 380 | |
| 381 | def visitProduct(self, prod, name): |
| 382 | for f in prod.fields: |
| 383 | self.visit(f, name) |
| 384 | |
| 385 | def check(mod): |
| 386 | v = Check() |
| 387 | v.visit(mod) |
| 388 | |
| 389 | for t in v.types: |
Fred Drake | 34e4f52 | 2006-12-29 04:42:48 +0000 | [diff] [blame] | 390 | if t not in mod.types and not t in builtin_types: |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 391 | v.errors += 1 |
| 392 | uses = ", ".join(v.types[t]) |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 393 | output("Undefined type %s, used in %s" % (t, uses)) |
Tim Peters | 536cf99 | 2005-12-25 23:18:31 +0000 | [diff] [blame] | 394 | |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 395 | return not v.errors |
| 396 | |
| 397 | def parse(file): |
| 398 | scanner = ASDLScanner() |
| 399 | parser = ASDLParser() |
| 400 | |
Eli Bendersky | 1891cff | 2013-09-26 09:35:39 -0700 | [diff] [blame] | 401 | f = open(file) |
Eli Bendersky | 9908123 | 2013-09-26 06:41:36 -0700 | [diff] [blame] | 402 | try: |
Eli Bendersky | 58fe1b1 | 2013-09-26 06:32:22 -0700 | [diff] [blame] | 403 | buf = f.read() |
Eli Bendersky | 9908123 | 2013-09-26 06:41:36 -0700 | [diff] [blame] | 404 | finally: |
| 405 | f.close() |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 406 | tokens = scanner.tokenize(buf) |
| 407 | try: |
| 408 | return parser.parse(tokens) |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 409 | except ASDLSyntaxError: |
Georg Brandl | 8a73278 | 2009-04-12 11:34:13 +0000 | [diff] [blame] | 410 | err = sys.exc_info()[1] |
| 411 | output(str(err)) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 412 | lines = buf.split("\n") |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 413 | output(lines[err.lineno - 1]) # lines starts at 0, files at 1 |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 414 | |
| 415 | if __name__ == "__main__": |
| 416 | import glob |
| 417 | import sys |
| 418 | |
| 419 | if len(sys.argv) > 1: |
| 420 | files = sys.argv[1:] |
| 421 | else: |
| 422 | testdir = "tests" |
| 423 | files = glob.glob(testdir + "/*.asdl") |
Tim Peters | 536cf99 | 2005-12-25 23:18:31 +0000 | [diff] [blame] | 424 | |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 425 | for file in files: |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 426 | output(file) |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 427 | mod = parse(file) |
Georg Brandl | 8a73278 | 2009-04-12 11:34:13 +0000 | [diff] [blame] | 428 | if not mod: |
| 429 | break |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 430 | output("module", mod.name) |
| 431 | output(len(mod.dfns), "definitions") |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 432 | if not check(mod): |
Guido van Rossum | 805365e | 2007-05-07 22:24:25 +0000 | [diff] [blame] | 433 | output("Check failed") |
Jeremy Hylton | 3e0055f | 2005-10-20 19:59:25 +0000 | [diff] [blame] | 434 | else: |
| 435 | for dfn in mod.dfns: |
Eli Bendersky | b788a38 | 2013-09-26 06:31:32 -0700 | [diff] [blame] | 436 | output(dfn.name, dfn.value) |