mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-23 14:20:22 +08:00
feat(parsely): Add stringUntil() parser
The counterpart of stringOf(), it reads characters until it matches its parameter.
This commit is contained in:
parent
5656d9d42f
commit
d46b043c5d
@ -1,6 +1,6 @@
|
|||||||
import { adapt_parser, VALUE } from './parser.js';
|
import { adapt_parser, VALUE } from './parser.js';
|
||||||
import { Discard, FirstMatch, Optional, Repeat, Sequence } from './parsers/combinators.js';
|
import { Discard, FirstMatch, Optional, Repeat, Sequence } from './parsers/combinators.js';
|
||||||
import { Fail, Literal, None, StringOf, Symbol } from './parsers/terminals.js';
|
import { Fail, Literal, None, StringOf, StringUntil, Symbol } from './parsers/terminals.js';
|
||||||
|
|
||||||
class ParserWithAction {
|
class ParserWithAction {
|
||||||
#parser;
|
#parser;
|
||||||
@ -89,6 +89,7 @@ export const standard_parsers = () => {
|
|||||||
repeat: Repeat,
|
repeat: Repeat,
|
||||||
sequence: Sequence,
|
sequence: Sequence,
|
||||||
stringOf: StringOf,
|
stringOf: StringOf,
|
||||||
|
stringUntil: StringUntil,
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,53 @@ export class StringOf extends Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses characters into a string, until it encounters the given character, unescaped.
|
||||||
|
* @param testOrCharacter End of the string. Either a character, or a function that takes a character,
|
||||||
|
* and returns whether it ends the string.
|
||||||
|
* @param escapeCharacter Character to use as the escape character. By default, is '\'.
|
||||||
|
*/
|
||||||
|
export class StringUntil extends Parser {
|
||||||
|
_create(testOrCharacter, { escapeCharacter = '\\' } = {}) {
|
||||||
|
if (typeof testOrCharacter === 'string') {
|
||||||
|
this.test = (c => c === testOrCharacter);
|
||||||
|
} else {
|
||||||
|
this.test = testOrCharacter;
|
||||||
|
}
|
||||||
|
this.escapeCharacter = escapeCharacter;
|
||||||
|
}
|
||||||
|
|
||||||
|
_parse(stream) {
|
||||||
|
const subStream = stream.fork();
|
||||||
|
let text = '';
|
||||||
|
let lastWasEscape = false;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
let { done, value } = subStream.look();
|
||||||
|
if ( done ) break;
|
||||||
|
if ( !lastWasEscape && this.test(value) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
subStream.next();
|
||||||
|
if (value === this.escapeCharacter) {
|
||||||
|
lastWasEscape = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lastWasEscape = false;
|
||||||
|
text += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastWasEscape)
|
||||||
|
return INVALID;
|
||||||
|
|
||||||
|
if (text.length === 0)
|
||||||
|
return UNRECOGNIZED;
|
||||||
|
|
||||||
|
stream.join(subStream);
|
||||||
|
return { status: VALUE, $: 'stringUntil', value: text };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an object defined by the symbol registry.
|
* Parses an object defined by the symbol registry.
|
||||||
* @param symbolName The name of the symbol to parse.
|
* @param symbolName The name of the symbol to parse.
|
||||||
|
Loading…
Reference in New Issue
Block a user