package hhc_ast import ( "git.swzry.com/zry/go-hhc-cli/hhc_common" ) type SDTLineParser struct { walker *SDTWalker currentToken []rune currentRunePos int errInParse bool errMsg hhc_common.SDTWalkError errPos int status hhc_common.InputStatusCode willPrintHelp bool helpMsg []hhc_common.SDTHelpInfo helpTrigged bool } func NewSDTLineParser(walker *SDTWalker) *SDTLineParser { p := &SDTLineParser{ walker: walker, } p.Reset() return p } func (p *SDTLineParser) HasError() bool { return p.errInParse } func (p *SDTLineParser) HelpTriggerd() bool { return p.helpTrigged } func (p *SDTLineParser) WillPrintHelp() bool { return p.willPrintHelp } func (p *SDTLineParser) GetError() (err hhc_common.SDTWalkError, pos int) { return p.errMsg, p.errPos } func (p *SDTLineParser) GetHelpMessage() []hhc_common.SDTHelpInfo { return p.helpMsg } func (p *SDTLineParser) Reset() { p.currentToken = []rune{} p.errInParse = false p.currentRunePos = 0 p.errMsg = nil p.errPos = 0 p.status = hhc_common.InputStat_Normal p.willPrintHelp = false p.helpMsg = nil p.helpTrigged = false p.walker.Reset() } func (p *SDTLineParser) Parse(rs []rune) { for i, v := range rs { p.currentRunePos = i quit := p.pushRune(v) if quit { return } } } func (p *SDTLineParser) TryGetRunFunc() (bool, ExecuteFunc) { if !p.errInParse { if len(p.currentToken) > 0 { tok := string(p.currentToken) p.currentToken = []rune{} ok := p.walker.NextStep(tok) if !ok { p.errInParse = true p.errPos = p.currentRunePos if p.walker.HasError() { p.errMsg = p.walker.GetError() } return false, nil } } ok := p.walker.NextStep("") if !ok { p.errInParse = true p.errPos = p.currentRunePos if p.walker.HasError() { p.errMsg = p.walker.GetError() } return false, nil } else { return p.walker.GetEndExecute() } } return false, nil } func (p *SDTLineParser) pushRune(r rune) bool { switch p.status { case hhc_common.InputStat_Normal: return p.pushNormal(r) case hhc_common.InputStat_Quote: return p.pushQuote(r) case hhc_common.InputStat_BackslashEscape: return p.pushBackslashEscape(r) default: return true } } func (p *SDTLineParser) pushBackslashEscape(r rune) bool { switch r { case '\\': p.currentToken = append(p.currentToken, '\\') break case '"': p.currentToken = append(p.currentToken, '"') break } p.status = hhc_common.InputStat_Quote return false } func (p *SDTLineParser) pushQuote(r rune) bool { switch r { case '\\': p.status = hhc_common.InputStat_BackslashEscape return false case '"': p.status = hhc_common.InputStat_Normal return false default: p.currentToken = append(p.currentToken, r) return false } } func (p *SDTLineParser) GetHelpListForTabComplete() ([]hhc_common.SDTHelpInfo, string) { tok := string(p.currentToken) return p.walker.GetHelps(tok), tok } func (p *SDTLineParser) GetWalkContext() *SDTWalkContext { return p.walker.GetContext() } func (p *SDTLineParser) pushNormal(r rune) bool { switch r { case ' ': if !p.errInParse { tok := string(p.currentToken) p.currentToken = []rune{} if len(tok) == 0 { return false } ok := p.walker.NextStep(tok) if !ok { p.errInParse = true p.errPos = p.currentRunePos if p.walker.HasError() { p.errMsg = p.walker.GetError() } } } return false case '?': p.helpTrigged = true if !p.errInParse { p.willPrintHelp = true p.helpMsg = p.walker.GetHelps(string(p.currentToken)) if len(p.helpMsg) == 0 { p.willPrintHelp = false p.errInParse = true p.errMsg = hhc_common.SDTWalkError_UnrecognizedCommand{RelyToken: string(p.currentToken)} p.errPos = p.currentRunePos } } return true case '"': p.status = hhc_common.InputStat_Quote return false default: p.currentToken = append(p.currentToken, r) return false } }