コード例 #1
0
ファイル: parser.go プロジェクト: jmptrader/calc
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
}
コード例 #2
0
ファイル: parser.go プロジェクト: jmptrader/calc
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
}
コード例 #3
0
ファイル: parser.go プロジェクト: jmptrader/calc
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
}