mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-04 10:57:50 +08:00
93 lines
1.8 KiB
Go
93 lines
1.8 KiB
Go
package edit
|
|
|
|
import "github.com/elves/elvish/parse"
|
|
|
|
var tokensBufferSize = 16
|
|
|
|
// Token is a leaf of the parse tree.
|
|
type Token struct {
|
|
Type TokenKind
|
|
Text string
|
|
Node parse.Node
|
|
MoreStyle string
|
|
}
|
|
|
|
// TokenKind classifies Token's.
|
|
type TokenKind int
|
|
|
|
// Values for TokenKind.
|
|
const (
|
|
ParserError TokenKind = iota
|
|
Bareword
|
|
SingleQuoted
|
|
DoubleQuoted
|
|
Variable
|
|
Wildcard
|
|
Tilde
|
|
Sep
|
|
)
|
|
|
|
func parserError(text string) Token {
|
|
return Token{ParserError, text, nil, ""}
|
|
}
|
|
|
|
// tokenize returns all leaves in an AST.
|
|
func tokenize(src string, n parse.Node) []Token {
|
|
lastEnd := 0
|
|
|
|
tokenCh := make(chan Token, tokensBufferSize)
|
|
tokens := []Token{}
|
|
tokensDone := make(chan bool)
|
|
|
|
go func() {
|
|
for token := range tokenCh {
|
|
begin := token.Node.Begin()
|
|
if begin > lastEnd {
|
|
tokens = append(tokens, parserError(src[lastEnd:begin]))
|
|
}
|
|
tokens = append(tokens, token)
|
|
lastEnd = token.Node.End()
|
|
}
|
|
tokensDone <- true
|
|
}()
|
|
produceTokens(n, tokenCh)
|
|
close(tokenCh)
|
|
|
|
<-tokensDone
|
|
if lastEnd != len(src) {
|
|
tokens = append(tokens, parserError(src[lastEnd:]))
|
|
}
|
|
return tokens
|
|
}
|
|
|
|
func produceTokens(n parse.Node, tokenCh chan<- Token) {
|
|
if len(n.Children()) == 0 {
|
|
tokenType := ParserError
|
|
moreStyle := ""
|
|
switch n := n.(type) {
|
|
case *parse.Primary:
|
|
switch n.Type {
|
|
case parse.Bareword:
|
|
tokenType = Bareword
|
|
case parse.SingleQuoted:
|
|
tokenType = SingleQuoted
|
|
case parse.DoubleQuoted:
|
|
tokenType = DoubleQuoted
|
|
case parse.Variable:
|
|
tokenType = Variable
|
|
case parse.Wildcard:
|
|
tokenType = Wildcard
|
|
case parse.Tilde:
|
|
tokenType = Tilde
|
|
}
|
|
case *parse.Sep:
|
|
tokenType = Sep
|
|
moreStyle = styleForSep[n.SourceText()]
|
|
}
|
|
tokenCh <- Token{tokenType, n.SourceText(), n, moreStyle}
|
|
}
|
|
for _, child := range n.Children() {
|
|
produceTokens(child, tokenCh)
|
|
}
|
|
}
|