17db96d56Sopenharmony_ci#------------------------------------------------------------------------------- 27db96d56Sopenharmony_ci# Parser for ASDL [1] definition files. Reads in an ASDL description and parses 37db96d56Sopenharmony_ci# it into an AST that describes it. 47db96d56Sopenharmony_ci# 57db96d56Sopenharmony_ci# The EBNF we're parsing here: Figure 1 of the paper [1]. Extended to support 67db96d56Sopenharmony_ci# modules and attributes after a product. Words starting with Capital letters 77db96d56Sopenharmony_ci# are terminals. Literal tokens are in "double quotes". Others are 87db96d56Sopenharmony_ci# non-terminals. Id is either TokenId or ConstructorId. 97db96d56Sopenharmony_ci# 107db96d56Sopenharmony_ci# module ::= "module" Id "{" [definitions] "}" 117db96d56Sopenharmony_ci# definitions ::= { TypeId "=" type } 127db96d56Sopenharmony_ci# type ::= product | sum 137db96d56Sopenharmony_ci# product ::= fields ["attributes" fields] 147db96d56Sopenharmony_ci# fields ::= "(" { field, "," } field ")" 157db96d56Sopenharmony_ci# field ::= TypeId ["?" | "*"] [Id] 167db96d56Sopenharmony_ci# sum ::= constructor { "|" constructor } ["attributes" fields] 177db96d56Sopenharmony_ci# constructor ::= ConstructorId [fields] 187db96d56Sopenharmony_ci# 197db96d56Sopenharmony_ci# [1] "The Zephyr Abstract Syntax Description Language" by Wang, et. al. See 207db96d56Sopenharmony_ci# http://asdl.sourceforge.net/ 217db96d56Sopenharmony_ci#------------------------------------------------------------------------------- 227db96d56Sopenharmony_cifrom collections import namedtuple 237db96d56Sopenharmony_ciimport re 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci__all__ = [ 267db96d56Sopenharmony_ci 'builtin_types', 'parse', 'AST', 'Module', 'Type', 'Constructor', 277db96d56Sopenharmony_ci 'Field', 'Sum', 'Product', 'VisitorBase', 'Check', 'check'] 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci# The following classes define nodes into which the ASDL description is parsed. 307db96d56Sopenharmony_ci# Note: this is a "meta-AST". ASDL files (such as Python.asdl) describe the AST 317db96d56Sopenharmony_ci# structure used by a programming language. But ASDL files themselves need to be 327db96d56Sopenharmony_ci# parsed. This module parses ASDL files and uses a simple AST to represent them. 337db96d56Sopenharmony_ci# See the EBNF at the top of the file to understand the logical connection 347db96d56Sopenharmony_ci# between the various node types. 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_cibuiltin_types = {'identifier', 'string', 'int', 'constant'} 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ciclass AST: 397db96d56Sopenharmony_ci def __repr__(self): 407db96d56Sopenharmony_ci raise NotImplementedError 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ciclass Module(AST): 437db96d56Sopenharmony_ci def __init__(self, name, dfns): 447db96d56Sopenharmony_ci self.name = name 457db96d56Sopenharmony_ci self.dfns = dfns 467db96d56Sopenharmony_ci self.types = {type.name: type.value for type in dfns} 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci def __repr__(self): 497db96d56Sopenharmony_ci return 'Module({0.name}, {0.dfns})'.format(self) 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ciclass Type(AST): 527db96d56Sopenharmony_ci def __init__(self, name, value): 537db96d56Sopenharmony_ci self.name = name 547db96d56Sopenharmony_ci self.value = value 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_ci def __repr__(self): 577db96d56Sopenharmony_ci return 'Type({0.name}, {0.value})'.format(self) 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ciclass Constructor(AST): 607db96d56Sopenharmony_ci def __init__(self, name, fields=None): 617db96d56Sopenharmony_ci self.name = name 627db96d56Sopenharmony_ci self.fields = fields or [] 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci def __repr__(self): 657db96d56Sopenharmony_ci return 'Constructor({0.name}, {0.fields})'.format(self) 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ciclass Field(AST): 687db96d56Sopenharmony_ci def __init__(self, type, name=None, seq=False, opt=False): 697db96d56Sopenharmony_ci self.type = type 707db96d56Sopenharmony_ci self.name = name 717db96d56Sopenharmony_ci self.seq = seq 727db96d56Sopenharmony_ci self.opt = opt 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci def __str__(self): 757db96d56Sopenharmony_ci if self.seq: 767db96d56Sopenharmony_ci extra = "*" 777db96d56Sopenharmony_ci elif self.opt: 787db96d56Sopenharmony_ci extra = "?" 797db96d56Sopenharmony_ci else: 807db96d56Sopenharmony_ci extra = "" 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ci return "{}{} {}".format(self.type, extra, self.name) 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci def __repr__(self): 857db96d56Sopenharmony_ci if self.seq: 867db96d56Sopenharmony_ci extra = ", seq=True" 877db96d56Sopenharmony_ci elif self.opt: 887db96d56Sopenharmony_ci extra = ", opt=True" 897db96d56Sopenharmony_ci else: 907db96d56Sopenharmony_ci extra = "" 917db96d56Sopenharmony_ci if self.name is None: 927db96d56Sopenharmony_ci return 'Field({0.type}{1})'.format(self, extra) 937db96d56Sopenharmony_ci else: 947db96d56Sopenharmony_ci return 'Field({0.type}, {0.name}{1})'.format(self, extra) 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ciclass Sum(AST): 977db96d56Sopenharmony_ci def __init__(self, types, attributes=None): 987db96d56Sopenharmony_ci self.types = types 997db96d56Sopenharmony_ci self.attributes = attributes or [] 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci def __repr__(self): 1027db96d56Sopenharmony_ci if self.attributes: 1037db96d56Sopenharmony_ci return 'Sum({0.types}, {0.attributes})'.format(self) 1047db96d56Sopenharmony_ci else: 1057db96d56Sopenharmony_ci return 'Sum({0.types})'.format(self) 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ciclass Product(AST): 1087db96d56Sopenharmony_ci def __init__(self, fields, attributes=None): 1097db96d56Sopenharmony_ci self.fields = fields 1107db96d56Sopenharmony_ci self.attributes = attributes or [] 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci def __repr__(self): 1137db96d56Sopenharmony_ci if self.attributes: 1147db96d56Sopenharmony_ci return 'Product({0.fields}, {0.attributes})'.format(self) 1157db96d56Sopenharmony_ci else: 1167db96d56Sopenharmony_ci return 'Product({0.fields})'.format(self) 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci# A generic visitor for the meta-AST that describes ASDL. This can be used by 1197db96d56Sopenharmony_ci# emitters. Note that this visitor does not provide a generic visit method, so a 1207db96d56Sopenharmony_ci# subclass needs to define visit methods from visitModule to as deep as the 1217db96d56Sopenharmony_ci# interesting node. 1227db96d56Sopenharmony_ci# We also define a Check visitor that makes sure the parsed ASDL is well-formed. 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ciclass VisitorBase(object): 1257db96d56Sopenharmony_ci """Generic tree visitor for ASTs.""" 1267db96d56Sopenharmony_ci def __init__(self): 1277db96d56Sopenharmony_ci self.cache = {} 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci def visit(self, obj, *args): 1307db96d56Sopenharmony_ci klass = obj.__class__ 1317db96d56Sopenharmony_ci meth = self.cache.get(klass) 1327db96d56Sopenharmony_ci if meth is None: 1337db96d56Sopenharmony_ci methname = "visit" + klass.__name__ 1347db96d56Sopenharmony_ci meth = getattr(self, methname, None) 1357db96d56Sopenharmony_ci self.cache[klass] = meth 1367db96d56Sopenharmony_ci if meth: 1377db96d56Sopenharmony_ci try: 1387db96d56Sopenharmony_ci meth(obj, *args) 1397db96d56Sopenharmony_ci except Exception as e: 1407db96d56Sopenharmony_ci print("Error visiting %r: %s" % (obj, e)) 1417db96d56Sopenharmony_ci raise 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ciclass Check(VisitorBase): 1447db96d56Sopenharmony_ci """A visitor that checks a parsed ASDL tree for correctness. 1457db96d56Sopenharmony_ci 1467db96d56Sopenharmony_ci Errors are printed and accumulated. 1477db96d56Sopenharmony_ci """ 1487db96d56Sopenharmony_ci def __init__(self): 1497db96d56Sopenharmony_ci super(Check, self).__init__() 1507db96d56Sopenharmony_ci self.cons = {} 1517db96d56Sopenharmony_ci self.errors = 0 1527db96d56Sopenharmony_ci self.types = {} 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci def visitModule(self, mod): 1557db96d56Sopenharmony_ci for dfn in mod.dfns: 1567db96d56Sopenharmony_ci self.visit(dfn) 1577db96d56Sopenharmony_ci 1587db96d56Sopenharmony_ci def visitType(self, type): 1597db96d56Sopenharmony_ci self.visit(type.value, str(type.name)) 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci def visitSum(self, sum, name): 1627db96d56Sopenharmony_ci for t in sum.types: 1637db96d56Sopenharmony_ci self.visit(t, name) 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci def visitConstructor(self, cons, name): 1667db96d56Sopenharmony_ci key = str(cons.name) 1677db96d56Sopenharmony_ci conflict = self.cons.get(key) 1687db96d56Sopenharmony_ci if conflict is None: 1697db96d56Sopenharmony_ci self.cons[key] = name 1707db96d56Sopenharmony_ci else: 1717db96d56Sopenharmony_ci print('Redefinition of constructor {}'.format(key)) 1727db96d56Sopenharmony_ci print('Defined in {} and {}'.format(conflict, name)) 1737db96d56Sopenharmony_ci self.errors += 1 1747db96d56Sopenharmony_ci for f in cons.fields: 1757db96d56Sopenharmony_ci self.visit(f, key) 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ci def visitField(self, field, name): 1787db96d56Sopenharmony_ci key = str(field.type) 1797db96d56Sopenharmony_ci l = self.types.setdefault(key, []) 1807db96d56Sopenharmony_ci l.append(name) 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci def visitProduct(self, prod, name): 1837db96d56Sopenharmony_ci for f in prod.fields: 1847db96d56Sopenharmony_ci self.visit(f, name) 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_cidef check(mod): 1877db96d56Sopenharmony_ci """Check the parsed ASDL tree for correctness. 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci Return True if success. For failure, the errors are printed out and False 1907db96d56Sopenharmony_ci is returned. 1917db96d56Sopenharmony_ci """ 1927db96d56Sopenharmony_ci v = Check() 1937db96d56Sopenharmony_ci v.visit(mod) 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci for t in v.types: 1967db96d56Sopenharmony_ci if t not in mod.types and not t in builtin_types: 1977db96d56Sopenharmony_ci v.errors += 1 1987db96d56Sopenharmony_ci uses = ", ".join(v.types[t]) 1997db96d56Sopenharmony_ci print('Undefined type {}, used in {}'.format(t, uses)) 2007db96d56Sopenharmony_ci return not v.errors 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci# The ASDL parser itself comes next. The only interesting external interface 2037db96d56Sopenharmony_ci# here is the top-level parse function. 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_cidef parse(filename): 2067db96d56Sopenharmony_ci """Parse ASDL from the given file and return a Module node describing it.""" 2077db96d56Sopenharmony_ci with open(filename, encoding="utf-8") as f: 2087db96d56Sopenharmony_ci parser = ASDLParser() 2097db96d56Sopenharmony_ci return parser.parse(f.read()) 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci# Types for describing tokens in an ASDL specification. 2127db96d56Sopenharmony_ciclass TokenKind: 2137db96d56Sopenharmony_ci """TokenKind is provides a scope for enumerated token kinds.""" 2147db96d56Sopenharmony_ci (ConstructorId, TypeId, Equals, Comma, Question, Pipe, Asterisk, 2157db96d56Sopenharmony_ci LParen, RParen, LBrace, RBrace) = range(11) 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci operator_table = { 2187db96d56Sopenharmony_ci '=': Equals, ',': Comma, '?': Question, '|': Pipe, '(': LParen, 2197db96d56Sopenharmony_ci ')': RParen, '*': Asterisk, '{': LBrace, '}': RBrace} 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ciToken = namedtuple('Token', 'kind value lineno') 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ciclass ASDLSyntaxError(Exception): 2247db96d56Sopenharmony_ci def __init__(self, msg, lineno=None): 2257db96d56Sopenharmony_ci self.msg = msg 2267db96d56Sopenharmony_ci self.lineno = lineno or '<unknown>' 2277db96d56Sopenharmony_ci 2287db96d56Sopenharmony_ci def __str__(self): 2297db96d56Sopenharmony_ci return 'Syntax error on line {0.lineno}: {0.msg}'.format(self) 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_cidef tokenize_asdl(buf): 2327db96d56Sopenharmony_ci """Tokenize the given buffer. Yield Token objects.""" 2337db96d56Sopenharmony_ci for lineno, line in enumerate(buf.splitlines(), 1): 2347db96d56Sopenharmony_ci for m in re.finditer(r'\s*(\w+|--.*|.)', line.strip()): 2357db96d56Sopenharmony_ci c = m.group(1) 2367db96d56Sopenharmony_ci if c[0].isalpha(): 2377db96d56Sopenharmony_ci # Some kind of identifier 2387db96d56Sopenharmony_ci if c[0].isupper(): 2397db96d56Sopenharmony_ci yield Token(TokenKind.ConstructorId, c, lineno) 2407db96d56Sopenharmony_ci else: 2417db96d56Sopenharmony_ci yield Token(TokenKind.TypeId, c, lineno) 2427db96d56Sopenharmony_ci elif c[:2] == '--': 2437db96d56Sopenharmony_ci # Comment 2447db96d56Sopenharmony_ci break 2457db96d56Sopenharmony_ci else: 2467db96d56Sopenharmony_ci # Operators 2477db96d56Sopenharmony_ci try: 2487db96d56Sopenharmony_ci op_kind = TokenKind.operator_table[c] 2497db96d56Sopenharmony_ci except KeyError: 2507db96d56Sopenharmony_ci raise ASDLSyntaxError('Invalid operator %s' % c, lineno) 2517db96d56Sopenharmony_ci yield Token(op_kind, c, lineno) 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ciclass ASDLParser: 2547db96d56Sopenharmony_ci """Parser for ASDL files. 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci Create, then call the parse method on a buffer containing ASDL. 2577db96d56Sopenharmony_ci This is a simple recursive descent parser that uses tokenize_asdl for the 2587db96d56Sopenharmony_ci lexing. 2597db96d56Sopenharmony_ci """ 2607db96d56Sopenharmony_ci def __init__(self): 2617db96d56Sopenharmony_ci self._tokenizer = None 2627db96d56Sopenharmony_ci self.cur_token = None 2637db96d56Sopenharmony_ci 2647db96d56Sopenharmony_ci def parse(self, buf): 2657db96d56Sopenharmony_ci """Parse the ASDL in the buffer and return an AST with a Module root. 2667db96d56Sopenharmony_ci """ 2677db96d56Sopenharmony_ci self._tokenizer = tokenize_asdl(buf) 2687db96d56Sopenharmony_ci self._advance() 2697db96d56Sopenharmony_ci return self._parse_module() 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ci def _parse_module(self): 2727db96d56Sopenharmony_ci if self._at_keyword('module'): 2737db96d56Sopenharmony_ci self._advance() 2747db96d56Sopenharmony_ci else: 2757db96d56Sopenharmony_ci raise ASDLSyntaxError( 2767db96d56Sopenharmony_ci 'Expected "module" (found {})'.format(self.cur_token.value), 2777db96d56Sopenharmony_ci self.cur_token.lineno) 2787db96d56Sopenharmony_ci name = self._match(self._id_kinds) 2797db96d56Sopenharmony_ci self._match(TokenKind.LBrace) 2807db96d56Sopenharmony_ci defs = self._parse_definitions() 2817db96d56Sopenharmony_ci self._match(TokenKind.RBrace) 2827db96d56Sopenharmony_ci return Module(name, defs) 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci def _parse_definitions(self): 2857db96d56Sopenharmony_ci defs = [] 2867db96d56Sopenharmony_ci while self.cur_token.kind == TokenKind.TypeId: 2877db96d56Sopenharmony_ci typename = self._advance() 2887db96d56Sopenharmony_ci self._match(TokenKind.Equals) 2897db96d56Sopenharmony_ci type = self._parse_type() 2907db96d56Sopenharmony_ci defs.append(Type(typename, type)) 2917db96d56Sopenharmony_ci return defs 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci def _parse_type(self): 2947db96d56Sopenharmony_ci if self.cur_token.kind == TokenKind.LParen: 2957db96d56Sopenharmony_ci # If we see a (, it's a product 2967db96d56Sopenharmony_ci return self._parse_product() 2977db96d56Sopenharmony_ci else: 2987db96d56Sopenharmony_ci # Otherwise it's a sum. Look for ConstructorId 2997db96d56Sopenharmony_ci sumlist = [Constructor(self._match(TokenKind.ConstructorId), 3007db96d56Sopenharmony_ci self._parse_optional_fields())] 3017db96d56Sopenharmony_ci while self.cur_token.kind == TokenKind.Pipe: 3027db96d56Sopenharmony_ci # More constructors 3037db96d56Sopenharmony_ci self._advance() 3047db96d56Sopenharmony_ci sumlist.append(Constructor( 3057db96d56Sopenharmony_ci self._match(TokenKind.ConstructorId), 3067db96d56Sopenharmony_ci self._parse_optional_fields())) 3077db96d56Sopenharmony_ci return Sum(sumlist, self._parse_optional_attributes()) 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci def _parse_product(self): 3107db96d56Sopenharmony_ci return Product(self._parse_fields(), self._parse_optional_attributes()) 3117db96d56Sopenharmony_ci 3127db96d56Sopenharmony_ci def _parse_fields(self): 3137db96d56Sopenharmony_ci fields = [] 3147db96d56Sopenharmony_ci self._match(TokenKind.LParen) 3157db96d56Sopenharmony_ci while self.cur_token.kind == TokenKind.TypeId: 3167db96d56Sopenharmony_ci typename = self._advance() 3177db96d56Sopenharmony_ci is_seq, is_opt = self._parse_optional_field_quantifier() 3187db96d56Sopenharmony_ci id = (self._advance() if self.cur_token.kind in self._id_kinds 3197db96d56Sopenharmony_ci else None) 3207db96d56Sopenharmony_ci fields.append(Field(typename, id, seq=is_seq, opt=is_opt)) 3217db96d56Sopenharmony_ci if self.cur_token.kind == TokenKind.RParen: 3227db96d56Sopenharmony_ci break 3237db96d56Sopenharmony_ci elif self.cur_token.kind == TokenKind.Comma: 3247db96d56Sopenharmony_ci self._advance() 3257db96d56Sopenharmony_ci self._match(TokenKind.RParen) 3267db96d56Sopenharmony_ci return fields 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci def _parse_optional_fields(self): 3297db96d56Sopenharmony_ci if self.cur_token.kind == TokenKind.LParen: 3307db96d56Sopenharmony_ci return self._parse_fields() 3317db96d56Sopenharmony_ci else: 3327db96d56Sopenharmony_ci return None 3337db96d56Sopenharmony_ci 3347db96d56Sopenharmony_ci def _parse_optional_attributes(self): 3357db96d56Sopenharmony_ci if self._at_keyword('attributes'): 3367db96d56Sopenharmony_ci self._advance() 3377db96d56Sopenharmony_ci return self._parse_fields() 3387db96d56Sopenharmony_ci else: 3397db96d56Sopenharmony_ci return None 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci def _parse_optional_field_quantifier(self): 3427db96d56Sopenharmony_ci is_seq, is_opt = False, False 3437db96d56Sopenharmony_ci if self.cur_token.kind == TokenKind.Asterisk: 3447db96d56Sopenharmony_ci is_seq = True 3457db96d56Sopenharmony_ci self._advance() 3467db96d56Sopenharmony_ci elif self.cur_token.kind == TokenKind.Question: 3477db96d56Sopenharmony_ci is_opt = True 3487db96d56Sopenharmony_ci self._advance() 3497db96d56Sopenharmony_ci return is_seq, is_opt 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci def _advance(self): 3527db96d56Sopenharmony_ci """ Return the value of the current token and read the next one into 3537db96d56Sopenharmony_ci self.cur_token. 3547db96d56Sopenharmony_ci """ 3557db96d56Sopenharmony_ci cur_val = None if self.cur_token is None else self.cur_token.value 3567db96d56Sopenharmony_ci try: 3577db96d56Sopenharmony_ci self.cur_token = next(self._tokenizer) 3587db96d56Sopenharmony_ci except StopIteration: 3597db96d56Sopenharmony_ci self.cur_token = None 3607db96d56Sopenharmony_ci return cur_val 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci _id_kinds = (TokenKind.ConstructorId, TokenKind.TypeId) 3637db96d56Sopenharmony_ci 3647db96d56Sopenharmony_ci def _match(self, kind): 3657db96d56Sopenharmony_ci """The 'match' primitive of RD parsers. 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci * Verifies that the current token is of the given kind (kind can 3687db96d56Sopenharmony_ci be a tuple, in which the kind must match one of its members). 3697db96d56Sopenharmony_ci * Returns the value of the current token 3707db96d56Sopenharmony_ci * Reads in the next token 3717db96d56Sopenharmony_ci """ 3727db96d56Sopenharmony_ci if (isinstance(kind, tuple) and self.cur_token.kind in kind or 3737db96d56Sopenharmony_ci self.cur_token.kind == kind 3747db96d56Sopenharmony_ci ): 3757db96d56Sopenharmony_ci value = self.cur_token.value 3767db96d56Sopenharmony_ci self._advance() 3777db96d56Sopenharmony_ci return value 3787db96d56Sopenharmony_ci else: 3797db96d56Sopenharmony_ci raise ASDLSyntaxError( 3807db96d56Sopenharmony_ci 'Unmatched {} (found {})'.format(kind, self.cur_token.kind), 3817db96d56Sopenharmony_ci self.cur_token.lineno) 3827db96d56Sopenharmony_ci 3837db96d56Sopenharmony_ci def _at_keyword(self, keyword): 3847db96d56Sopenharmony_ci return (self.cur_token.kind == TokenKind.TypeId and 3857db96d56Sopenharmony_ci self.cur_token.value == keyword) 386