fix subst.mk
add wildcard_with_commas.mk
add go_test make targets for run go unittest.
diff --git a/parser.go b/parser.go
index 0815e6b..133d100 100644
--- a/parser.go
+++ b/parser.go
@@ -157,52 +157,76 @@
return ast
}
-func (p *parser) parseEq(s string) (string, string, bool) {
- if len(s) == 0 || s[0] != '(' {
- return "", "", false
+func closeParen(ch byte) (byte, error) {
+ switch ch {
+ case '(':
+ return ')', nil
+ case '{':
+ return '}', nil
+ default:
+ return 0, fmt.Errorf("unexpected paren %c", ch)
}
+}
+// parseExpr parses s as expr.
+// The expr should starts with '(' or '{' and returns strings
+// separeted by ',' before ')' or '}' respectively, and an index for the rest.
+func parseExpr(s string) ([]string, int, error) {
+ if len(s) == 0 {
+ return nil, 0, errors.New("empty expr")
+ }
+ paren, err := closeParen(s[0])
+ if err != nil {
+ return nil, 0, err
+ }
+ parenCnt := make(map[byte]int)
i := 0
- parenCnt := 0
- inRhs := false
- var lhs []byte
- var rhs []byte
+ ia := 1
+ var args []string
+Loop:
for {
i++
if i == len(s) {
- return "", "", false
+ return nil, 0, errors.New("unexpected end of expr")
}
ch := s[i]
- if ch == '(' {
- parenCnt++
- } else if ch == ')' {
- parenCnt--
- if parenCnt < 0 {
- if inRhs {
- break
- } else {
- return "", "", false
- }
+ switch ch {
+ case '(', '{':
+ cch, err := closeParen(ch)
+ if err != nil {
+ return nil, 0, err
}
- } else if ch == ',' {
- if inRhs {
- return "", "", false
- } else {
- inRhs = true
- continue
+ parenCnt[cch]++
+ case ')', '}':
+ parenCnt[ch]--
+ if ch == paren && parenCnt[ch] < 0 {
+ break Loop
}
- }
- if inRhs {
- rhs = append(rhs, ch)
- } else {
- lhs = append(lhs, ch)
+ case ',':
+ if parenCnt[')'] == 0 && parenCnt['}'] == 0 {
+ args = append(args, s[ia:i])
+ ia = i + 1
+ }
}
}
- return string(lhs), string(rhs), true
+ args = append(args, s[ia:i])
+ return args, i + 1, nil
+}
+
+func parseEq(s string) (string, string, bool) {
+ args, _, err := parseExpr(s)
+ if err != nil {
+ return "", "", false
+ }
+ if len(args) != 2 {
+ return "", "", false
+ }
+ // TODO: check rest?
+ return args[0], args[1], true
}
func (p *parser) parseIfeq(line string, oplen int) AST {
- lhs, rhs, ok := p.parseEq(strings.TrimSpace(line[oplen+1:]))
+ lhs, rhs, ok := parseEq(strings.TrimSpace(line[oplen+1:]))
if !ok {
Error(p.filename, p.lineno, `*** invalid syntax in conditional.`)
}