1 Star 0 Fork 0

ThinCats/tree-sitter-nodegen

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
parse.go 4.75 KB
一键复制 编辑 原始数据 按行查看 历史
ThinCats 提交于 2021-04-25 16:39 +08:00 . fix: use yaml.MapSlice to preserve json key order
package parse
import (
"fmt"
"gitee.com/thincats/tree-sitter-nodegen/pkg/types"
"gitee.com/thincats/tree-sitter-nodegen/pkg/utils"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
func impossibleRoute() {
panic("impossible route")
}
// ErrParse parse error
var ErrParse = errors.New("parse error")
var panicIfErr = utils.CreatePanicIfErr(ErrParse)
// Parse do parsing
func Parse(data []byte) (res []types.Node, err error) {
p := newParser()
return p.Parse(data)
}
// parser do parse
type parser struct {
// contains symtab for NamedNode
namedSymTab map[string]types.NamedNode
namelessSymTab map[string]*types.NamelessNode
}
func newParser() *parser {
return &parser{
namedSymTab: make(map[string]types.NamedNode),
namelessSymTab: make(map[string]*types.NamelessNode),
}
}
// JSONToYAML Convert JSON to YAML.
func JSONToYAML(j []byte) ([]byte, error) {
// Convert the JSON to an object.
var jsonObj interface{}
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
// Go JSON library doesn't try to pick the right number type (int, float,
// etc.) when unmarshalling to interface{}, it just picks float64
// universally. go-yaml does go through the effort of picking the right
// number type, so we can preserve number type throughout this process.
err := yaml.Unmarshal(j, &jsonObj)
if err != nil {
return nil, err
}
// Marshal this object into YAML.
return yaml.Marshal(jsonObj)
}
func (p *parser) Parse(data []byte) (res []types.Node, err error) {
defer func() {
err = utils.RecoverFromErr(ErrParse)
}()
rawNodes := []*RawTypeNode{}
err = yaml.Unmarshal(data, &rawNodes)
panicIfErr(err)
rawNodes = p.classifyRawTypeNodes(rawNodes)
p.constructSymTab(rawNodes)
for _, rawNode := range rawNodes {
res = append(res, p.parseRawNode(rawNode))
}
return res, nil
}
func (p *parser) classifyRawTypeNodes(rawNodes []*RawTypeNode) []*RawTypeNode {
res := []*RawTypeNode{}
for _, rawNode := range rawNodes {
if rawNode.Named {
if !rawNode.Subtypes.Empty() {
// SuperType
rawNode.Kind = kindSuperType
} else if rawNode.Fields.Empty() && rawNode.Children.Empty() {
rawNode.Kind = kindNamedTokenType
} else {
// NormalType
rawNode.Kind = kindNormalType
}
}
res = append(res, rawNode)
}
return res
}
func (p *parser) constructSymTab(rawNodes []*RawTypeNode) {
for _, rawNode := range rawNodes {
if !rawNode.Named {
// if Type = *, then return "*"
p.namelessSymTab[rawNode.Type] = &types.NamelessNode{
Type: rawNode.Type,
}
} else {
var node types.NamedNode
switch rawNode.Kind {
case kindSuperType:
node = &types.SuperTypeNode{
Type: rawNode.Type,
}
case kindNamedTokenType:
node = &types.NamedTokenType{
Type: rawNode.Type,
}
case kindNormalType:
node = &types.NormalTypeNode{
Type: rawNode.Type,
}
default:
impossibleRoute()
}
p.namedSymTab[rawNode.Type] = node
}
}
}
func (p *parser) parseRawNode(rawNode *RawTypeNode) types.Node {
if !rawNode.Named {
return &types.NamelessNode{
Type: rawNode.Type,
}
}
// handle named node
rawSubtypes := []typeRefFragment{}
if !rawNode.Subtypes.Empty() {
// fmt.Println(rawNode.Subtypes.String())
err := rawNode.Subtypes.Unmarshal(&rawSubtypes)
panicIfErr(err)
}
rawFields := MakeFieldFragmentOrderedMap()
if !rawNode.Fields.Empty() {
err := rawNode.Fields.Unmarshal(&rawFields)
panicIfErr(err)
}
fields := types.MakeFieldFragmentOrderedMap()
for _, entity := range rawFields.Entities() {
k, field := entity.Key, entity.Val
fields.Set(k, p.handleFieldFragment(k, field))
}
if !rawNode.Children.Empty() {
rawChildren := fieldFragment{}
err := rawNode.Children.Unmarshal(&rawChildren)
panicIfErr(err)
fields.Set("children", p.handleFieldFragment("children", rawChildren))
}
// assign them to actual nodes
node := p.namedSymTab[rawNode.Type]
switch rawNode.Kind {
case kindSuperType:
n := node.(*types.SuperTypeNode)
n.SubTypes = p.handleTypeRefFragments(rawSubtypes)
case kindNormalType:
n := node.(*types.NormalTypeNode)
n.Fields = fields
case kindNamedTokenType:
break
default:
impossibleRoute()
}
return node
}
func (p *parser) handleFieldFragment(fieldName string, f fieldFragment) types.FieldFragment {
return types.FieldFragment{
Name: fieldName,
Multiple: f.Multiple,
Required: f.Required,
Types: p.handleTypeRefFragments(f.Types),
}
}
func (p *parser) handleTypeRefFragments(datas []typeRefFragment) []types.Node {
res := []types.Node{}
for _, t := range datas {
var (
node types.Node
ok bool
)
node, ok = p.namedSymTab[t.Type]
if !ok {
node, ok = p.namelessSymTab[t.Type]
if !ok {
panicIfErr(fmt.Errorf("no such nameless type: %s", t.Type))
}
}
res = append(res, node)
}
return res
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/thincats/tree-sitter-nodegen.git
git@gitee.com:thincats/tree-sitter-nodegen.git
thincats
tree-sitter-nodegen
tree-sitter-nodegen
606d0162f6c8

搜索帮助