1
0
treerack/cmd/treerack/show.go

110 lines
2.2 KiB
Go

package main
import (
"code.squareroundforest.org/arpio/treerack"
"encoding/json"
"io"
)
type showOptions struct {
// Syntax specifies the filename of the syntax definition file.
Syntax string
// SyntaxString specifies the syntax as an inline string.
SyntaxString string
// Input specifies the filename of the input content to be validated.
Input string
// InputString specifies the input content as an inline string.
InputString string
// Pretty enables indented, human-readable output.
Pretty bool
// Indent specifies a custom indentation string for the output.
Indent string
}
type node struct {
Name string `json:"name"`
From int `json:"from"`
To int `json:"to"`
Text string `json:"text,omitempty"`
Nodes []node `json:"nodes,omitempty"`
}
func mapNode(n *treerack.Node) node {
var nn node
nn.Name = n.Name
nn.From = n.From
nn.To = n.To
if len(n.Nodes) == 0 {
nn.Text = n.Text()
return nn
}
for i := range n.Nodes {
nn.Nodes = append(nn.Nodes, mapNode(n.Nodes[i]))
}
return nn
}
// show input content against a provided syntax definition and outputs the resulting AST (Abstract Syntax Tree)
// in JSON format. Syntax can be provided via a filename option or an inline string option. Input can be
// provided via a filename option, a positional argument filename, an inline string option, or piped from
// standard input.
func show(o showOptions, stdin io.Reader, stdout io.Writer, args ...string) error {
syntax, finalizeSyntax, err := initInput(o.Syntax, o.SyntaxString, nil, nil)
if err != nil {
return err
}
defer finalizeSyntax()
input, finalizeInput, err := initInput(o.Input, o.InputString, stdin, args)
if err != nil {
return err
}
defer finalizeInput()
s := &treerack.Syntax{}
if err := s.ReadSyntax(syntax); err != nil {
return err
}
if err := s.Init(); err != nil {
return err
}
n, err := s.Parse(input)
if err != nil {
return err
}
nn := mapNode(n)
encode := json.Marshal
if o.Pretty || o.Indent != "" {
if o.Indent == "" {
o.Indent = " "
}
encode = func(a any) ([]byte, error) {
return json.MarshalIndent(a, "", o.Indent)
}
}
b, err := encode(nn)
if err != nil {
return err
}
if _, err := stdout.Write(b); err != nil {
return err
}
return nil
}