You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
2.3 KiB
Go
129 lines
2.3 KiB
Go
package shell
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
func NewWord(wordS string) *Word {
|
|
word := new(Word)
|
|
|
|
for _, c := range wordS {
|
|
word.AddToken(Char(c))
|
|
}
|
|
|
|
return word
|
|
}
|
|
|
|
type Word struct {
|
|
chars []Char
|
|
consecutiveBackslashes int
|
|
}
|
|
|
|
func (w *Word) Tokens() []Token {
|
|
return []Token{}
|
|
}
|
|
|
|
func (w *Word) AddToken(token Token) {
|
|
if char, ok := token.(Char); ok {
|
|
if rune(char) == '\\' {
|
|
w.consecutiveBackslashes += 1
|
|
} else if w.consecutiveBackslashes%2 == 1 {
|
|
if len(w.chars) > 0 {
|
|
w.chars = w.chars[:len(w.chars)-1]
|
|
} else {
|
|
log.Println(
|
|
"Parse error: funky shit is happening, a word with 0" +
|
|
" chars was expected to contain a backslash",
|
|
)
|
|
}
|
|
|
|
w.consecutiveBackslashes = 0
|
|
}
|
|
|
|
w.chars = append(w.chars, char)
|
|
}
|
|
}
|
|
|
|
func (w *Word) Expand(_ State, _ io.Reader, _ io.Writer) ([]string, uint8) {
|
|
var str string
|
|
for _, char := range w.chars {
|
|
str += string(char)
|
|
}
|
|
|
|
return []string{str}, 0
|
|
}
|
|
|
|
func (w *Word) String() string {
|
|
str, _ := w.Expand(nil, nil, nil)
|
|
|
|
return strings.Join(str, "")
|
|
}
|
|
|
|
type WordParameters struct{}
|
|
|
|
func (p *WordParameters) MakeToken() Token {
|
|
return new(Word)
|
|
}
|
|
|
|
var wordRegexp = regexp.MustCompile("[0-9a-zA-Z_.~/:\\\\=-]")
|
|
|
|
func (p *WordParameters) Supports(charsBefore []rune, r rune) bool {
|
|
return wordRegexp.MatchString(string(r))
|
|
}
|
|
|
|
func (p *WordParameters) ShouldLeave(charsBefore []rune, r rune) bool {
|
|
if !p.Supports(charsBefore, r) {
|
|
return countBackslashSuffixes(charsBefore)%2 == 0
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (p *WordParameters) Leave(i *CharIterator) error {
|
|
return i.Previous()
|
|
}
|
|
|
|
func (p *WordParameters) SubParsers() []Parser {
|
|
return []Parser{
|
|
&BaseParser{
|
|
parameters: &CharParserParameters{},
|
|
},
|
|
}
|
|
}
|
|
|
|
type Char rune
|
|
|
|
func (c Char) Tokens() []Token {
|
|
return nil
|
|
}
|
|
|
|
func (c Char) AddToken(_ Token) {}
|
|
|
|
func (c Char) String() string {
|
|
return string(c)
|
|
}
|
|
|
|
type CharParserParameters struct {
|
|
currentRune rune
|
|
}
|
|
|
|
func (p *CharParserParameters) MakeToken() Token {
|
|
return Char(p.currentRune)
|
|
}
|
|
|
|
func (p *CharParserParameters) Supports(charsBefore []rune, r rune) bool {
|
|
p.currentRune = r
|
|
return true
|
|
}
|
|
|
|
func (p *CharParserParameters) ShouldLeave(charsBefore []rune, r rune) bool {
|
|
return true
|
|
}
|
|
|
|
func (p *CharParserParameters) SubParsers() []Parser {
|
|
return nil
|
|
}
|