parser.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. package main
  2. // a simplified version of github.com/glycerine/zygomys/repl/parser.go
  3. type Parser struct {
  4. Done chan bool
  5. reqStop chan bool
  6. // client adds input here, typically by calling Parser.NewInput().
  7. // io.RuneScanner supports ReadRune() and UnreadRune().
  8. AddInput chan io.RuneScanner
  9. // client resets old parse and adds new input here,
  10. // typically by calling Parser.ResetAddNewInput()
  11. ReqReset chan io.RuneScanner
  12. // client obtains output here, typically by calling
  13. // Parser.ParseTokens()
  14. ParsedOutput chan []ParserReply
  15. mut sync.Mutex
  16. stopped bool
  17. sendMe []ParserReply
  18. FlagSendNeedInput bool
  19. }
  20. type ParserReply struct {
  21. Expr []Sexp
  22. Err error
  23. }
  24. // NewParser creates a new stopped Parser. Call Start()
  25. // on it before using it.
  26. func (env *Glisp) NewParser() *Parser {
  27. p := &Parser{
  28. env: env,
  29. Done: make(chan bool),
  30. reqStop: make(chan bool),
  31. ReqReset: make(chan io.RuneScanner),
  32. AddInput: make(chan io.RuneScanner),
  33. ParsedOutput: make(chan []ParserReply),
  34. sendMe: make([]ParserReply, 0, 1),
  35. }
  36. p.lexer = NewLexer(p)
  37. return p
  38. }
  39. // ParseTokens is the main service the Parser provides.
  40. // Currently returns first error encountered, ignoring
  41. // any expressions after that.
  42. func (p *Parser) ParseTokens() ([]Sexp, error) {
  43. select {
  44. case out := <-p.ParsedOutput:
  45. // out is type []ParserReply
  46. r := make([]Sexp, 0)
  47. for _, k := range out {
  48. r = append(r, k.Expr...)
  49. if k.Err != nil {
  50. return r, k.Err
  51. }
  52. }
  53. return r, nil
  54. case <-p.reqStop:
  55. return nil, ErrShuttingDown
  56. }
  57. }
  58. // NewInput is the principal API function to
  59. // supply parser with addition textual
  60. // input lines
  61. func (p *Parser) NewInput(s io.RuneScanner) {
  62. select {
  63. case p.AddInput <- s:
  64. case <-p.reqStop:
  65. }
  66. }
  67. // ResetAddNewInput is the principal API function to
  68. // tell the parser to forget everything it has stored,
  69. // reset, and take as new input the scanner s.
  70. func (p *Parser) ResetAddNewInput(s io.RuneScanner) {
  71. select {
  72. case p.ReqReset <- s:
  73. case <-p.reqStop:
  74. }
  75. }
  76. var ParserHaltRequested = fmt.Errorf("parser halt requested")
  77. var ResetRequested = fmt.Errorf("parser reset requested")
  78. // Stop gracefully shutsdown the parser and its background goroutine.
  79. func (p *Parser) Stop() error {
  80. p.mut.Lock()
  81. defer p.mut.Unlock()
  82. if p.stopped {
  83. return nil
  84. }
  85. p.stopped = true
  86. close(p.reqStop)
  87. <-p.Done
  88. return nil
  89. }
  90. // Start() commences the background parse loop goroutine.
  91. func (p *Parser) Start() {
  92. go p.infiniteParsingLoop()
  93. }
  94. var ParserHaltRequested = fmt.Errorf("parser halt requested")
  95. var ResetRequested = fmt.Errorf("parser reset requested")
  96. func (p *Parser) infiniteParsingLoop() {
  97. defer close(p.Done)
  98. expressions := make([]Sexp, 0, SliceDefaultCap)
  99. // maybe we already have input, be optimistic!
  100. // no need to call p.getMoreInput() before staring
  101. // our loop. The client may have already loaded
  102. // some text or a stream that already
  103. // has input ready for us.
  104. for {
  105. expr, err := p.parseExpression(0)
  106. if err != nil || expr == SexpEnd {
  107. if err == ParserHaltRequested {
  108. return
  109. }
  110. // expr == SexpEnd means that parserExpression
  111. // couldn't read another token, so a call to
  112. // getMoreInput() is required.
  113. // provide accumulated expressions
  114. // back to the client here
  115. err = p.getMoreInput(expressions, err)
  116. if err == ParserHaltRequested {
  117. return
  118. }
  119. // getMoreInput() will have delivered
  120. // expressions to the client. Reset expressions since we
  121. // don't own that memory any more.
  122. expressions = make([]Sexp, 0, SliceDefaultCap)
  123. } else {
  124. // INVAR: err == nil && expr is not SexpEnd
  125. expressions = append(expressions, expr)
  126. }
  127. }
  128. }
  129. var ErrMoreInputNeeded = fmt.Errorf("parser needs more input")
  130. // getMoreInput is called by the Parser routines mid-parse, if
  131. // need be, to obtain the next line/rune of input.
  132. //
  133. // getMoreInput() is used by Parser.ParseList(), Parser.ParseArray(),
  134. // Parser.ParseBlockComment(), and Parser.ParseInfix().
  135. //
  136. // getMoreInput() is also used by Parser.infiniteParsingLoop() which
  137. // is the main driver behind parsing.
  138. //
  139. // This function should *return* when it has more input
  140. // for the parser/lexer, which will call it when they get wedged.
  141. //
  142. // Listeners on p.ParsedOutput should know the Convention: sending
  143. // a length 0 []ParserReply on p.ParsedOutput channel means: we need more
  144. // input! They should send some in on p.AddInput channel; or request
  145. // a reset and simultaneously give us new input with p.ReqReset channel.
  146. func (p *Parser) getMoreInput(deliverThese []Sexp, errorToReport error) error {
  147. if len(deliverThese) == 0 && errorToReport == nil {
  148. p.FlagSendNeedInput = true
  149. } else {
  150. p.sendMe = append(p.sendMe,
  151. ParserReply{
  152. Expr: deliverThese,
  153. Err: errorToReport,
  154. })
  155. }
  156. for {
  157. select {
  158. case <-p.reqStop:
  159. return ParserHaltRequested
  160. case input := <-p.AddInput:
  161. p.lexer.AddNextStream(input)
  162. p.FlagSendNeedInput = false
  163. return nil
  164. case input := <-p.ReqReset:
  165. p.lexer.Reset()
  166. p.lexer.AddNextStream(input)
  167. p.FlagSendNeedInput = false
  168. return ResetRequested
  169. case p.HaveStuffToSend() <- p.sendMe:
  170. // that was a conditional send, because
  171. // HaveStuffToSend() will return us a
  172. // nil channel if there's nothing ready.
  173. p.sendMe = make([]ParserReply, 0, 1)
  174. p.FlagSendNeedInput = false
  175. }
  176. }
  177. }
  178. func (p *Parser) HaveStuffToSend() chan []ParserReply {
  179. if len(p.sendMe) > 0 || p.FlagSendNeedInput {
  180. return p.ParsedOutput
  181. }
  182. return nil
  183. }
  184. func (p *Parser) Reset() {
  185. select {
  186. case p.ReqReset <- nil:
  187. case <-p.reqStop:
  188. }
  189. }
  190. var UnexpectedEnd error = errors.New("Unexpected end of input")
  191. // ParserExpression is an internal Parser routine - the
  192. // main one for parsing expressions
  193. func (parser *Parser) parseExpression(depth int) (res Sexp, err error) {
  194. //getAnother:
  195. tok, err := parser.lexer.getNextToken()
  196. if err != nil {
  197. return SexpEnd, err
  198. }
  199. switch tok.typ {
  200. case TokenLParen:
  201. exp, err := parser.parseList(depth + 1)
  202. return exp, err
  203. case TokenLSquare:
  204. exp, err := parser.parseArray(depth + 1)
  205. return exp, err
  206. case TokenLCurly:
  207. exp, err := parser.parseInfix(depth + 1)
  208. return exp, err
  209. case TokenQuote:
  210. expr, err := parser.parseExpression(depth + 1)
  211. if err != nil {
  212. return SexpNull, err
  213. }
  214. return MakeList([]Sexp{parser.env.MakeSymbol("quote"), expr}), nil
  215. case TokenCaret:
  216. //...
  217. }
  218. }
  219. func (parser *Parser) parseArray(depth int) (Sexp, error) {
  220. arr := make([]Sexp, 0, SliceDefaultCap)
  221. var tok Token
  222. var err error
  223. for {
  224. getTok:
  225. for {
  226. tok, err = parser.lexer.peekNextToken()
  227. if err != nil {
  228. return SexpEnd, err
  229. }
  230. if tok.typ == TokenComma {
  231. // pop off the ,
  232. _, _ = parser.lexer.getNextToken()
  233. continue getTok
  234. }
  235. if tok.typ != TokenEnd {
  236. break getTok
  237. } else {
  238. // we ask for more, and then loop
  239. err = parser.getMoreInput(nil, ErrMoreInputNeeded)
  240. switch err {
  241. case ParserHaltRequested:
  242. return SexpNull, err
  243. case ResetRequested:
  244. return SexpEnd, err
  245. }
  246. }
  247. }
  248. if tok.typ == TokenRSquare {
  249. // pop off the ]
  250. _, _ = parser.lexer.getNextToken()
  251. break
  252. }
  253. expr, err := parser.parseExpression(depth + 1)
  254. if err != nil {
  255. return SexpNull, err
  256. }
  257. arr = append(arr, expr)
  258. }
  259. return &SexpArray{Val: arr, Env: parser.env}, nil
  260. }
  261. func (parser *Parser) parseList(depth int) (sx Sexp, err error) {
  262. var tok Token
  263. tokFilled:
  264. for {
  265. // if lexer runs out of tokens it will
  266. // return EndTk = Token{typ: TokenEnd}.
  267. //
  268. tok, err = parser.lexer.peekNextToken()
  269. if err != nil {
  270. return SexpNull, err
  271. }
  272. if tok.typ != TokenEnd {
  273. break tokFilled
  274. }
  275. // instead of returning UnexpectedEnd, we:
  276. err = parser.getMoreInput(nil, ErrMoreInputNeeded)
  277. switch err {
  278. case ParserHaltRequested:
  279. return SexpNull, err
  280. case ResetRequested:
  281. return SexpEnd, err
  282. }
  283. // have to still fill tok, so
  284. // loop to the top to peekNextToken
  285. }
  286. if tok.typ == TokenRParen {
  287. _, _ = parser.lexer.getNextToken()
  288. return SexpNull, nil
  289. }
  290. var start = &SexpPair{}
  291. expr, err := parser.parseExpression(depth + 1)
  292. if err != nil {
  293. return SexpNull, err
  294. }
  295. start.Head = expr
  296. tok, err = parser.lexer.peekNextToken()
  297. if err != nil {
  298. return SexpNull, err
  299. }
  300. // backslash '\' replaces dot '.' in zygomys
  301. if tok.typ == TokenBackslash {
  302. // eat up the backslash
  303. _, _ = parser.lexer.getNextToken()
  304. expr, err = parser.parseExpression(depth + 1)
  305. if err != nil {
  306. return SexpNull, err
  307. }
  308. // eat up the end paren
  309. tok, err = parser.lexer.getNextToken()
  310. if err != nil {
  311. return SexpNull, err
  312. }
  313. // make sure it was actually an end paren
  314. if tok.typ != TokenRParen {
  315. return SexpNull, errors.New("extra value in dotted pair")
  316. }
  317. start.Tail = expr
  318. return start, nil
  319. }
  320. expr, err = parser.parseList(depth + 1)
  321. if err != nil {
  322. return start, err
  323. }
  324. start.Tail = expr
  325. return start, nil
  326. }
  327. func (parser *Parser) ParseBlockComment(start *Token) (sx Sexp, err error) {
  328. defer func() {
  329. if sx != nil {
  330. //Q("returning from ParseBlockComment with sx ='%v', err='%v'",
  331. // sx.SexpString(), err)
  332. }
  333. }()
  334. lexer := parser.lexer
  335. var tok Token
  336. var block = &SexpComment{Block: true, Comment: start.str}
  337. for {
  338. tokFilled:
  339. for {
  340. tok, err = lexer.PeekNextToken()
  341. if err != nil {
  342. return SexpNull, err
  343. }
  344. if tok.typ != TokenEnd {
  345. break tokFilled
  346. }
  347. err = parser.GetMoreInput(nil, ErrMoreInputNeeded)
  348. switch err {
  349. case ParserHaltRequested:
  350. return SexpNull, err
  351. case ResetRequested:
  352. return SexpEnd, err
  353. }
  354. // have to still fill tok, so
  355. // loop to the top to PeekNextToken
  356. }
  357. // consume it
  358. //cons, err := lexer.GetNextToken()
  359. _, err := lexer.GetNextToken()
  360. if err != nil {
  361. return nil, err
  362. }
  363. //Q("parse block comment is consuming '%v'", cons)
  364. switch tok.typ {
  365. case TokenEndBlockComment:
  366. block.Comment += tok.str
  367. return block, nil
  368. case TokenComment:
  369. block.Comment += tok.str
  370. default:
  371. panic("internal error: inside a block comment, we should only see TokenComment and TokenEndBlockComment tokens")
  372. }
  373. }
  374. //return block, nil
  375. }
  376. func (parser *Parser) ParseInfix(depth int) (Sexp, error) {
  377. lexer := parser.lexer
  378. arr := make([]Sexp, 0, SliceDefaultCap)
  379. var err error
  380. var tok Token
  381. for {
  382. getTok:
  383. for {
  384. tok, err = lexer.PeekNextToken()
  385. if err != nil {
  386. return SexpEnd, err
  387. }
  388. if tok.typ != TokenEnd {
  389. break getTok
  390. } else {
  391. //instead of return SexpEnd, UnexpectedEnd
  392. // we ask for more, and then loop
  393. err = parser.GetMoreInput(nil, ErrMoreInputNeeded)
  394. switch err {
  395. case ParserHaltRequested:
  396. return SexpNull, err
  397. case ResetRequested:
  398. return SexpEnd, err
  399. }
  400. }
  401. }
  402. if tok.typ == TokenRCurly {
  403. // pop off the }
  404. _, _ = lexer.GetNextToken()
  405. break
  406. }
  407. Q("debug: ParseInfix(depth=%v) calling ParseExpression", depth)
  408. expr, err := parser.ParseExpression(depth + 1)
  409. if err != nil {
  410. return SexpNull, err
  411. }
  412. Q("debug2: ParseInfix(depth=%v) appending expr = '%v'", depth, expr.SexpString(nil))
  413. arr = append(arr, expr)
  414. }
  415. var list SexpPair
  416. list.Head = parser.env.MakeSymbol("infix")
  417. list.Tail = SexpNull
  418. if len(arr) > 0 {
  419. list.Tail = Cons(&SexpArray{Val: arr, Infix: true, Env: parser.env}, SexpNull)
  420. }
  421. return &list, nil
  422. //return &SexpArray{Val: arr, Infix: true, Env: env}, nil
  423. }