error.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package parser
  2. import (
  3. "kumachan/standalone/util/richtext"
  4. "kumachan/lang/textual/cst"
  5. "kumachan/lang/textual/syntax"
  6. )
  7. type Error struct {
  8. IsScannerError bool
  9. ScannerError error
  10. Tree *cst.Tree
  11. HasExpectedPart bool
  12. ExpectedPart syntax.Id
  13. NodeIndex int // may be bigger than the index of last token
  14. }
  15. func (err *Error) IsEmptyTree() bool {
  16. return err.NodeIndex < 0 || len(err.Tree.Tokens) == 0
  17. }
  18. func (err *Error) Desc() richtext.Block {
  19. if err.IsScannerError {
  20. var desc richtext.Block
  21. desc.WriteLine(err.ScannerError.Error(), richtext.TAG_ERR)
  22. return desc
  23. }
  24. if err.IsEmptyTree() {
  25. var desc richtext.Block
  26. desc.WriteLine("empty input", richtext.TAG_ERR)
  27. return desc
  28. }
  29. var node = err.Tree.Nodes[err.NodeIndex]
  30. var got string
  31. if node.Pos >= len(err.Tree.Tokens) {
  32. got = "EOF"
  33. } else {
  34. got = syntax.Id2Name(err.Tree.Tokens[node.Pos].Id)
  35. }
  36. var desc richtext.Block
  37. if err.HasExpectedPart {
  38. desc.WriteSpan("Syntax unit", richtext.TAG_ERR)
  39. desc.WriteSpan(syntax.Id2Name(err.ExpectedPart), richtext.TAG_ERR_INLINE)
  40. desc.WriteSpan("expected", richtext.TAG_ERR)
  41. } else {
  42. desc.WriteSpan("Parser stuck", richtext.TAG_ERR)
  43. }
  44. desc.WriteSpan("(", richtext.TAG_ERR)
  45. desc.WriteSpan("got", richtext.TAG_ERR)
  46. desc.WriteSpan(got, richtext.TAG_ERR_INLINE)
  47. desc.WriteSpan(")", richtext.TAG_ERR)
  48. return desc
  49. }
  50. func (err *Error) Message() richtext.Block {
  51. if err.IsScannerError {
  52. return err.Desc()
  53. }
  54. if err.IsEmptyTree() {
  55. return err.Desc()
  56. }
  57. var tree = err.Tree
  58. var token = cst.GetNodeFirstToken(tree, err.NodeIndex)
  59. var point = tree.Info[token.Span.Start]
  60. var desc = err.Desc()
  61. const FOV = 5
  62. return cst.FormatError (
  63. tree.Name, tree.Code, tree.Info, tree.SpanMap,
  64. point, token.Span, FOV, desc,
  65. )
  66. }
  67. func (err *Error) Error() string {
  68. return err.Message().RenderConsole()
  69. }