parser.km 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. type Parser [out T, out E]
  2. &(String) => Result[(T,String),(E,String)];
  3. // note: currently, the error type (E,String) is an ad-hoc implementation
  4. // (fatal errors and non-fatal errors should be distinguished)
  5. function make-lazy:[T,E]
  6. &(&() => Parser[T,E]) => Parser[T,E]
  7. &(thunk) => &(input) =>
  8. let parse := { thunk () },
  9. { parse input };
  10. function output:[T]
  11. &(T) => Parser[T,never]
  12. &(value) => &(input) => { Success (value, input) };
  13. function throw:[E]
  14. &(E) => Parser[never,E]
  15. &(err) => &(input) => { Failure (err, input) };
  16. function consume:[E]
  17. &(String, E) => Parser[unit,E]
  18. &(target, err) => &(input) =>
  19. switch (input.[String] shift-prefix target):
  20. case Some input:
  21. { Success ((), input) },
  22. case None:
  23. { Failure (err, input) },
  24. end;
  25. function with-ignored:[T,E]
  26. &(Parser[T,E], Parser[unit,E]) => Parser[T,E]
  27. &(parse-t, parse-blank) =>
  28. let parse-blanks:
  29. &(String) => String :=
  30. &(input) rec(parse-blanks) =>
  31. switch { parse-blank input }:
  32. case Success (_, input):
  33. { parse-blanks input },
  34. case Failure _:
  35. input,
  36. end,
  37. &(input) =>
  38. { parse-t { parse-blanks input } }
  39. . { map &(t, input) => (t, { parse-blanks input }) };
  40. function map:[A,B,E]
  41. &(Parser[A,E], &(A) => B) => Parser[B,E]
  42. &(parse-a, a->b) => &(input) =>
  43. switch { parse-a input }:
  44. case Success (a, input):
  45. { Success ({ a->b a }, input) },
  46. case Failure err:
  47. { Failure err },
  48. end;
  49. function apply:[T,R,E]
  50. &(Parser[T,E], &(T) => Parser[R,E]) => Parser[R,E]
  51. &(parse, k) => &(input) =>
  52. switch { parse input }:
  53. case Success (value, input):
  54. let parse-next := { k(value) },
  55. { parse-next input },
  56. case Failure err:
  57. { Failure err },
  58. end;
  59. function choose:[T,E]
  60. &(List[Parser[T,E]]) => Parser[T,E]
  61. &(parsers) =>
  62. \ (first, rest) := assert-some { shift parsers },
  63. (rest reduce (first, &(parse-prev, parse-this) => &(input) =>
  64. switch { parse-prev input }:
  65. case Success parsed:
  66. { Success parsed },
  67. case Failure (prev-err, prev-remaining):
  68. switch { parse-this input }:
  69. case Success parsed:
  70. { Success parsed },
  71. case Failure (this-err, this-remaining):
  72. if (this-remaining.{length} < prev-remaining.{length}):
  73. { Failure (this-err, this-remaining) },
  74. else:
  75. { Failure (prev-err, prev-remaining) },
  76. end,
  77. end
  78. ));
  79. function repeat:[T,E]
  80. &(Parser[T,E]) => Parser[List[T],E]
  81. &(item) => &(input) =>
  82. let proceed:
  83. &(String, Seq[T]) => Result[(Seq[T],String),(E,String)] :=
  84. &(input, seq) rec(proceed) =>
  85. switch { item input }:
  86. case Success (value, input):
  87. { proceed (input, (value cons seq)) },
  88. case Failure _:
  89. { Success (seq, input) },
  90. end,
  91. { proceed (input, Nil) }
  92. . { map &(seq, input) => (seq.{List}.{reverse}, input) };
  93. function repeat:[T,E]
  94. & { item: Parser[T,E], sep: Parser[unit,E] } => Parser[List[T],E]
  95. & { item, sep } => &(input) =>
  96. let proceed:
  97. &(String, Seq[T]) => Result[(Seq[T],String),(E,String)] :=
  98. &(input, seq) rec(proceed) =>
  99. switch { item input }:
  100. case Success (value, input):
  101. let seq := (value cons seq),
  102. switch { sep input }:
  103. case Success (_, input):
  104. { proceed (input, seq) },
  105. case Failure _:
  106. { Success (seq, input) },
  107. end,
  108. case Failure err:
  109. if seq.{is-nil}:
  110. { Success (Nil, input) },
  111. else:
  112. { Failure err },
  113. end,
  114. { proceed (input, Nil) }
  115. . { map &(seq, input) => (seq.{List}.{reverse}, input) };