MergeWhitespacePStratumImpl.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. const decoder = new TextDecoder();
  20. export class MergeWhitespacePStratumImpl {
  21. static meta = {
  22. inputs: 'node',
  23. outputs: 'node',
  24. }
  25. constructor (tabWidth) {
  26. this.tabWidth = tabWidth ?? 1;
  27. this.line = 0;
  28. this.col = 0;
  29. }
  30. countChar (c) {
  31. if ( c === '\n' ) {
  32. this.line++;
  33. this.col = 0;
  34. return;
  35. }
  36. if ( c === '\t' ) {
  37. this.col += this.tabWidth;
  38. return;
  39. }
  40. if ( c === '\r' ) return;
  41. this.col++;
  42. }
  43. next (api) {
  44. const lexer = api.delegate;
  45. for ( ;; ) {
  46. const { value, done } = lexer.next();
  47. if ( done ) return { value, done };
  48. if ( value.$ === 'whitespace' ) {
  49. for ( const c of value.text ) {
  50. this.countChar(c);
  51. }
  52. return { value, done: false };
  53. // continue;
  54. }
  55. value.$cst = {
  56. ...(value.$cst ?? {}),
  57. line: this.line,
  58. col: this.col,
  59. };
  60. if ( value.hasOwnProperty('$source') ) {
  61. let source = value.$source;
  62. if ( source instanceof Uint8Array ) {
  63. source = decoder.decode(source);
  64. }
  65. for ( let c of source ) {
  66. this.countChar(c);
  67. }
  68. } else {
  69. console.warn('source missing; can\'t count position');
  70. }
  71. return { value, done: false };
  72. }
  73. }
  74. }