diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/mash/expr.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/cmd/mash/expr.b')
| -rw-r--r-- | appl/cmd/mash/expr.b | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/appl/cmd/mash/expr.b b/appl/cmd/mash/expr.b new file mode 100644 index 00000000..00e45069 --- /dev/null +++ b/appl/cmd/mash/expr.b @@ -0,0 +1,158 @@ +# +# Expression evaluation. +# + +# +# Filename pattern matching. +# +glob(e: ref Env, s: string): (string, list of string) +{ + if (filepat == nil) { + filepat = load Filepat Filepat->PATH; + if (filepat == nil) + e.couldnot("load", Filepat->PATH); + } + l := filepat->expand(s); + if (l != nil) + return (nil, l); + return (s, nil); +} + +# +# RE pattern matching. +# +match(s1, s2: string): int +{ + (re, nil) := regex->compile(s2, 0); + return regex->execute(re, s1) != nil; +} + +# +# RE match of two lists. Two non-singleton lists never match. +# +match2(e: ref Env, s1: string, l1: list of string, s2: string, l2: list of string): int +{ + if (regex == nil) { + regex = load Regex Regex->PATH; + if (regex == nil) + e.couldnot("load", Regex->PATH); + } + if (s1 != nil) { + if (s2 != nil) + return match(s1, s2); + while (l2 != nil) { + if (match(s1, hd l2)) + return 1; + l2 = tl l2; + } + } else if (l1 != nil) { + if (s2 == nil) + return 0; + while (l1 != nil) { + if (match(hd l1, s2)) + return 1; + l1 = tl l1; + } + } else if (s2 != nil) + return match(nil, s2); + else if (l2 != nil) { + while (l2 != nil) { + if (match(nil, hd l2)) + return 1; + l2 = tl l2; + } + } else + return 1; + return 0; +} + +# +# Test list equality. Same length and identical members. +# +eqlist(l1, l2: list of string): int +{ + while (l1 != nil && l2 != nil) { + if (hd l1 != hd l2) + return 0; + l1 = tl l1; + l2 = tl l2; + } + return l1 == nil && l2 == nil; +} + +# +# Equality operator. +# +Cmd.evaleq(c: self ref Cmd, e: ref Env): int +{ + (s1, l1, nil) := c.left.eeval2(e); + (s2, l2, nil) := c.right.eeval2(e); + if (s1 != nil) + return s1 == s2; + if (l1 != nil) + return eqlist(l1, l2); + return s2 == nil && l2 == nil; +} + +# +# Match operator. +# +Cmd.evalmatch(c: self ref Cmd, e: ref Env): int +{ + (s1, l1, nil) := c.left.eeval2(e); + (s2, l2, nil) := c.right.eeval2(e); + return match2(e, s1, l1, s2, l2); +} + +# +# Catenation operator. +# +Item.caret(i: self ref Item, e: ref Env): (string, list of string, int) +{ + (s1, l1, x1) := i.left.ieval2(e); + (s2, l2, x2) := i.right.ieval2(e); + return caret(s1, l1, x1, s2, l2, x2); +} + +# +# Caret of lists. A singleton distributes. Otherwise pairwise, padded with nils. +# +caret(s1: string, l1: list of string, x1: int, s2: string, l2: list of string, x2: int): (string, list of string, int) +{ + l: list of string; + if (s1 != nil) { + if (s2 != nil) + return (s1 + s2, nil, x1 | x2); + if (l2 == nil) + return (s1, nil, x1); + while (l2 != nil) { + l = (s1 + hd l2) :: l; + l2 = tl l2; + } + } else if (s2 != nil) { + if (l1 == nil) + return (s2, nil, x2); + while (l1 != nil) { + l = (hd l1 + s2) :: l; + l1 = tl l1; + } + } else if (l1 != nil) { + if (l2 == nil) + return (nil, l1, 0); + while (l1 != nil || l2 != nil) { + if (l1 != nil) { + s1 = hd l1; + l1 = tl l1; + } else + s1 = nil; + if (l2 != nil) { + s2 = hd l2; + l2 = tl l2; + } else + s2 = nil; + l = (s1 + s2) :: l; + } + } else if (l2 != nil) + return (nil, l2, 0); + return (nil, revstrs(l), 0); +} |
