メインコンテンツまでスキップ

API Docs (old page)

Terrario v0.9.0

Basic APIs

T.language()

T.language(syntaxes: Record<string, (rules: Language) => Parser>): Language

We can define some syntax rules to build a language.
Each rule is lazy evaluated.

const lang = T.language({
root: rules => {
return T.alt([
rules.rule1,
rules.rule2,
]);
},

rule1: rules => {
return T.str('a');
},

rule2: rules => {
return T.str('b');
},
});

const result = lang.root.parse('a');
console.log(result);
// => { success: true, value: 'a', index: 1 }

parser.parse()

parser.parse(input: string, state?: any): Result

Parses with the parser.

const parser = T.str('a');

parser.parse('a');

// specify states
parser.parse('a', { flag: true, count: 0 });

T.str()

T.str(value: string): Parser

Generates a parser that consumes the specified string.

// [Equivalent PEG] "test"
const parser = T.str('test');

const result = parser.parse('test');
console.log(result);
// => { success: true, value: 'test', index: 4 }

With regular expression

T.str(pattern: Regexp): Parser

Generates a parser that consumes the specified regular expression.

// [Equivalent PEG] [a-z]
const parser = T.str(/[a-z]/);

const result = parser.parse('a');
console.log(result);
// => { success: true, value: 'a', index: 1 }

T.seq()

T.seq(parsers: Parser[], select?: boolean): Parser

Generates a parser that applies parsers in sequence.

// [Equivalent PEG] "a" "1"
const parser = T.seq([
T.str('a'),
T.str('1'),
]);

const result = parser.parse('a1');
console.log(result);
// => { success: true, value: [ 'a', '1' ], index: 2 }

Select a return value

You can also select a result to be returned from all of them:

// [Equivalent PEG] value0:"a" value1:"1" { return value1; }
const parser = T.seq([
T.str('a'),
T.str('1'),
], 1);

const result = parser.parse('a1');
console.log(result);
// => { success: true, value: '1', index: 2 }

T.alt()

T.alt(parsers: Parser[]): Parser

Generates a parser that tries to match one of the parsers.
The parsers are used in order of precedence.

// [Equivalent PEG] "a" / "1"
const parser = T.alt([
T.str('a'),
T.str('1'),
]);

let result;

result = parser.parse('a');
console.log(result);
// => { success: true, value: 'a', index: 1 }

result = parser.parse('1');
console.log(result);
// => { success: true, value: '1', index: 1 }

T.sep()

T.sep(item: Parser, separator: Parser, min: number): Parser

NOTE: This API has removed.

Generates a parser that splits a string and extracts multiple items.
The separator parser is used to split the string, and the item parser is used to consume each item.

The min argument specifies the minimum number of times it will be applied.
This argument must be greater than or equal to 1.

let parser, result;

// (1)
// [Equivalent PEG] head:"a" tail:("," @"a")* { return [head, ...tail]; }
parser = T.sep(T.str('a'), T.str(','), 1);

result = parser.parse('a');
console.log(result);
// => { success: true, value: [ 'a' ], index: 1 }

result = parser.parse('a,a');
console.log(result);
// => { success: true, value: [ 'a', 'a' ], index: 3 }

// (2)
// [Equivalent PEG]
// newline = "\r\n" / [\r\n]
// item = $(!newline .)+
// parser = head:item tail:(newline @item)* { return [head, ...tail]; }
parser = T.sep(T.seq([
T.notMatch(T.newline),
T.char
], 1).many(0).text(), T.newline, 1);

result = parser.parse('abc\r\nxyz');
console.log(result);
// => { success: true, value: [ 'abc', 'xyz' ], index: 8 }

T.match()

T.match(parser: Parser): Parser

Generates a new parser to continue if the match is successful. (Positive lookahead)
The generated parser does not consume input.

// [Equivalent PEG] &"a" "abc"
const parser = T.seq([
T.match(T.str('a')),
T.str('abc'),
]);
const result = parser.parse('abc');
console.log(result);
// => { success: true, value: [ 'a', 'abc' ], index: 3 }

T.notMatch()

T.notMatch(parser: Parser): Parser

Generates a new parser to continue if the match fails. (Negative lookahead)
The generated parser does not consume input.

// [Equivalent PEG] !"x" "abc"
const parser = T.seq([
T.notMatch(T.str('x')),
T.str('abc'),
]);
const result = parser.parse('abc');
console.log(result);
// => { success: true, value: [ null, 'abc' ], index: 3 }

parser.map()

parser.map(fn: (value) => any): Parser

Maps the parsed results using the specified function.

// [Equivalent PEG] value0:"a" value1:"b" value2:"c" { return [value0, value2]; }
const parser = T.seq([
T.str('a'),
T.str('b'),
T.str('c'),
]).map(value => {
return [value[0], value[2]];
});

const result = parser.parse('abc');
console.log(result);
// => { success: true, value: [ 'a', 'c' ], index: 3 }

parser.text()

parser.text(): Parser

The parser maps the consumed portion as a string.

