add json translator

master
Jordan Orelli 10 years ago
parent cbbeff9908
commit 64d05746e6

@ -1,37 +1,37 @@
package main package main
import ( import (
"encoding/json"
"flag" "flag"
"fmt" "fmt"
"io" "io"
"os" "os"
) )
func input() io.ReadCloser { func input(n int) io.ReadCloser {
if flag.Arg(1) == "" { if flag.Arg(n) == "" {
return os.Stdin return os.Stdin
} else { } else {
f, err := os.Open(flag.Arg(1)) f, err := os.Open(flag.Arg(n))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "error: %s\n", err) bail(1, "input error: %s", err)
os.Exit(1)
} }
return f return f
} }
} }
func check() { func check() {
r := input() r := input(1)
defer r.Close() defer r.Close()
_, err := parse(r) _, err := parse(r)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err) bail(1, "parse error: %s", err)
} }
} }
func lexx() { func lexx() {
r := input() r := input(1)
defer r.Close() defer r.Close()
c := lex(r) c := lex(r)
@ -41,20 +41,65 @@ func lexx() {
} }
func parsse() { func parsse() {
r := input() r := input(1)
defer r.Close() defer r.Close()
n, err := parse(r) n, err := parse(r)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "error: %s\n", err) bail(1, "parse error: %s", err)
os.Exit(1)
} }
if err := n.pretty(os.Stdout, ""); err != nil { if err := n.pretty(os.Stdout, ""); err != nil {
fmt.Fprintf(os.Stderr, "error: %s\n", err) bail(1, "output error: %s", err)
}
}
func eval(r io.Reader) (map[string]interface{}, error) {
n, err := parse(r)
if err != nil {
return nil, fmt.Errorf("parse error: %s\n", err)
}
ctx := make(map[string]interface{})
if err := n.eval(ctx); err != nil {
return nil, fmt.Errorf("eval error: %s\n", err)
}
return ctx, nil
}
func to() {
switch flag.Arg(1) {
case "json":
to_json(2)
default:
fmt.Fprintf(os.Stderr, "%s is not a valid output format\n", flag.Arg(1))
fmt.Fprintln(os.Stderr, "valid output formats: json")
os.Exit(1) os.Exit(1)
} }
} }
func to_json(n int) {
v, err := eval(input(n))
if err != nil {
bail(1, "input error: %s", err)
}
b, err := json.MarshalIndent(v, "", " ")
if err != nil {
bail(1, "encode error: %s", err)
}
os.Stdout.Write(b)
}
func bail(status int, t string, args ...interface{}) {
var w io.Writer
if status == 0 {
w = os.Stdout
} else {
w = os.Stderr
}
fmt.Fprintf(w, t+"\n", args...)
os.Exit(status)
}
func main() { func main() {
flag.Parse() flag.Parse()
switch flag.Arg(0) { switch flag.Arg(0) {
@ -64,11 +109,11 @@ func main() {
lexx() lexx()
case "parse": case "parse":
parsse() parsse()
case "to":
to()
case "": case "":
fmt.Fprintf(os.Stderr, "specify an action (check)\n") bail(1, "must specify an action.\nvalid actions: check lex parse to")
os.Exit(1)
default: default:
fmt.Fprintf(os.Stderr, "no such action: %s\n", flag.Arg(0)) bail(1, "no such action:%s", flag.Arg(0))
os.Exit(1)
} }
} }

@ -23,6 +23,7 @@ type node interface {
Type() nodeType Type() nodeType
parse(*parser) error parse(*parser) error
pretty(io.Writer, string) error pretty(io.Writer, string) error
eval(map[string]interface{}) error
} }
type rootNode struct { type rootNode struct {
@ -90,6 +91,15 @@ func (n *rootNode) pretty(w io.Writer, prefix string) error {
return nil return nil
} }
func (n *rootNode) eval(ctx map[string]interface{}) error {
for _, child := range n.children {
if err := child.eval(ctx); err != nil {
return err
}
}
return nil
}
type commentNode struct { type commentNode struct {
body string body string
} }
@ -126,6 +136,10 @@ func (n *commentNode) pretty(w io.Writer, prefix string) error {
return nil return nil
} }
func (n *commentNode) eval(ctx map[string]interface{}) error {
return nil
}
type assignmentNode struct { type assignmentNode struct {
name string name string
value interface{} value interface{}
@ -167,5 +181,13 @@ func (n *assignmentNode) pretty(w io.Writer, prefix string) error {
return nil return nil
} }
func (n *assignmentNode) eval(ctx map[string]interface{}) error {
if _, ok := ctx[n.name]; ok {
return fmt.Errorf("invalid re-declaration: %s", n.name)
}
ctx[n.name] = n.value
return nil
}
type list []interface{} type list []interface{}
type object map[string]interface{} type object map[string]interface{}

Loading…
Cancel
Save