mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-08-08 21:10:29 +00:00
Split generator/tlobject into separate files
This commit is contained in:
98
telethon_generator/parsers/tlobject/parser.py
Normal file
98
telethon_generator/parsers/tlobject/parser.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import collections
|
||||
import re
|
||||
|
||||
from .tlarg import TLArg
|
||||
from .tlobject import TLObject
|
||||
|
||||
|
||||
def _from_line(line, is_function, layer):
|
||||
match = re.match(
|
||||
r'^([\w.]+)' # 'name'
|
||||
r'(?:#([0-9a-fA-F]+))?' # '#optionalcode'
|
||||
r'(?:\s{?\w+:[\w\d<>#.?!]+}?)*' # '{args:.0?type}'
|
||||
r'\s=\s' # ' = '
|
||||
r'([\w\d<>#.?]+);$', # '<result.type>;'
|
||||
line
|
||||
)
|
||||
if match is None:
|
||||
# Probably "vector#1cb5c415 {t:Type} # [ t ] = Vector t;"
|
||||
raise ValueError('Cannot parse TLObject {}'.format(line))
|
||||
|
||||
args_match = re.findall(
|
||||
r'({)?'
|
||||
r'(\w+)'
|
||||
r':'
|
||||
r'([\w\d<>#.?!]+)'
|
||||
r'}?',
|
||||
line
|
||||
)
|
||||
return TLObject(
|
||||
fullname=match.group(1),
|
||||
object_id=match.group(2),
|
||||
result=match.group(3),
|
||||
is_function=is_function,
|
||||
layer=layer,
|
||||
args=[TLArg(name, arg_type, brace != '')
|
||||
for brace, name, arg_type in args_match]
|
||||
)
|
||||
|
||||
|
||||
def parse_tl(file_path, layer, invalid_bot_methods=None):
|
||||
"""
|
||||
This method yields TLObjects from a given .tl file.
|
||||
|
||||
Note that the file is parsed completely before the function yields
|
||||
because references to other objects may appear later in the file.
|
||||
"""
|
||||
if invalid_bot_methods is None:
|
||||
invalid_bot_methods = set()
|
||||
|
||||
obj_all = []
|
||||
obj_by_name = {}
|
||||
obj_by_type = collections.defaultdict(list)
|
||||
with open(file_path, 'r', encoding='utf-8') as file:
|
||||
is_function = False
|
||||
for line in file:
|
||||
comment_index = line.find('//')
|
||||
if comment_index != -1:
|
||||
line = line[:comment_index]
|
||||
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
match = re.match('---(\w+)---', line)
|
||||
if match:
|
||||
following_types = match.group(1)
|
||||
is_function = following_types == 'functions'
|
||||
continue
|
||||
|
||||
try:
|
||||
result = _from_line(line, is_function, layer=layer)
|
||||
result.bot_usable = result.fullname not in invalid_bot_methods
|
||||
obj_all.append(result)
|
||||
obj_by_name[result.fullname] = result
|
||||
obj_by_type[result.result].append(result)
|
||||
except ValueError as e:
|
||||
if 'vector#1cb5c415' not in str(e):
|
||||
raise
|
||||
|
||||
# Once all objects have been parsed, replace the
|
||||
# string type from the arguments with references
|
||||
for obj in obj_all:
|
||||
for arg in obj.args:
|
||||
arg.cls = obj_by_type.get(arg.type) or (
|
||||
[obj_by_name[arg.type]] if arg.type in obj_by_name else []
|
||||
)
|
||||
|
||||
yield from obj_all
|
||||
|
||||
|
||||
def find_layer(file_path):
|
||||
"""Finds the layer used on the specified scheme.tl file."""
|
||||
layer_regex = re.compile(r'^//\s*LAYER\s*(\d+)$')
|
||||
with open(file_path, 'r', encoding='utf-8') as file:
|
||||
for line in file:
|
||||
match = layer_regex.match(line)
|
||||
if match:
|
||||
return int(match.group(1))
|
Reference in New Issue
Block a user