You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
7.4 KiB
266 lines
7.4 KiB
import 'tl_token.dart'; |
|
|
|
class TlSchema { |
|
final List<TlSchemeAbstractClass> abstractClasses; |
|
final List<TlSchemeObject> objects; |
|
final List<TlSchemeFunction> functions; |
|
|
|
TlSchema({ |
|
required this.abstractClasses, |
|
required this.objects, |
|
required this.functions, |
|
}); |
|
|
|
TlSchemeItem? findType(String type) { |
|
TlSchemeItem? find(List<TlSchemeItem> list) { |
|
for (final item in list) { |
|
if (item.name == type) { |
|
return item; |
|
} |
|
} |
|
} |
|
|
|
return find(abstractClasses) ?? find(objects) ?? find(functions); |
|
} |
|
|
|
factory TlSchema.parse(String file) { |
|
var abstractClasses = <String, TlSchemeAbstractClass>{}; |
|
var objects = <String, TlSchemeObject>{}; |
|
var functions = <String, TlSchemeFunction>{}; |
|
|
|
var comments = <TlTokenCommentTag>[]; |
|
|
|
void finishBuilder(_TlSchemeItemBuilder builder) { |
|
comments.clear(); |
|
if (builder is _TlSchemeAbstractClassBuilder) { |
|
final ac = builder.build(); |
|
abstractClasses[ac.name] = ac; |
|
} |
|
else if (builder is _TlSchemeObjectBuilder) { |
|
final obj = builder.build(); |
|
objects[obj.name] = obj; |
|
if (!abstractClasses.containsKey(obj.baseType)) { |
|
abstractClasses[obj.baseType] = TlSchemeAbstractClass( |
|
name: obj.baseType, |
|
doc: '' |
|
); |
|
} |
|
} |
|
else if (builder is _TlSchemeFunctionBuilder) { |
|
final fn = builder.build(); |
|
functions[fn.name] = fn; |
|
} |
|
else { |
|
throw Exception('Unknown builder: $builder'); |
|
} |
|
} |
|
|
|
var buildingFunctions = false; |
|
_TlSchemeItemBuilder? builder; |
|
|
|
for (final token in TlToken.tokenize(file)) { |
|
if (token is TlTokenNone) { |
|
if (builder != null) { |
|
finishBuilder(builder); |
|
} |
|
builder = null; |
|
} |
|
else if (token is TlTokenFunctionsDelimiter) { |
|
buildingFunctions = true; |
|
} |
|
else if (token is TlTokenCommentTag) { |
|
if (token.name == 'class' && comments.isEmpty && builder == null) { |
|
builder = _TlSchemeAbstractClassBuilder( |
|
name: token.value, |
|
); |
|
} |
|
else if (builder is _TlSchemeAbstractClassBuilder && token.name == 'description') { |
|
builder.doc = token.value; |
|
} |
|
else { |
|
comments.add(token); |
|
} |
|
} |
|
else if (token is TlTokenClassTag) { |
|
// Check for skippable |
|
final skippable = [ |
|
'double', |
|
'string', |
|
'int32', |
|
'int53', |
|
'int64', |
|
'bytes', |
|
'boolFalse', |
|
'boolTrue', |
|
'vector', |
|
]; |
|
if (skippable.contains(token.name)) { |
|
comments.clear(); |
|
builder = null; |
|
continue; |
|
} |
|
|
|
var typeDoc = ''; |
|
var paramDoc = <String, String>{}; |
|
|
|
for (final comment in comments) { |
|
if (comment.name == 'description') { |
|
typeDoc = comment.value; |
|
} |
|
else if (comment.name == 'param_description') { |
|
paramDoc['description'] = comment.value; |
|
} |
|
else { |
|
paramDoc[comment.name] = comment.value; |
|
} |
|
} |
|
|
|
if (buildingFunctions) { |
|
builder = _TlSchemeFunctionBuilder( |
|
returnType: token.baseType, |
|
name: token.name, |
|
doc: typeDoc, |
|
parameters: token.parameters.map((t) => _TlSchemeParamBuilder( |
|
name: t.name, |
|
type: t.type, |
|
doc: paramDoc[t.name]!, |
|
)).toList(growable: false), |
|
); |
|
} |
|
else { |
|
builder = _TlSchemeObjectBuilder( |
|
baseType: token.baseType, |
|
name: token.name, |
|
doc: typeDoc, |
|
parameters: token.parameters.map((t) => _TlSchemeParamBuilder( |
|
name: t.name, |
|
type: t.type, |
|
doc: paramDoc[t.name]!, |
|
)).toList(growable: false), |
|
); |
|
} |
|
finishBuilder(builder); |
|
builder = null; |
|
} |
|
} |
|
|
|
return TlSchema( |
|
abstractClasses: abstractClasses.values.toList(growable: false), |
|
objects: objects.values.toList(growable: false), |
|
functions: functions.values.toList(growable: false), |
|
); |
|
} |
|
} |
|
|
|
abstract class TlSchemeItem { |
|
final String name; |
|
final String doc; |
|
TlSchemeItem({required this.name, required this.doc}); |
|
} |
|
abstract class _TlSchemeItemBuilder<T extends TlSchemeItem> { |
|
T build(); |
|
} |
|
|
|
class TlSchemeAbstractClass extends TlSchemeItem { |
|
TlSchemeAbstractClass({required String name, required String doc}) |
|
: super(name: name, doc: doc); |
|
|
|
@override |
|
String toString() { |
|
return 'abstract $name'; |
|
} |
|
} |
|
class _TlSchemeAbstractClassBuilder extends _TlSchemeItemBuilder<TlSchemeAbstractClass> { |
|
String name; |
|
String doc; |
|
_TlSchemeAbstractClassBuilder({this.name = '', this.doc = ''}); |
|
@override |
|
TlSchemeAbstractClass build() => TlSchemeAbstractClass(name: name, doc: doc); |
|
} |
|
|
|
class TlSchemeObject extends TlSchemeItem { |
|
final String baseType; |
|
final List<TlSchemeParam> parameters; |
|
TlSchemeObject({ |
|
required this.baseType, |
|
required String name, |
|
required String doc, |
|
required this.parameters, |
|
}) : super(name: name, doc: doc); |
|
|
|
@override |
|
String toString() { |
|
return 'class $name(${parameters.join(', ')}) : $baseType'; |
|
} |
|
} |
|
class _TlSchemeObjectBuilder extends _TlSchemeItemBuilder<TlSchemeObject> { |
|
String baseType; |
|
String name; |
|
String doc; |
|
List<_TlSchemeParamBuilder> parameters; |
|
_TlSchemeObjectBuilder({ |
|
this.baseType = '', |
|
this.name = '', |
|
this.doc = '', |
|
this.parameters = const <_TlSchemeParamBuilder>[] |
|
}); |
|
@override |
|
TlSchemeObject build() => TlSchemeObject( |
|
baseType: baseType, |
|
name: name, |
|
doc: doc, |
|
parameters: parameters.map((b) => b.build()).toList(growable: false), |
|
); |
|
} |
|
|
|
class TlSchemeFunction extends TlSchemeItem { |
|
final String returnType; |
|
final List<TlSchemeParam> parameters; |
|
TlSchemeFunction({ |
|
required this.returnType, |
|
required String name, |
|
required String doc, |
|
required this.parameters, |
|
}) : super(name: name, doc: doc); |
|
@override |
|
String toString() { |
|
return 'fn $name(${parameters.join(', ')}) -> $returnType'; |
|
} |
|
} |
|
class _TlSchemeFunctionBuilder extends _TlSchemeItemBuilder<TlSchemeFunction> { |
|
String returnType; |
|
String name; |
|
String doc; |
|
List<_TlSchemeParamBuilder> parameters; |
|
_TlSchemeFunctionBuilder({ |
|
this.returnType = '', |
|
this.name = '', |
|
this.doc = '', |
|
this.parameters = const <_TlSchemeParamBuilder>[] |
|
}); |
|
@override |
|
TlSchemeFunction build() => TlSchemeFunction( |
|
returnType: returnType, |
|
name: name, |
|
doc: doc, |
|
parameters: parameters.map((b) => b.build()).toList(growable: false), |
|
); |
|
} |
|
|
|
class TlSchemeParam { |
|
final String name; |
|
final String type; |
|
final String doc; |
|
TlSchemeParam({required this.name, required this.type, required this.doc}); |
|
@override |
|
String toString() { |
|
return '$name: $type'; |
|
} |
|
} |
|
class _TlSchemeParamBuilder { |
|
String name; |
|
String type; |
|
String doc; |
|
_TlSchemeParamBuilder({this.name = '', this.type = '', this.doc = ''}); |
|
TlSchemeParam build() => TlSchemeParam(name: name, type: type, doc: doc); |
|
}
|
|
|