diff --git a/main.go b/main.go index f3b3d7f..383a140 100644 --- a/main.go +++ b/main.go @@ -7,16 +7,68 @@ import ( "os" ) -func check(r io.Reader) { +func input() io.ReadCloser { + if flag.Arg(1) == "" { + return os.Stdin + } else { + f, err := os.Open(flag.Arg(1)) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %s\n", err) + os.Exit(1) + } + return f + } +} + +func check() { + r := input() + defer r.Close() + _, err := parse(r) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) } } +func lexx() { + r := input() + defer r.Close() + + c := lex(r) + for t := range c { + fmt.Println(t) + } +} + +func parsse() { + r := input() + defer r.Close() + + n, err := parse(r) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %s", err) + os.Exit(1) + } + if err := n.pretty(os.Stdout, ""); err != nil { + fmt.Fprintf(os.Stderr, "error: %s\n", err) + os.Exit(1) + } +} + func main() { flag.Parse() - if flag.NArg() == 0 { - check(os.Stdin) + switch flag.Arg(0) { + case "check": + check() + case "lex": + lexx() + case "parse": + parsse() + case "": + fmt.Fprintf(os.Stderr, "specify an action (check)\n") + os.Exit(1) + default: + fmt.Fprintf(os.Stderr, "no such action: %s\n", flag.Arg(0)) + os.Exit(1) } } diff --git a/node.go b/node.go index 5ab6b6c..06b5170 100644 --- a/node.go +++ b/node.go @@ -1,8 +1,11 @@ package main import ( + "bufio" "bytes" "fmt" + "io" + "strings" ) type nodeType int @@ -14,9 +17,12 @@ const ( n_assignment ) +var indent = " " + type node interface { Type() nodeType parse(*parser) error + pretty(io.Writer, string) error } type rootNode struct { @@ -73,6 +79,17 @@ func (n *rootNode) String() string { return buf.String() } +func (n *rootNode) pretty(w io.Writer, prefix string) error { + fmt.Fprintf(w, "%sroot{\n", prefix) + for _, child := range n.children { + if err := child.pretty(w, prefix+indent); err != nil { + return err + } + } + fmt.Fprintf(w, "%s}\n", prefix) + return nil +} + type commentNode struct { body string } @@ -89,6 +106,26 @@ func (n *commentNode) String() string { return fmt.Sprintf("{comment: %s}", n.body) } +func (n *commentNode) pretty(w io.Writer, prefix string) error { + r := bufio.NewReader(strings.NewReader(n.body)) + fmt.Fprintf(w, "%scomment{\n", prefix) + for { + line, err := r.ReadString('\n') + if err == io.EOF { + if line != "" { + fmt.Fprintf(w, "%s%s%s\n", prefix, indent, line) + } + break + } + if err != nil { + return err + } + fmt.Fprintf(w, "%s%s%s\n", prefix, indent, line) + } + fmt.Fprintf(w, "%s}\n", prefix) + return nil +} + type assignmentNode struct { name string value interface{} @@ -122,5 +159,13 @@ func (n *assignmentNode) String() string { return fmt.Sprintf("{assign: name=%s, val=%v}", n.name, n.value) } +func (n *assignmentNode) pretty(w io.Writer, prefix string) error { + fmt.Fprintf(w, "%sassign{\n", prefix) + fmt.Fprintf(w, "%s%sname: %s\n", prefix, indent, n.name) + fmt.Fprintf(w, "%s%svalue: %v\n", prefix, indent, n.value) + fmt.Fprintf(w, "%s}\n", prefix) + return nil +} + type list []interface{} type object map[string]interface{}