Fix rule_in_var.mk
Now we parse rules at eval time, not in parse time.
diff --git a/ast.go b/ast.go
index 33ef5be..2997aea 100644
--- a/ast.go
+++ b/ast.go
@@ -47,38 +47,26 @@
Log("%s=%s", ast.lhs, ast.rhs)
}
-type RuleAST struct {
+// Note we cannot be sure what this is, until all variables in |expr|
+// are expanded.
+type MaybeRuleAST struct {
ASTBase
- lhs string
- rhs string
+ expr string
cmds []string
cmdLineno int
}
-func (ast *RuleAST) eval(ev *Evaluator) {
- ev.evalRule(ast)
+func (ast *MaybeRuleAST) eval(ev *Evaluator) {
+ ev.evalMaybeRule(ast)
}
-func (ast *RuleAST) show() {
- Log("%s: %s", ast.lhs, ast.rhs)
+func (ast *MaybeRuleAST) show() {
+ Log("%s", ast.expr)
for _, cmd := range ast.cmds {
Log("\t%s", cmd)
}
}
-type RawExprAST struct {
- ASTBase
- expr string
-}
-
-func (ast *RawExprAST) eval(ev *Evaluator) {
- ev.evalRawExpr(ast)
-}
-
-func (ast *RawExprAST) show() {
- Log("%s", ast.expr)
-}
-
type IncludeAST struct {
ASTBase
expr string
diff --git a/eval.go b/eval.go
index e0e1dd4..060763c 100644
--- a/eval.go
+++ b/eval.go
@@ -132,18 +132,32 @@
ev.outVars[lhs] = rhs
}
-func (ev *Evaluator) evalRule(ast *RuleAST) {
+func (ev *Evaluator) evalMaybeRule(ast *MaybeRuleAST) {
ev.filename = ast.filename
ev.lineno = ast.lineno
+ line := ev.evalExpr(ast.expr)
+ if strings.TrimSpace(line) == "" {
+ if len(ast.cmds) > 0 {
+ Error(ast.filename, ast.cmdLineno, "*** commands commence before first target.")
+ }
+ return
+ }
+
ev.curRule = &Rule{
filename: ast.filename,
lineno: ast.lineno,
cmdLineno: ast.cmdLineno,
}
- lhs := ev.evalExpr(ast.lhs)
+
+ colonIndex := strings.IndexByte(line, ':')
+ if colonIndex < 0 {
+ Error(ast.filename, ast.lineno, "*** missing separator.")
+ }
+
+ lhs := line[:colonIndex]
ev.curRule.output = lhs
- rhs := strings.TrimSpace(ev.evalExpr(ast.rhs))
+ rhs := strings.TrimSpace(line[colonIndex+1:])
if rhs != "" {
re, err := regexp.Compile(`\s+`)
if err != nil {
@@ -155,12 +169,13 @@
for _, cmd := range ast.cmds {
cmds = append(cmds, ev.evalExpr(cmd))
}
- Log("RULE: %s=%s", lhs, rhs)
+ Log("RULE: %s=%s (%d commands)", lhs, rhs, len(cmds))
ev.curRule.cmds = cmds
ev.outRules = append(ev.outRules, ev.curRule)
ev.curRule = nil
}
+/*
func (ev *Evaluator) evalRawExpr(ast *RawExprAST) {
ev.filename = ast.filename
ev.lineno = ast.lineno
@@ -171,6 +186,7 @@
Error(ast.filename, ast.lineno, "*** missing separator.")
}
}
+*/
func (ev *Evaluator) getVar(name string) (string, bool) {
value, present := ev.outVars[name]
diff --git a/parser.go b/parser.go
index 2f7af91..9fd5eef 100644
--- a/parser.go
+++ b/parser.go
@@ -110,12 +110,16 @@
return ast
}
-func (p *parser) parseRule(line []byte, sep int) AST {
- lhs := string(bytes.TrimSpace(line[:sep]))
- rhs := string(bytes.TrimSpace(line[sep+1:]))
- ast := &RuleAST{
- lhs: lhs,
- rhs: rhs,
+func (p *parser) parseMaybeRule(line string) AST {
+ if len(strings.TrimSpace(line)) == 0 {
+ return nil
+ }
+ if line[0] == '\t' {
+ Error(p.filename, p.lineno, "*** commands commence before first target.")
+ }
+
+ ast := &MaybeRuleAST{
+ expr: line,
}
ast.filename = p.filename
ast.lineno = p.lineno
@@ -312,13 +316,6 @@
return false
}
-func (p *parser) parseLine(line string) AST {
- ast := &RawExprAST{expr: line}
- ast.filename = p.filename
- ast.lineno = p.lineno
- return ast
-}
-
func (p *parser) parse() (mk Makefile, err error) {
defer func() {
if r := recover(); r != nil {
@@ -339,7 +336,7 @@
if i+1 < len(line) && line[i+1] == '=' {
ast = p.parseAssign(line, i, i+2)
} else {
- ast = p.parseRule(line, i)
+ ast = p.parseMaybeRule(string(line))
}
case '=':
ast = p.parseAssign(line, i, i+1)
@@ -353,9 +350,11 @@
break
}
}
- if ast == nil && len(bytes.TrimSpace(line)) > 0 {
- ast = p.parseLine(string(line))
- p.addStatement(ast)
+ if ast == nil {
+ ast = p.parseMaybeRule(string(line))
+ if ast != nil {
+ p.addStatement(ast)
+ }
}
}
return p.mk, nil
diff --git a/test/err_no_target_commands.mk b/test/err_no_target_commands.mk
new file mode 100644
index 0000000..2113a57
--- /dev/null
+++ b/test/err_no_target_commands.mk
@@ -0,0 +1 @@
+ all:
diff --git a/test/err_no_target_commands2.mk b/test/err_no_target_commands2.mk
new file mode 100644
index 0000000..47570b1
--- /dev/null
+++ b/test/err_no_target_commands2.mk
@@ -0,0 +1,2 @@
+$(empty)
+ all:
diff --git a/test/rule_in_var.mk b/test/rule_in_var.mk
index c527cb5..caf4303 100644
--- a/test/rule_in_var.mk
+++ b/test/rule_in_var.mk
@@ -1,5 +1,3 @@
-# TODO: Implement this. We probably need this.
-
RULE=foo:
test: foo