func Parse()

in newt/parse/parse.go [218:308]


func Parse(tokens []Token) (*Node, error) {
	if len(tokens) == 0 {
		return nil, nil
	}

	////// Terminal symbols.

	if len(tokens) == 1 {
		switch tokens[0].Code {
		case TOKEN_NUMBER:
			return &Node{
				Code: PARSE_NUMBER,
				Data: tokens[0].Text,
			}, nil

		case TOKEN_STRING:
			return &Node{
				Code: PARSE_STRING,
				Data: tokens[0].Text,
			}, nil

		case TOKEN_IDENT:
			return &Node{
				Code: PARSE_IDENT,
				Data: tokens[0].Text,
			}, nil

		default:
			return nil, fmt.Errorf("invalid expression: %s", tokens[0].Text)
		}
	}

	////// Nonterminal symbols.

	// <expr><binary><expr>
	binIdx, err := findAnyToken(tokens, binaryTokens)
	if err != nil {
		return nil, err
	}
	if binIdx == 0 || binIdx == len(tokens)-1 {
		return nil, fmt.Errorf("binary operator %s at start or end",
			tokens[binIdx].Text)
	}
	if binIdx != -1 {
		n := &Node{
			Code: binTokenToParse(tokens[binIdx].Code),
			Data: tokens[binIdx].Text,
		}

		l, err := Parse(tokens[0:binIdx])
		if err != nil {
			return nil, err
		}

		r, err := Parse(tokens[binIdx+1 : len(tokens)])
		if err != nil {
			return nil, err
		}

		n.Left = l
		n.Right = r

		return n, nil
	}

	// <unary><expr>
	if tokens[0].Code == TOKEN_NOT {
		n := &Node{
			Code: PARSE_NOT,
			Data: tokens[0].Text,
		}
		r, err := Parse(tokens[1:])
		if err != nil {
			return nil, err
		}
		n.Right = r
		return n, nil
	}

	// "("<expr>")"
	if tokens[0].Code == TOKEN_LPAREN {
		stripped, err := stripParens(tokens)
		if err != nil {
			return nil, err
		}

		return Parse(stripped)
	}

	return nil, fmt.Errorf("invalid expression")
}