1212# type ::= product | sum
1313# product ::= fields ["attributes" fields]
1414# fields ::= "(" { field, "," } field ")"
15- # field ::= TypeId [ "?" | "*"] [Id]
15+ # field ::= TypeId { "?" | "*" } [Id]
1616# sum ::= constructor { "|" constructor } ["attributes" fields]
1717# constructor ::= ConstructorId [fields]
1818#
1919# [1] "The Zephyr Abstract Syntax Description Language" by Wang, et. al. See
2020# http://asdl.sourceforge.net/
2121#-------------------------------------------------------------------------------
2222from collections import namedtuple
23+ import enum
2324import re
2425
2526__all__ = [
@@ -64,34 +65,43 @@ def __init__(self, name, fields=None):
6465 def __repr__ (self ):
6566 return 'Constructor({0.name}, {0.fields})' .format (self )
6667
68+ class Quantifier (enum .Enum ):
69+ OPTIONAL = enum .auto ()
70+ SEQUENCE = enum .auto ()
71+
6772class Field (AST ):
68- def __init__ (self , type , name = None , seq = False , opt = False ):
73+ def __init__ (self , type , name = None , quantifiers = None ):
6974 self .type = type
7075 self .name = name
71- self .seq = seq
72- self .opt = opt
76+ self .seq = False
77+ self .opt = False
78+ self .quantifiers = quantifiers or []
79+ if len (self .quantifiers ) > 0 :
80+ self .seq = self .quantifiers [- 1 ] is Quantifier .SEQUENCE
81+ self .opt = self .quantifiers [- 1 ] is Quantifier .OPTIONAL
7382
7483 def __str__ (self ):
75- if self . seq :
76- extra = "*"
77- elif self . opt :
78- extra = "? "
79- else :
80- extra = ""
84+ extra = ""
85+ for mod in self . quantifiers :
86+ if mod is Quantifier . SEQUENCE :
87+ extra + = "* "
88+ elif mod is Quantifier . OPTIONAL :
89+ extra + = "? "
8190
8291 return "{}{} {}" .format (self .type , extra , self .name )
8392
8493 def __repr__ (self ):
85- if self .seq :
86- extra = ", seq=True"
87- elif self .opt :
88- extra = ", opt=True"
89- else :
90- extra = ""
94+ extra = ""
95+ for mod in self .quantifiers :
96+ if mod is Quantifier .SEQUENCE :
97+ extra += ", SEQUENCE"
98+ elif mod is Quantifier .OPTIONAL :
99+ extra += ", OPTIONAL"
100+
91101 if self .name is None :
92- return 'Field({0.type}{1})' .format (self , extra )
102+ return 'Field({0.type}, quantifiers=[ {1}] )' .format (self , extra )
93103 else :
94- return 'Field({0.type}, {0.name}{1})' .format (self , extra )
104+ return 'Field({0.type}, {0.name}, quantifiers=[ {1}] )' .format (self , extra )
95105
96106class Sum (AST ):
97107 def __init__ (self , types , attributes = None ):
@@ -314,10 +324,10 @@ def _parse_fields(self):
314324 self ._match (TokenKind .LParen )
315325 while self .cur_token .kind == TokenKind .TypeId :
316326 typename = self ._advance ()
317- is_seq , is_opt = self ._parse_optional_field_quantifier ()
327+ quantifiers = self ._parse_optional_field_quantifier ()
318328 id = (self ._advance () if self .cur_token .kind in self ._id_kinds
319329 else None )
320- fields .append (Field (typename , id , seq = is_seq , opt = is_opt ))
330+ fields .append (Field (typename , id , quantifiers = quantifiers ))
321331 if self .cur_token .kind == TokenKind .RParen :
322332 break
323333 elif self .cur_token .kind == TokenKind .Comma :
@@ -339,14 +349,14 @@ def _parse_optional_attributes(self):
339349 return None
340350
341351 def _parse_optional_field_quantifier (self ):
342- is_seq , is_opt = False , False
343- if self .cur_token .kind == TokenKind .Asterisk :
344- is_seq = True
345- self . _advance ( )
346- elif self .cur_token .kind == TokenKind .Question :
347- is_opt = True
352+ quantifiers = []
353+ while self .cur_token .kind in ( TokenKind .Asterisk , TokenKind . Question ) :
354+ if self . cur_token . kind == TokenKind . Asterisk :
355+ quantifiers . append ( Quantifier . SEQUENCE )
356+ elif self .cur_token .kind == TokenKind .Question :
357+ quantifiers . append ( Quantifier . OPTIONAL )
348358 self ._advance ()
349- return is_seq , is_opt
359+ return quantifiers
350360
351361 def _advance (self ):
352362 """ Return the value of the current token and read the next one into
0 commit comments