sdt_lineparser.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package hhc_ast
  2. import (
  3. "git.swzry.com/zry/go-hhc-cli/hhc_common"
  4. )
  5. type SDTLineParser struct {
  6. walker *SDTWalker
  7. currentToken []rune
  8. currentRunePos int
  9. errInParse bool
  10. errMsg hhc_common.SDTWalkError
  11. errPos int
  12. status hhc_common.InputStatusCode
  13. willPrintHelp bool
  14. helpMsg []hhc_common.SDTHelpInfo
  15. helpTrigged bool
  16. }
  17. func NewSDTLineParser(walker *SDTWalker) *SDTLineParser {
  18. p := &SDTLineParser{
  19. walker: walker,
  20. }
  21. p.Reset()
  22. return p
  23. }
  24. func (p *SDTLineParser) HasError() bool {
  25. return p.errInParse
  26. }
  27. func (p *SDTLineParser) HelpTriggerd() bool {
  28. return p.helpTrigged
  29. }
  30. func (p *SDTLineParser) WillPrintHelp() bool {
  31. return p.willPrintHelp
  32. }
  33. func (p *SDTLineParser) GetError() (err hhc_common.SDTWalkError, pos int) {
  34. return p.errMsg, p.errPos
  35. }
  36. func (p *SDTLineParser) GetHelpMessage() []hhc_common.SDTHelpInfo {
  37. return p.helpMsg
  38. }
  39. func (p *SDTLineParser) Reset() {
  40. p.currentToken = []rune{}
  41. p.errInParse = false
  42. p.currentRunePos = 0
  43. p.errMsg = nil
  44. p.errPos = 0
  45. p.status = hhc_common.InputStat_Normal
  46. p.willPrintHelp = false
  47. p.helpMsg = nil
  48. p.helpTrigged = false
  49. p.walker.Reset()
  50. }
  51. func (p *SDTLineParser) Parse(rs []rune) {
  52. for i, v := range rs {
  53. p.currentRunePos = i
  54. quit := p.pushRune(v)
  55. if quit {
  56. return
  57. }
  58. }
  59. }
  60. func (p *SDTLineParser) TryGetRunFunc() (bool, ExecuteFunc) {
  61. if !p.errInParse {
  62. if len(p.currentToken) > 0 {
  63. tok := string(p.currentToken)
  64. p.currentToken = []rune{}
  65. ok := p.walker.NextStep(tok)
  66. if !ok {
  67. p.errInParse = true
  68. p.errPos = p.currentRunePos
  69. if p.walker.HasError() {
  70. p.errMsg = p.walker.GetError()
  71. }
  72. return false, nil
  73. }
  74. }
  75. ok := p.walker.NextStep("")
  76. if !ok {
  77. p.errInParse = true
  78. p.errPos = p.currentRunePos
  79. if p.walker.HasError() {
  80. p.errMsg = p.walker.GetError()
  81. }
  82. return false, nil
  83. } else {
  84. return p.walker.GetEndExecute()
  85. }
  86. }
  87. return false, nil
  88. }
  89. func (p *SDTLineParser) pushRune(r rune) bool {
  90. switch p.status {
  91. case hhc_common.InputStat_Normal:
  92. return p.pushNormal(r)
  93. case hhc_common.InputStat_Quote:
  94. return p.pushQuote(r)
  95. case hhc_common.InputStat_BackslashEscape:
  96. return p.pushBackslashEscape(r)
  97. default:
  98. return true
  99. }
  100. }
  101. func (p *SDTLineParser) pushBackslashEscape(r rune) bool {
  102. switch r {
  103. case '\\':
  104. p.currentToken = append(p.currentToken, '\\')
  105. break
  106. case '"':
  107. p.currentToken = append(p.currentToken, '"')
  108. break
  109. }
  110. p.status = hhc_common.InputStat_Quote
  111. return false
  112. }
  113. func (p *SDTLineParser) pushQuote(r rune) bool {
  114. switch r {
  115. case '\\':
  116. p.status = hhc_common.InputStat_BackslashEscape
  117. return false
  118. case '"':
  119. p.status = hhc_common.InputStat_Normal
  120. return false
  121. default:
  122. p.currentToken = append(p.currentToken, r)
  123. return false
  124. }
  125. }
  126. func (p *SDTLineParser) GetHelpListForTabComplete() ([]hhc_common.SDTHelpInfo, string) {
  127. tok := string(p.currentToken)
  128. return p.walker.GetHelps(tok), tok
  129. }
  130. func (p *SDTLineParser) GetWalkContext() *SDTWalkContext {
  131. return p.walker.GetContext()
  132. }
  133. func (p *SDTLineParser) pushNormal(r rune) bool {
  134. switch r {
  135. case ' ':
  136. if !p.errInParse {
  137. tok := string(p.currentToken)
  138. p.currentToken = []rune{}
  139. if len(tok) == 0 {
  140. return false
  141. }
  142. ok := p.walker.NextStep(tok)
  143. if !ok {
  144. p.errInParse = true
  145. p.errPos = p.currentRunePos
  146. if p.walker.HasError() {
  147. p.errMsg = p.walker.GetError()
  148. }
  149. }
  150. }
  151. return false
  152. case '?':
  153. p.helpTrigged = true
  154. if !p.errInParse {
  155. p.willPrintHelp = true
  156. p.helpMsg = p.walker.GetHelps(string(p.currentToken))
  157. if len(p.helpMsg) == 0 {
  158. p.willPrintHelp = false
  159. p.errInParse = true
  160. p.errMsg = hhc_common.SDTWalkError_UnrecognizedCommand{RelyToken: string(p.currentToken)}
  161. p.errPos = p.currentRunePos
  162. }
  163. }
  164. return true
  165. case '"':
  166. p.status = hhc_common.InputStat_Quote
  167. return false
  168. default:
  169. p.currentToken = append(p.currentToken, r)
  170. return false
  171. }
  172. }