FirstRecognizedPStratumImpl.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /*
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Phoenix Shell.
  5. *
  6. * Phoenix Shell is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. import { AcceptParserUtil, ParseResult, Parser } from "../parse.js";
  20. export default class FirstRecognizedPStratumImpl {
  21. static meta = {
  22. description: `
  23. Implements a layer of top-down parsing by
  24. iterating over parsers for higher-level constructs
  25. and returning the first recognized value that was
  26. produced from lower-level constructs.
  27. `
  28. }
  29. constructor ({ parsers }) {
  30. this.parsers = parsers.map(AcceptParserUtil.adapt);
  31. this.valid = true;
  32. }
  33. next (api) {
  34. if ( ! this.valid ) return { done: true };
  35. const lexer = api.delegate;
  36. for ( const parser of this.parsers ) {
  37. {
  38. const { done } = lexer.look();
  39. if ( done ) return { done };
  40. }
  41. const subLexer = lexer.fork();
  42. const result = parser.parse(subLexer);
  43. if ( result.status === ParseResult.UNRECOGNIZED ) {
  44. continue;
  45. }
  46. if ( result.status === ParseResult.INVALID ) {
  47. return { done: true, value: result };
  48. }
  49. lexer.join(subLexer);
  50. return { done: false, value: result.value };
  51. }
  52. return { done: true, value: 'ran out of parsers' };
  53. }
  54. }