func parseBinaryExpr(p *Parser, tree ast.Expr, last *ast.BinaryExpr) ast.Expr { if last.Y == nil { switch t := p.nextNonNewline(); { case isUnaryOp(t): unary := &ast.UnaryExpr{Op: t} tree, _ = ast.InsertExpr(tree, unary) return parseUnaryExpr(p, tree, unary) case t.Typ == lex.IDENTIFIER: ident := newIdentExpr(p, t) tree, _ = ast.InsertExpr(tree, ident) return parseLiteralOrIdent(p, tree, ident) case isLiteral(t): bLit := &ast.BasicLit{Tok: t} tree, _ = ast.InsertExpr(tree, bLit) return parseLiteralOrIdent(p, tree, bLit) case t.Typ == lex.LEFTPAREN: paren := newParenExpr(p, t) tree, _ = ast.InsertExpr(tree, paren) return parseParenExpr(p, tree, paren) default: p.errorf("Invalid expression at line %d:%d with token '%s' in file : %s\n", p.lineNumber(), t.Pos, t.Val, p.name) } } else { p.errorf("Internal Error: Invalid parser state in parseBinaryExpr") return nil } return nil }
func parseLiteralOrIdent(p *Parser, tree, last ast.Expr) ast.Expr { switch t := p.next(); { case t.IsOperator(): oper := &ast.BinaryExpr{Op: t} tree, _ = ast.InsertExpr(tree, oper) return parseBinaryExpr(p, tree, oper) case t.Typ == lex.NEWLINE && len(p.pDepth.Stack) > 0: return parseLiteralOrIdent(p, tree, last) case atTerminator(t): return tree case t.Typ == lex.RIGHTPAREN: paren := p.pDepth.pop() paren.Rparen = t return parseParenExpr(p, tree, paren) default: p.errorf("Invalid expression at line %d:%d with token '%s' in file : %s\n", p.lineNumber(), t.Pos, t.Val, p.name) } return nil }
func parseParenExpr(p *Parser, tree ast.Expr, last *ast.ParenExpr) ast.Expr { // if expr.X == nil && expr.Rparen.Val == "" // else if expr.X != nil && expr.Rparen.Val == "" // else if expr.Rparen.Val == ")" // Unclosed Empty paren expr if last.X == nil && last.Rparen.Val == "" { switch t := p.nextNonNewline(); { case t.Typ == lex.IDENTIFIER: ident := newIdentExpr(p, t) tree, _ = ast.InsertExpr(tree, ident) return parseLiteralOrIdent(p, tree, ident) case isLiteral(t): num := &ast.BasicLit{Tok: t} tree, _ = ast.InsertExpr(tree, num) return parseLiteralOrIdent(p, tree, num) case isUnaryOp(t): unary := &ast.UnaryExpr{Op: t} tree, _ = ast.InsertExpr(tree, unary) return parseUnaryExpr(p, tree, unary) case t.Typ == lex.LEFTPAREN: paren := newParenExpr(p, t) tree, _ = ast.InsertExpr(tree, paren) return parseParenExpr(p, tree, paren) case t.Typ == lex.RIGHTPAREN: paren := p.pDepth.pop() paren.Rparen = t if paren != last { p.errorf("Internal error in parseLiteralOrIdent closing paren not matching current paren expr at line %d:%d with token '%s' in file : %s\n", p.lineNumber(), t.Pos, t.Val, p.name) } return parseParenExpr(p, tree, last) default: p.errorf("Invalid expression at line %d:%d with token '%s' in file %s\n", p.lineNumber(), t.Pos, t.Val, p.name) } } else if last.Rparen.Val == ")" { if last.X == nil { // empty closed paren expr () // give value nil to () fmt.Printf("Warning: empty paren expression has value nil") } // Closed non-empty paren expr switch t := p.next(); { case t.IsOperator(): binary := &ast.BinaryExpr{Op: t} tree, _ = ast.InsertExpr(tree, binary) return parseBinaryExpr(p, tree, binary) case t.Typ == lex.LEFTPAREN: p.errorf("Invalid paren expression closed expression followed by opening parenthesis at line %d:%d with token '%s' in file %s\n", p.lineNumber(), t.Pos, t.Val, p.name) return nil case t.Typ == lex.RIGHTPAREN: // close enclosing paren in case parenExpr{X:parenExpr{}} paren := p.pDepth.pop() paren.Rparen = t return parseParenExpr(p, tree, paren) case t.Typ == lex.NEWLINE && len(p.pDepth.Stack) > 0: return parseParenExpr(p, tree, last) case atTerminator(t): return tree default: p.errorf("Invalid paren expression at line %d:%d with token '%s' in file : %s\n", p.lineNumber(), t.Pos, t.Val, p.name) } } else { p.errorf("Internal error in parseParenExpr: at line %d:%d with token '%s' in file: %s\n", p.lineNumber(), p.lastToken.Pos, p.lastToken.Val, p.name) return nil } return nil }