ginger/expr/parse.go

300 lines
7.3 KiB
Go

package expr
//type exprErr struct {
// reason string
// err error
// tok lexer.Token
// tokCtx string // e.g. "block starting at" or "open paren at"
//}
//
//func (e exprErr) Error() string {
// var msg string
// if e.err != nil {
// msg = e.err.Error()
// } else {
// msg = e.reason
// }
// if err := e.tok.Err(); err != nil {
// msg += " - token error: " + err.Error()
// } else if (e.tok != lexer.Token{}) {
// msg += " - "
// if e.tokCtx != "" {
// msg += e.tokCtx + ": "
// }
// msg = fmt.Sprintf("%s [line:%d col:%d]", msg, e.tok.Row, e.tok.Col)
// }
// return msg
//}
//
//////////////////////////////////////////////////////////////////////////////////
//
//// toks[0] must be start
//func sliceEnclosedToks(toks []lexer.Token, start, end lexer.Token) ([]lexer.Token, []lexer.Token, error) {
// c := 1
// ret := []lexer.Token{}
// first := toks[0]
// for i, tok := range toks[1:] {
// if tok.Err() != nil {
// return nil, nil, exprErr{
// reason: fmt.Sprintf("missing closing %v", end),
// tok: tok,
// }
// }
//
// if tok.Equal(start) {
// c++
// } else if tok.Equal(end) {
// c--
// }
// if c == 0 {
// return ret, toks[2+i:], nil
// }
// ret = append(ret, tok)
// }
//
// return nil, nil, exprErr{
// reason: fmt.Sprintf("missing closing %v", end),
// tok: first,
// tokCtx: "starting at",
// }
//}
//
//// Parse reads in all expressions it can from the given io.Reader and returns
//// them
//func Parse(r io.Reader) ([]Expr, error) {
// toks := readAllToks(r)
// var ret []Expr
// var expr Expr
// var err error
// for len(toks) > 0 {
// if toks[0].TokenType == lexer.EOF {
// return ret, nil
// }
// expr, toks, err = parse(toks)
// if err != nil {
// return nil, err
// }
// ret = append(ret, expr)
// }
// return ret, nil
//}
//
//// ParseAsBlock reads the given io.Reader as if it was implicitly surrounded by
//// curly braces, making it into a Block. This means all expressions from the
//// io.Reader *must* be statements. The returned Expr's Actual will always be a
//// Block.
//func ParseAsBlock(r io.Reader) (Expr, error) {
// return parseBlock(readAllToks(r))
//}
//
//func readAllToks(r io.Reader) []lexer.Token {
// l := lexer.New(r)
// var toks []lexer.Token
// for l.HasNext() {
// toks = append(toks, l.Next())
// }
// return toks
//}
//
//// For all parse methods it is assumed that toks is not empty
//
//var (
// openParen = lexer.Token{TokenType: lexer.Wrapper, Val: "("}
// closeParen = lexer.Token{TokenType: lexer.Wrapper, Val: ")"}
// openCurly = lexer.Token{TokenType: lexer.Wrapper, Val: "{"}
// closeCurly = lexer.Token{TokenType: lexer.Wrapper, Val: "}"}
// comma = lexer.Token{TokenType: lexer.Punctuation, Val: ","}
// arrow = lexer.Token{TokenType: lexer.Punctuation, Val: ">"}
//)
//
//func parse(toks []lexer.Token) (Expr, []lexer.Token, error) {
// expr, toks, err := parseSingle(toks)
// if err != nil {
// return Expr{}, nil, err
// }
//
// if len(toks) > 0 && toks[0].TokenType == lexer.Punctuation {
// return parseConnectingPunct(toks, expr)
// }
//
// return expr, toks, nil
//}
//
//func parseSingle(toks []lexer.Token) (Expr, []lexer.Token, error) {
// var expr Expr
// var err error
//
// if toks[0].Err() != nil {
// return Expr{}, nil, exprErr{
// reason: "could not parse token",
// tok: toks[0],
// }
// }
//
// if toks[0].Equal(openParen) {
// starter := toks[0]
// var ptoks []lexer.Token
// ptoks, toks, err = sliceEnclosedToks(toks, openParen, closeParen)
// if err != nil {
// return Expr{}, nil, err
// }
//
// if expr, ptoks, err = parse(ptoks); err != nil {
// return Expr{}, nil, err
// } else if len(ptoks) > 0 {
// return Expr{}, nil, exprErr{
// reason: "multiple expressions inside parenthesis",
// tok: starter,
// tokCtx: "starting at",
// }
// }
// return expr, toks, nil
//
// } else if toks[0].Equal(openCurly) {
// var btoks []lexer.Token
// btoks, toks, err = sliceEnclosedToks(toks, openCurly, closeCurly)
// if err != nil {
// return Expr{}, nil, err
// }
//
// if expr, err = parseBlock(btoks); err != nil {
// return Expr{}, nil, err
// }
// return expr, toks, nil
// }
//
// if expr, err = parseNonPunct(toks[0]); err != nil {
// return Expr{}, nil, err
// }
// return expr, toks[1:], nil
//}
//
//func parseNonPunct(tok lexer.Token) (Expr, error) {
// if tok.TokenType == lexer.Identifier {
// return parseIdentifier(tok)
// } else if tok.TokenType == lexer.String {
// //return parseString(tok)
// }
//
// return Expr{}, exprErr{
// reason: "unexpected non-punctuation token",
// tok: tok,
// }
//}
//
//func parseIdentifier(t lexer.Token) (Expr, error) {
// e := Expr{Token: t}
// if t.Val[0] == '-' || (t.Val[0] >= '0' && t.Val[0] <= '9') {
// n, err := strconv.ParseInt(t.Val, 10, 64)
// if err != nil {
// return Expr{}, exprErr{
// err: err,
// tok: t,
// }
// }
// e.Actual = Int(n)
//
// /*
// } else if t.Val == "%true" {
// e.Actual = Bool(true)
//
// } else if t.Val == "%false" {
// e.Actual = Bool(false)
// */
//
// } else if t.Val[0] == '%' {
// e.Actual = Macro(t.Val[1:])
//
// } else {
// e.Actual = Identifier(t.Val)
// }
//
// return e, nil
//}
//
///*
//func parseString(t lexer.Token) (Expr, error) {
// str, err := strconv.Unquote(t.Val)
// if err != nil {
// return Expr{}, exprErr{
// err: err,
// tok: t,
// }
// }
// return Expr{Token: t, Actual: String(str)}, nil
//}
//*/
//
//func parseConnectingPunct(toks []lexer.Token, root Expr) (Expr, []lexer.Token, error) {
// if toks[0].Equal(comma) {
// return parseTuple(toks, root)
//
// } else if toks[0].Equal(arrow) {
// expr, toks, err := parse(toks[1:])
// if err != nil {
// return Expr{}, nil, err
// }
// return Expr{Token: root.Token, Actual: Statement{In: root, To: expr}}, toks, nil
// }
//
// return root, toks, nil
//}
//
//func parseTuple(toks []lexer.Token, root Expr) (Expr, []lexer.Token, error) {
// rootTup, ok := root.Actual.(Tuple)
// if !ok {
// rootTup = Tuple{root}
// }
//
// // rootTup is modified throughout, be we need to make it into an Expr for
// // every return, which is annoying. so make a function to do it on the fly
// mkRoot := func() Expr {
// return Expr{Token: rootTup[0].Token, Actual: rootTup}
// }
//
// if len(toks) < 2 {
// return mkRoot(), toks, nil
// } else if !toks[0].Equal(comma) {
// if toks[0].TokenType == lexer.Punctuation {
// return parseConnectingPunct(toks, mkRoot())
// }
// return mkRoot(), toks, nil
// }
//
// var expr Expr
// var err error
// if expr, toks, err = parseSingle(toks[1:]); err != nil {
// return Expr{}, nil, err
// }
//
// rootTup = append(rootTup, expr)
// return parseTuple(toks, mkRoot())
//}
//
//// parseBlock assumes that the given token list is the entire block, already
//// pulled from outer curly braces by sliceEnclosedToks, or determined to be the
//// entire block in some other way.
//func parseBlock(toks []lexer.Token) (Expr, error) {
// b := Block{}
// first := toks[0]
// var expr Expr
// var err error
// for {
// if len(toks) == 0 {
// return Expr{Token: first, Actual: b}, nil
// }
//
// if expr, toks, err = parse(toks); err != nil {
// return Expr{}, err
// }
// if _, ok := expr.Actual.(Statement); !ok {
// return Expr{}, exprErr{
// reason: "blocks may only contain full statements",
// tok: expr.Token,
// tokCtx: "non-statement here",
// }
// }
// b = append(b, expr)
// }
//}