// [Equivalent PEG] "a" "b" "c" { return text(); }
const parser = T.seq([
T.str('a'),
T.str('b'),
T.str('c'),
]).text();

const result = parser.parse('abc');
console.log(result);
// => { success: true, value: 'abc', index: 3 }

parser.many()

parser.many(min?: number, max?: number): Parser
parser.many(opts: { min?: number, max?: number, notMatch?: Parser }): Parser

Repeatedly applies the parser.
The argument min specifies the minimum number of times it will be applied.

Matches 0 or more items:

// [Equivalent PEG] "abc"*
const parser = T.str('abc').many(0);

let result;

result = parser.parse('');
console.log(result);
// => { success: true, value: [], index: 0 }

result = parser.parse('abc');
console.log(result);
// => { success: true, value: [ 'abc' ], index: 3 }

Matches 1 or more items:

// [Equivalent PEG] "abc"+
const parser = T.str('abc').many(1);

let result;

result = parser.parse('abc');
console.log(result);
// => { success: true, value: [ 'abc' ], index: 3 }

result = parser.parse('abcabc');
console.log(result);
// => { success: true, value: [ 'abc', 'abc' ], index: 6 }

With termination condition

The parser.many() can have a termination condition.

The following example uses many to match strings up to ")". The terminating condition ")" is not consumed.

// [Equivalent PEG] "(" (!")" @.)+ ")"
const parser = T.seq([
T.str('('),
T.char.many({ min: 1, notMatch: T.str(')') }),
T.str(')'),
]);

const result = parser.parse('(abc)');
console.log(result);
// => { success: true, value: [ '(', [ 'a', 'b', 'c' ], ')' ], index: 5 }

parser.option()

parser.option(): Parser

Generates a new parser that returns null even if the match fails.
Make the parser consumption optional.

// [Equivalent PEG] "a" "b"?
const parser = T.seq([
T.str('a'),
T.str('b').option(),
]);

let result;

result = parser.parse('ab');
console.log(result);
// => { success: true, value: [ 'a', 'b' ], index: 2 }

result = parser.parse('a');
console.log(result);
// => { success: true, value: [ 'a', null ], index: 1 }

T.newline

T.newline: Parser

Matches \r\n or \r or \n

T.sof

T.sof: Parser

Matches start of input string.

T.eof

T.eof: Parser

Matches end of input string.

// [Equivalent PEG] "a" !.
const parser = T.seq([
T.str('a'),
T.eof,
]);

const result = parser.parse('a');
console.log(result);
// => { success: true, value: [ 'a', null ], index: 1 }

T.char

T.char: Parser

A parser that consumes any single character.

// [Equivalent PEG] .
const parser = T.char;

const result = parser.parse('a');
console.log(result);
// => { success: true, value: 'a', index: 1 }

T.lineBegin

T.lineBegin: Parser
//TODO

T.lineEnd

T.lineEnd: Parser
//TODO

Parsing result

type Success = {
success: true;
index: number;
value: any;
};
type Failure = {
success: false;
index: number;
};
type Result = Success | Failure;

Result structure is unstable yet.

Control with states

parser.state()

parser.state(key: string, value: (state: any) => any): Parser

parser.state() creates a parser that sets a value to a specified key in a state object.
When this parser finishes executing, the contents of the state object are restored.

T.cond()

T.cond(predicate: (state: any) => boolean): Parser

Conditional branching can be performed using the state.

const parser = T.seq([
T.cond(state => state.enabled),
T.char,
]).state('enabled', () => true);

const result = parser.parse('a', { enabled: false });
console.log(result);
// => { success: true, value: [ null, 'a' ], index: 1 }

Find pattern APIs

parser.find()

parser.find(input: string, state?: any): { index: number, input: string, result: Result } | undefined

Find the matches to the pattern, starting from the front

parser.findAll()

parser.findAll(input: string, state?: any): { index: number, input: string, result: Result }[]

Custom parsers

T.parser()

T.parser(handler: (input: string, index: number, children: Parser[], state: any) => Result, children?: Parser[], name?: string): Parser

Makes a new custom parser.

const parser = T.parser((input, index, children, state) => {
if (index >= input.length) {
return T.failure(index);
}
return T.success(index, 'result value');
});

T.success()

T.success(index: number, value: any): Success

Generates a result indicating the success of a parser.

T.failure()

T.failure(index: number): Failure

Generates a result indicating the failure of a parser.

parser.exec()

parser.exec(input: string, state?: any, offset?: number): Result

Perform other parsers within the custom parser.

Minor APIs

T.lazy()

T.lazy(fn: () => Parser, name?: string): Parser

Generates a new parser that is lazy-evaluated.
Normally there is no need to use this API. Use T.language() instead.

T.succeeded()

T.succeeded(value: any): Parser

Generates a parser that succeeds with the specified value.

const parser = T.succeeded('abc');
const result = parser.parse('');
console.log(result);
// => { success: true, value: "abc", index: 0 }

T.cr

T.cr: Parser

Matches \r (CR)

T.lf

T.lf: Parser

Matches \n (LF)

T.crlf

T.crlf: Parser

Matches \r\n (CR + LF)