blob: 77e8923dd0c8a38825cc61fbf7ed91f270bf30a0 [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "strings"
// an sexpr is an s-expression. It is either a token or a
// parenthesized list of s-expressions.
//
// Used just for initial development. Should we keep it for testing, or
// ditch it once we've plugged into the main compiler output?
type sexpr struct {
compound bool
name string // !compound
parts []sexpr // compound
}
func (s *sexpr) String() string {
if !s.compound {
return s.name
}
x := "("
for i, p := range s.parts {
if i != 0 {
x += " "
}
x += p.String()
}
return x + ")"
}
func parseSexpr(s string) sexpr {
var e string
e, s = grabOne(s)
if len(e) > 0 && e[0] == '(' {
e = e[1 : len(e)-1]
var parts []sexpr
for e != "" {
var p string
p, e = grabOne(e)
parts = append(parts, parseSexpr(p))
}
return sexpr{true, "", parts}
}
return sexpr{false, e, nil}
}
// grabOne peels off first token or parenthesized string from s.
// returns first thing and the remainder of s.
func grabOne(s string) (string, string) {
for len(s) > 0 && s[0] == ' ' {
s = s[1:]
}
if len(s) == 0 || s[0] != '(' {
i := strings.Index(s, " ")
if i < 0 {
return s, ""
}
return s[:i], s[i:]
}
d := 0
i := 0
for {
if len(s) == i {
panic("unterminated s-expression: " + s)
}
if s[i] == '(' {
d++
}
if s[i] == ')' {
d--
if d == 0 {
i++
return s[:i], s[i:]
}
}
i++
}
}