refactor assign ast.
diff --git a/ast.go b/ast.go
index 137c29a..4525136 100644
--- a/ast.go
+++ b/ast.go
@@ -1,5 +1,7 @@
 package main
 
+import "fmt"
+
 type AST interface {
 	eval(*Evaluator)
 	show()
@@ -10,24 +12,28 @@
 	lineno   int
 }
 
-const (
-	ASSIGN_SIMPLE      = iota // :=
-	ASSIGN_RECURSIVE          // =
-	ASSIGN_APPEND             // +=
-	ASSIGN_CONDITIONAL        // ?=
-)
-
 type AssignAST struct {
 	ASTBase
-	lhs         string
-	rhs         string
-	assign_type int
+	lhs string
+	rhs string
+	op  string
 }
 
 func (ast *AssignAST) eval(ev *Evaluator) {
 	ev.evalAssign(ast)
 }
 
+func (ast *AssignAST) evalRHS(ev *Evaluator) string {
+	switch ast.op {
+	case ":=":
+		return ev.evalExpr(ast.rhs)
+	case "=":
+		return ast.rhs
+	default: // "+=", "?="
+		panic(fmt.Sprintf("not implemented assign op: %q", ast.op))
+	}
+}
+
 func (ast *AssignAST) show() {
 	Log("%s=%s", ast.lhs, ast.rhs)
 }
diff --git a/eval.go b/eval.go
index 590a7ae..42aa35a 100644
--- a/eval.go
+++ b/eval.go
@@ -133,15 +133,7 @@
 	ev.lineno = ast.lineno
 
 	lhs := ev.evalExpr(ast.lhs)
-	var rhs string
-	switch ast.assign_type {
-	case ASSIGN_SIMPLE:
-		rhs = ev.evalExpr(ast.rhs)
-	case ASSIGN_RECURSIVE:
-		rhs = ast.rhs
-	default:
-		panic("TODO")
-	}
+	rhs := ast.evalRHS(ev)
 	Log("ASSIGN: %s=%s", lhs, rhs)
 	ev.outVars[lhs] = rhs
 }
diff --git a/parser.go b/parser.go
index 553a512..4a45b6f 100644
--- a/parser.go
+++ b/parser.go
@@ -84,15 +84,13 @@
 	p.hasUnBuf = true
 }
 
-func (p *parser) parseAssign(line []byte, sep int, typ int) AST {
-	Log("parseAssign %s %d", line, sep)
-	esep := sep + 1
-	if typ != ASSIGN_RECURSIVE {
-		esep++
+func (p *parser) parseAssign(line []byte, sep, esep int) AST {
+	Log("parseAssign %s %s", line, line[sep:esep])
+	ast := &AssignAST{
+		lhs: string(bytes.TrimSpace(line[:sep])),
+		rhs: string(bytes.TrimLeft(line[esep:], " \t")),
+		op:  string(line[sep:esep]),
 	}
-	lhs := string(bytes.TrimSpace(line[:sep]))
-	rhs := string(bytes.TrimLeft(line[esep:], " \t"))
-	ast := &AssignAST{lhs: lhs, rhs: rhs, assign_type: typ}
 	ast.filename = p.filename
 	ast.lineno = p.lineno
 	return ast
@@ -135,12 +133,12 @@
 			switch ch {
 			case ':':
 				if i+1 < len(line) && line[i+1] == '=' {
-					ast = p.parseAssign(line, i, ASSIGN_SIMPLE)
+					ast = p.parseAssign(line, i, i+2)
 				} else {
 					ast = p.parseRule(line, i)
 				}
 			case '=':
-				ast = p.parseAssign(line, i, ASSIGN_RECURSIVE)
+				ast = p.parseAssign(line, i, i+1)
 			case '?':
 				panic("TODO")
 			}