| 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) |