Support for namelists. Fixes #3.
This commit is contained in:
parent
e343ba3689
commit
8cb7110099
2 changed files with 46 additions and 2 deletions
30
expand.go
30
expand.go
|
|
@ -3,6 +3,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
|
@ -136,18 +137,45 @@ func expandSigil(input string, vars map[string][]string) ([]string, int) {
|
|||
c, w := utf8.DecodeRuneInString(input)
|
||||
var offset int
|
||||
var varname string
|
||||
var namelist_pattern = regexp.MustCompile(`^\s*([^:]+)\s*:\s*([^%]*)%([^=]*)\s*=\s*([^%]*)%([^%]*)\s*`)
|
||||
|
||||
// escaping of "$" with "$$"
|
||||
if c == '$' {
|
||||
return []string{"$"}, 2
|
||||
// match bracketed expansions: ${foo}, or ${foo:a%b=c%d}
|
||||
} else if c == '{' {
|
||||
j := strings.IndexRune(input[w:], '}')
|
||||
if j < 0 {
|
||||
return []string{"$" + input}, len(input)
|
||||
}
|
||||
|
||||
varname = input[w : w+j]
|
||||
offset = w + j + 1
|
||||
|
||||
// is this a namelist?
|
||||
mat := namelist_pattern.FindStringSubmatch(varname)
|
||||
if mat != nil && isValidVarName(mat[1]) {
|
||||
// ${varname:a%b=c%d}
|
||||
varname = mat[1]
|
||||
a, b, c, d := mat[2], mat[3], mat[4], mat[5]
|
||||
values, ok := vars[varname]
|
||||
if !ok {
|
||||
return []string{}, offset
|
||||
}
|
||||
|
||||
pat := regexp.MustCompile(strings.Join([]string{`^\Q`, a, `\E(.*)\Q`, b, `\E$`}, ""))
|
||||
expanded_values := make([]string, len(values))
|
||||
for i, value := range values {
|
||||
value_match := pat.FindStringSubmatch(value)
|
||||
if value_match != nil {
|
||||
expanded_values[i] = strings.Join([]string{c, value_match[1], d}, "")
|
||||
} else {
|
||||
expanded_values[i] = value
|
||||
}
|
||||
}
|
||||
|
||||
return expanded_values, offset
|
||||
}
|
||||
// bare variables: $foo
|
||||
} else {
|
||||
// try to match a variable name
|
||||
i := 0
|
||||
|
|
|
|||
18
lex.go
18
lex.go
|
|
@ -11,7 +11,7 @@ type tokenType int
|
|||
const eof rune = '\000'
|
||||
|
||||
// Rune's that cannot be part of a bare (unquoted) string.
|
||||
const nonBareRunes = " \t\n\r\\=:#'\""
|
||||
const nonBareRunes = " \t\n\r\\=:#'\"$"
|
||||
|
||||
// Return true if the string contains whitespace only.
|
||||
func onlyWhitespace(s string) bool {
|
||||
|
|
@ -383,6 +383,14 @@ func lexBareWord(l *lexer) lexerStateFun {
|
|||
l.next()
|
||||
return lexBareWord
|
||||
}
|
||||
} else if c == '$' {
|
||||
c1 := l.peekN(1)
|
||||
if c1 == '{' {
|
||||
return lexBracketExpansion
|
||||
} else {
|
||||
l.next()
|
||||
return lexBareWord
|
||||
}
|
||||
}
|
||||
|
||||
if l.start < l.pos {
|
||||
|
|
@ -391,3 +399,11 @@ func lexBareWord(l *lexer) lexerStateFun {
|
|||
|
||||
return lexTopLevel
|
||||
}
|
||||
|
||||
func lexBracketExpansion(l *lexer) lexerStateFun {
|
||||
l.next() // '$'
|
||||
l.next() // '{'
|
||||
l.acceptUntil("}")
|
||||
l.next() // '}'
|
||||
return lexBareWord
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue