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")
}