2018-08-30 14:55:42 +00:00
|
|
|
package tlparser
|
|
|
|
|
|
|
|
import (
|
2018-10-23 12:49:10 +00:00
|
|
|
"bufio"
|
|
|
|
"io"
|
|
|
|
"strings"
|
2018-08-30 14:55:42 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func Parse(reader io.Reader) (*Schema, error) {
|
2018-10-23 12:49:10 +00:00
|
|
|
schema := &Schema{
|
|
|
|
Types: []*Type{},
|
|
|
|
Classes: []*Class{},
|
|
|
|
Functions: []*Function{},
|
|
|
|
}
|
|
|
|
|
|
|
|
scanner := bufio.NewScanner(reader)
|
|
|
|
|
|
|
|
hitFunctions := false
|
|
|
|
|
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(line, "//@description"):
|
|
|
|
if hitFunctions {
|
|
|
|
schema.Functions = append(schema.Functions, parseFunction(line, scanner))
|
|
|
|
} else {
|
|
|
|
schema.Types = append(schema.Types, parseType(line, scanner))
|
|
|
|
}
|
|
|
|
|
|
|
|
case strings.HasPrefix(line, "//@class"):
|
|
|
|
schema.Classes = append(schema.Classes, parseClass(line, scanner))
|
|
|
|
|
|
|
|
case strings.Contains(line, "---functions---"):
|
|
|
|
hitFunctions = true
|
|
|
|
|
|
|
|
case line == "":
|
|
|
|
|
|
|
|
default:
|
|
|
|
bodyFields := strings.Fields(line)
|
|
|
|
name := bodyFields[0]
|
|
|
|
class := strings.TrimRight(bodyFields[len(bodyFields)-1], ";")
|
|
|
|
if hitFunctions {
|
|
|
|
schema.Functions = append(schema.Functions, &Function{
|
|
|
|
Name: name,
|
|
|
|
Description: "",
|
|
|
|
Class: class,
|
|
|
|
Properties: []*Property{},
|
|
|
|
IsSynchronous: false,
|
|
|
|
Type: FUNCTION_TYPE_UNKNOWN,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
if name == "vector" {
|
|
|
|
name = "vector<t>"
|
|
|
|
class = "Vector<T>"
|
|
|
|
}
|
|
|
|
|
|
|
|
schema.Types = append(schema.Types, &Type{
|
|
|
|
Name: name,
|
|
|
|
Description: "",
|
|
|
|
Class: class,
|
|
|
|
Properties: []*Property{},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return schema, nil
|
2018-08-30 14:55:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func parseType(firstLine string, scanner *bufio.Scanner) *Type {
|
2018-10-23 12:49:10 +00:00
|
|
|
name, description, class, properties, _ := parseEntity(firstLine, scanner)
|
|
|
|
return &Type{
|
|
|
|
Name: name,
|
|
|
|
Description: description,
|
|
|
|
Class: class,
|
|
|
|
Properties: properties,
|
|
|
|
}
|
2018-08-30 14:55:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func parseFunction(firstLine string, scanner *bufio.Scanner) *Function {
|
2018-10-23 12:49:10 +00:00
|
|
|
name, description, class, properties, isSynchronous := parseEntity(firstLine, scanner)
|
|
|
|
return &Function{
|
|
|
|
Name: name,
|
|
|
|
Description: description,
|
|
|
|
Class: class,
|
|
|
|
Properties: properties,
|
|
|
|
IsSynchronous: isSynchronous,
|
|
|
|
Type: FUNCTION_TYPE_UNKNOWN,
|
|
|
|
}
|
2018-08-30 14:55:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func parseClass(firstLine string, scanner *bufio.Scanner) *Class {
|
2023-11-11 17:31:19 +00:00
|
|
|
name, description, _, _, _ := parseEntity(firstLine, scanner)
|
|
|
|
return &Class{
|
|
|
|
Name: name,
|
|
|
|
Description: description,
|
2018-10-23 12:49:10 +00:00
|
|
|
}
|
2018-08-30 14:55:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func parseEntity(firstLine string, scanner *bufio.Scanner) (string, string, string, []*Property, bool) {
|
2018-10-23 12:49:10 +00:00
|
|
|
name := ""
|
|
|
|
description := ""
|
|
|
|
class := ""
|
|
|
|
properties := []*Property{}
|
2018-08-30 14:55:42 +00:00
|
|
|
|
2018-10-23 12:49:10 +00:00
|
|
|
propertiesLine := strings.TrimLeft(firstLine, "//")
|
2018-08-30 14:55:42 +00:00
|
|
|
|
|
|
|
Loop:
|
2018-10-23 12:49:10 +00:00
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(line, "//@"):
|
|
|
|
propertiesLine += " " + strings.TrimLeft(line, "//")
|
|
|
|
|
|
|
|
case strings.HasPrefix(line, "//-"):
|
|
|
|
propertiesLine += " " + strings.TrimLeft(line, "//-")
|
|
|
|
|
|
|
|
default:
|
|
|
|
bodyFields := strings.Fields(line)
|
2023-11-11 17:31:19 +00:00
|
|
|
if len(bodyFields) == 0 {
|
|
|
|
break Loop
|
|
|
|
}
|
2018-10-23 12:49:10 +00:00
|
|
|
name = bodyFields[0]
|
|
|
|
|
|
|
|
for _, rawProperty := range bodyFields[1 : len(bodyFields)-2] {
|
|
|
|
propertyParts := strings.Split(rawProperty, ":")
|
|
|
|
property := &Property{
|
|
|
|
Name: propertyParts[0],
|
|
|
|
Type: propertyParts[1],
|
|
|
|
}
|
|
|
|
properties = append(properties, property)
|
|
|
|
}
|
|
|
|
class = strings.TrimRight(bodyFields[len(bodyFields)-1], ";")
|
|
|
|
break Loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rawProperties := strings.Split(propertiesLine, "@")
|
|
|
|
for _, rawProperty := range rawProperties[1:] {
|
2023-11-11 17:31:19 +00:00
|
|
|
propertyName, value := parseProperty(rawProperty)
|
2018-10-23 12:49:10 +00:00
|
|
|
switch {
|
2023-11-11 17:31:19 +00:00
|
|
|
case propertyName == "class":
|
|
|
|
if name == "" {
|
|
|
|
name = value
|
|
|
|
}
|
|
|
|
case propertyName == "description":
|
2018-10-23 12:49:10 +00:00
|
|
|
description = value
|
|
|
|
default:
|
2023-11-11 17:31:19 +00:00
|
|
|
propertyName = strings.TrimPrefix(propertyName, "param_")
|
|
|
|
property := getProperty(properties, propertyName)
|
2018-10-23 12:49:10 +00:00
|
|
|
property.Description = value
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return name, description, class, properties, strings.Contains(description, "Can be called synchronously")
|
2018-08-30 14:55:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func parseProperty(str string) (string, string) {
|
2018-10-23 12:49:10 +00:00
|
|
|
strParts := strings.Fields(str)
|
2018-08-30 14:55:42 +00:00
|
|
|
|
2018-10-23 12:49:10 +00:00
|
|
|
return strParts[0], strings.Join(strParts[1:], " ")
|
2018-08-30 14:55:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getProperty(properties []*Property, name string) *Property {
|
2018-10-23 12:49:10 +00:00
|
|
|
for _, property := range properties {
|
|
|
|
if property.Name == name {
|
|
|
|
return property
|
|
|
|
}
|
|
|
|
}
|
2018-08-30 14:55:42 +00:00
|
|
|
|
2018-10-23 12:49:10 +00:00
|
|
|
return nil
|
2018-08-30 14:55:42 +00:00
|
|
|
}
|