good-enough-parser
Advanced tools
Comparing version 1.1.18 to 1.1.19
@@ -10,3 +10,3 @@ import type { Cursor } from '../parser/types'; | ||
parse(input: string): Cursor; | ||
query<Ctx>(input: string | Cursor, q: QueryBuilder<Ctx>, context: Ctx): Ctx | undefined; | ||
query<Ctx>(input: string | Cursor, q: QueryBuilder<Ctx>, context: Ctx): Ctx | null; | ||
} | ||
@@ -13,0 +13,0 @@ declare const languagePresets: { |
@@ -42,3 +42,3 @@ "use strict"; | ||
const result = checkpoint === null || checkpoint === void 0 ? void 0 : checkpoint.context; | ||
return result && (0, clone_1.clone)(result); | ||
return result ? (0, clone_1.clone)(result) : null; | ||
} | ||
@@ -45,0 +45,0 @@ } |
@@ -68,12 +68,41 @@ "use strict"; | ||
exports.configureLexerRules = configureLexerRules; | ||
function isVarToken(key) { | ||
return typeof key === 'string' && /^str\$\d+\$tpl\$\d+\$token$/.test(key); | ||
} | ||
function getVarEndToken({ type, value, offset, line, col, lineBreaks, }) { | ||
return { | ||
type: type === null || type === void 0 ? void 0 : type.replace(/\$[^$]+$/, '$end'), | ||
value: '', | ||
text: '', | ||
offset: offset + value.length, | ||
line: line + lineBreaks, | ||
col: col + value.length, | ||
lineBreaks: 0, | ||
}; | ||
} | ||
function getSubLexers(states) { | ||
const result = {}; | ||
for (const [key, rules] of Object.entries(states)) { | ||
if (isVarToken(key)) { | ||
result[key] = (0, moo_1.compile)(rules); | ||
} | ||
} | ||
return result; | ||
} | ||
function createLexer(options) { | ||
const rules = configureLexerRules(options); | ||
const mooLexer = (0, moo_1.states)(rules); | ||
const subLexers = getSubLexers(rules); | ||
const mainLexer = (0, moo_1.states)(rules); | ||
let subLexer; | ||
let subLexerToken; | ||
const result = { | ||
reset(input) { | ||
Object.values(subLexers).forEach((subLexer) => subLexer.reset()); | ||
subLexer = undefined; | ||
subLexerToken = undefined; | ||
if (typeof input === 'undefined' || input === null) { | ||
mooLexer.reset(); | ||
mainLexer.reset(); | ||
} | ||
else { | ||
mooLexer.reset(input); | ||
mainLexer.reset(input); | ||
} | ||
@@ -83,12 +112,40 @@ return result; | ||
[Symbol.iterator]() { | ||
const mooIter = mooLexer[Symbol.iterator](); | ||
const next = () => { | ||
const mooLexer = subLexer !== null && subLexer !== void 0 ? subLexer : mainLexer; | ||
const mooIter = mooLexer[Symbol.iterator](); | ||
const nextElem = mooIter.next(); | ||
if (nextElem.done) { | ||
return { done: true, value: null }; | ||
if (subLexer && subLexerToken) { | ||
const subLexerType = subLexerToken.type; | ||
mooLexer.reset(); | ||
if (isVarToken(subLexerType)) { | ||
const x = getVarEndToken(subLexerToken); | ||
const value = (0, token_1.coerceToken)(x); | ||
subLexer = undefined; | ||
subLexerToken = undefined; | ||
return { done: false, value }; | ||
} | ||
else { | ||
subLexer = undefined; | ||
subLexerToken = undefined; | ||
return next(); | ||
} | ||
} | ||
else { | ||
return { done: true, value: null }; | ||
} | ||
} | ||
else { | ||
const value = (0, token_1.coerceToken)(nextElem.value); | ||
return { done: false, value }; | ||
const mooToken = nextElem.value; | ||
if (!subLexer) { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const mooTokenType = mooToken.type; | ||
subLexer = subLexers[mooTokenType]; | ||
if (subLexer) { | ||
subLexerToken = mooToken; | ||
subLexer.reset(mooToken.value); | ||
return next(); | ||
} | ||
} | ||
const value = (0, token_1.coerceToken)(mooToken, subLexerToken); | ||
return { done: false, value }; | ||
}; | ||
@@ -95,0 +152,0 @@ return { next }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.configStrings = void 0; | ||
const clone_1 = require("../util/clone"); | ||
const regex_1 = require("../util/regex"); | ||
const bracket_1 = require("./bracket"); | ||
const rules_1 = require("./rules"); | ||
function copyStateDefinition(state) { | ||
const result = { ...state }; | ||
const result = (0, clone_1.clone)(state); | ||
Object.entries(result).forEach(([key, val]) => { | ||
result[key] = { ...val }; | ||
result[key] = (0, clone_1.clone)(val); | ||
}); | ||
@@ -32,3 +34,3 @@ return result; | ||
counterpartRule.push = '$'; | ||
rootState[counterpartKey] = { ...counterpartRule }; | ||
rootState[counterpartKey] = (0, clone_1.clone)(counterpartRule); | ||
rootState[bracketKey] = { ...bracketRule, pop: 1 }; | ||
@@ -47,51 +49,2 @@ } | ||
} | ||
function varTplState($, strState, { operators = [], symbols }) { | ||
const result = { ...strState }; | ||
let strStateName = null; | ||
Object.entries(result).forEach(([key, val]) => { | ||
if (val.t !== 'fallback') { | ||
const rule = { ...val }; | ||
if (rule.push) { | ||
rule.next = rule.push; | ||
delete rule.push; | ||
} | ||
result[key] = rule; | ||
} | ||
else { | ||
delete result[key]; | ||
strStateName = key; | ||
} | ||
}); | ||
const symbolRule = symbols | ||
? { t: 'regex', type: 'symbol', match: symbols, chunk: null } | ||
: $.symbol; | ||
if (!symbolRule) { | ||
throw new Error(`String definition isn't found for template definition`); | ||
} | ||
result.symbol = symbolRule; | ||
for (const op of operators) { | ||
const opEntry = Object.entries($).find(([key, rule]) => key.startsWith('op$') && rule.t === 'string' && rule.match === op); | ||
if (opEntry) { | ||
const [opKey, opRule] = opEntry; | ||
result[opKey] = { ...opRule }; | ||
} | ||
else { | ||
throw new Error(`Operator is not found: ${op}`); | ||
} | ||
} | ||
if (strStateName) { | ||
result[strStateName] = { | ||
t: 'regex', | ||
type: strStateName, | ||
match: /./, | ||
chunk: null, | ||
lineBreaks: true, | ||
pop: 1, | ||
}; | ||
} | ||
else { | ||
throw new Error(`Fallback value is missing for variable-style template`); | ||
} | ||
return result; | ||
} | ||
function configStrings(states, opts) { | ||
@@ -104,3 +57,3 @@ if (!opts.length) { | ||
const exprTplPreStates = []; | ||
const varTplPreStates = []; | ||
const tplStates = {}; | ||
opts.forEach((strOpt, strIdx) => { | ||
@@ -124,8 +77,9 @@ const { startsWith: strStart, endsWith: strEnd = strStart, templates: tplOpts, } = strOpt; | ||
tplOpts === null || tplOpts === void 0 ? void 0 : tplOpts.forEach((tplOpt, tplIdx) => { | ||
var _a; | ||
const { startsWith: tplStart } = tplOpt; | ||
const tplToken = `${strToken}$tpl$${tplIdx}`; | ||
const tplStartToken = `${tplToken}$start`; | ||
const tplEndToken = `${tplToken}$end`; | ||
const tplStateName = `${tplToken}$state`; | ||
if (tplOpt.type === 'expr') { | ||
const tplToken = `${strToken}$tpl$${tplIdx}`; | ||
const tplStartToken = `${tplToken}$start`; | ||
const tplEndToken = `${tplToken}$end`; | ||
const tplStateName = `${tplToken}$state`; | ||
strState[tplStartToken] = { | ||
@@ -142,3 +96,38 @@ t: 'string', | ||
if (tplOpt.type === 'var') { | ||
strState[tplStartToken] = { | ||
const tplToken = `${strToken}$tpl$${tplIdx}`; | ||
const tplStartToken = `${tplToken}$start`; | ||
const tplTokenName = `${tplToken}$token`; | ||
const { operators = [], symbols } = tplOpt; | ||
let symRegex = symbols; | ||
if (!symRegex && ((_a = $.symbol) === null || _a === void 0 ? void 0 : _a.t) === 'regex') { | ||
symRegex = $.symbol.match; | ||
} | ||
if (!symRegex) { | ||
throw new Error(`String definition isn't found for template definition`); | ||
} | ||
const start = (0, regex_1.escape)(tplStart); | ||
const symSource = symRegex.source; | ||
let varTplSource = `${start}${symSource}`; | ||
const opRules = {}; | ||
if (operators.length) { | ||
const opSource = `(?:${operators.map(regex_1.escape).join('|')})`; | ||
varTplSource += `(?:${opSource}${symSource})*`; | ||
operators.forEach((match, idx) => { | ||
const type = `op$${idx}`; | ||
opRules[type] = { | ||
t: 'string', | ||
type, | ||
match, | ||
chunk: match, | ||
}; | ||
}); | ||
} | ||
const match = new RegExp(varTplSource); | ||
strState[tplTokenName] = { | ||
t: 'regex', | ||
type: tplTokenName, | ||
match, | ||
chunk: tplStart, | ||
}; | ||
const tplStartRule = { | ||
t: 'string', | ||
@@ -148,13 +137,14 @@ type: tplStartToken, | ||
chunk: tplStart, | ||
push: tplStateName, | ||
}; | ||
const { operators = [], symbols } = tplOpt; | ||
varTplPreStates.push({ | ||
symbols, | ||
operators, | ||
tplStateName, | ||
tplStart, | ||
strEnd, | ||
strStateName, | ||
}); | ||
const symbolRule = { | ||
t: 'regex', | ||
type: 'symbol', | ||
match: symRegex, | ||
chunk: null, | ||
}; | ||
tplStates[tplTokenName] = { | ||
[tplStartToken]: tplStartRule, | ||
symbol: symbolRule, | ||
...opRules, | ||
}; | ||
} | ||
@@ -171,3 +161,2 @@ }); | ||
}); | ||
const tplStates = {}; | ||
for (const exprTplStateInput of exprTplPreStates) { | ||
@@ -179,9 +168,2 @@ const { tplStateName } = exprTplStateInput; | ||
} | ||
for (const varTplStateInput of varTplPreStates) { | ||
const { tplStateName, strStateName } = varTplStateInput; | ||
const strState = strStates[strStateName]; | ||
if (strState) { | ||
tplStates[tplStateName] = varTplState($, strState, varTplStateInput); | ||
} | ||
} | ||
return { $, ...strStates, ...tplStates }; | ||
@@ -188,0 +170,0 @@ } |
import type { Token as MooToken } from 'moo'; | ||
import type { Token } from './types'; | ||
export declare function coerceToken({ type, value, offset, line, col, lineBreaks, }: MooToken): Token; | ||
export declare function coerceToken({ type, value, offset, line, col, lineBreaks }: MooToken, parent?: MooToken): Token; | ||
//# sourceMappingURL=token.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.coerceToken = void 0; | ||
function coerceToken({ type, value, offset, line, col, lineBreaks, }) { | ||
const base = { value, offset, line, col, lineBreaks }; | ||
function coerceToken({ type, value, offset, line, col, lineBreaks }, parent) { | ||
const base = parent | ||
? { | ||
value, | ||
offset: offset + parent.offset, | ||
line: line + parent.line - 1, | ||
col: col + parent.col - 1, | ||
lineBreaks: lineBreaks + parent.lineBreaks, | ||
} | ||
: { value, offset, line, col, lineBreaks }; | ||
if (typeof type === 'string') { | ||
const [p1, , p3, , p5] = type.split('$'); | ||
const [p1, , p2, , p3] = type.split('$'); | ||
if (p1 === 'newline') { | ||
@@ -15,6 +23,6 @@ return { type: 'newline', ...base }; | ||
else if (p1 === 'bracket') { | ||
if (p3 === 'left') { | ||
if (p2 === 'left') { | ||
return { type: 'bracket-left', ...base }; | ||
} | ||
else if (p3 === 'right') { | ||
else if (p2 === 'right') { | ||
return { type: 'bracket-right', ...base }; | ||
@@ -30,16 +38,16 @@ } | ||
else if (p1 === 'str') { | ||
if (p3 === 'start') { | ||
if (p2 === 'start') { | ||
return { type: 'string-start', ...base }; | ||
} | ||
else if (p3 === 'value') { | ||
else if (p2 === 'value') { | ||
return { type: 'string-value', ...base }; | ||
} | ||
else if (p3 === 'end') { | ||
else if (p2 === 'end') { | ||
return { type: 'string-end', ...base }; | ||
} | ||
else if (p3 === 'tpl') { | ||
if (p5 === 'start') { | ||
else if (p2 === 'tpl') { | ||
if (p3 === 'start') { | ||
return { type: 'template-start', ...base }; | ||
} | ||
else if (p5 === 'end') { | ||
else if (p3 === 'end') { | ||
return { type: 'template-end', ...base }; | ||
@@ -46,0 +54,0 @@ } |
@@ -9,2 +9,4 @@ import type { Cursor } from '../../parser/types'; | ||
readonly type: TreeMatcherType | null; | ||
readonly startsWithValue: string | null; | ||
readonly endsWithValue: string | null; | ||
readonly matcher: Matcher<Ctx> | null; | ||
@@ -11,0 +13,0 @@ readonly maxDepth: number; |
@@ -9,3 +9,3 @@ "use strict"; | ||
constructor(config) { | ||
var _a; | ||
var _a, _b, _c; | ||
super(); | ||
@@ -15,2 +15,4 @@ this.walkDepth = 0; | ||
this.type = (_a = config.type) !== null && _a !== void 0 ? _a : null; | ||
this.startsWithValue = (_b = config.startsWith) !== null && _b !== void 0 ? _b : null; | ||
this.endsWithValue = (_c = config.endsWith) !== null && _c !== void 0 ? _c : null; | ||
this.matcher = config.matcher; | ||
@@ -88,2 +90,13 @@ this.maxDepth = | ||
} | ||
if (this.type === 'wrapped-tree') { | ||
const currentTree = rootNode; | ||
if (this.startsWithValue && | ||
currentTree.startsWith.value !== this.startsWithValue) { | ||
return null; | ||
} | ||
if (this.endsWithValue && | ||
currentTree.endsWith.value !== this.endsWithValue) { | ||
return null; | ||
} | ||
} | ||
let context = checkpoint.context; | ||
@@ -90,0 +103,0 @@ context = this.preHandler(context, rootNode); |
@@ -40,2 +40,4 @@ import type { CommentToken, MinorToken, NumberToken, OperatorToken, SymbolToken } from '../lexer/types'; | ||
type?: TreeMatcherType; | ||
startsWith?: string | null; | ||
endsWith?: string | null; | ||
maxDepth?: number | null; | ||
@@ -42,0 +44,0 @@ maxMatches?: number | null; |
@@ -10,3 +10,3 @@ import type { Cursor } from '../parser/types'; | ||
parse(input: string): Cursor; | ||
query<Ctx>(input: string | Cursor, q: QueryBuilder<Ctx>, context: Ctx): Ctx | undefined; | ||
query<Ctx>(input: string | Cursor, q: QueryBuilder<Ctx>, context: Ctx): Ctx | null; | ||
} | ||
@@ -13,0 +13,0 @@ declare const languagePresets: { |
@@ -25,3 +25,3 @@ import { createLexer } from '../lexer'; | ||
const result = checkpoint === null || checkpoint === void 0 ? void 0 : checkpoint.context; | ||
return result && clone(result); | ||
return result ? clone(result) : null; | ||
} | ||
@@ -28,0 +28,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { states as mooStates } from 'moo'; | ||
import { compile as mooCompile, states as mooStates, } from 'moo'; | ||
import { configBrackets } from './bracket'; | ||
@@ -50,12 +50,41 @@ import { configComments } from './comment'; | ||
} | ||
function isVarToken(key) { | ||
return typeof key === 'string' && /^str\$\d+\$tpl\$\d+\$token$/.test(key); | ||
} | ||
function getVarEndToken({ type, value, offset, line, col, lineBreaks, }) { | ||
return { | ||
type: type === null || type === void 0 ? void 0 : type.replace(/\$[^$]+$/, '$end'), | ||
value: '', | ||
text: '', | ||
offset: offset + value.length, | ||
line: line + lineBreaks, | ||
col: col + value.length, | ||
lineBreaks: 0, | ||
}; | ||
} | ||
function getSubLexers(states) { | ||
const result = {}; | ||
for (const [key, rules] of Object.entries(states)) { | ||
if (isVarToken(key)) { | ||
result[key] = mooCompile(rules); | ||
} | ||
} | ||
return result; | ||
} | ||
export function createLexer(options) { | ||
const rules = configureLexerRules(options); | ||
const mooLexer = mooStates(rules); | ||
const subLexers = getSubLexers(rules); | ||
const mainLexer = mooStates(rules); | ||
let subLexer; | ||
let subLexerToken; | ||
const result = { | ||
reset(input) { | ||
Object.values(subLexers).forEach((subLexer) => subLexer.reset()); | ||
subLexer = undefined; | ||
subLexerToken = undefined; | ||
if (typeof input === 'undefined' || input === null) { | ||
mooLexer.reset(); | ||
mainLexer.reset(); | ||
} | ||
else { | ||
mooLexer.reset(input); | ||
mainLexer.reset(input); | ||
} | ||
@@ -65,12 +94,40 @@ return result; | ||
[Symbol.iterator]() { | ||
const mooIter = mooLexer[Symbol.iterator](); | ||
const next = () => { | ||
const mooLexer = subLexer !== null && subLexer !== void 0 ? subLexer : mainLexer; | ||
const mooIter = mooLexer[Symbol.iterator](); | ||
const nextElem = mooIter.next(); | ||
if (nextElem.done) { | ||
return { done: true, value: null }; | ||
if (subLexer && subLexerToken) { | ||
const subLexerType = subLexerToken.type; | ||
mooLexer.reset(); | ||
if (isVarToken(subLexerType)) { | ||
const x = getVarEndToken(subLexerToken); | ||
const value = coerceToken(x); | ||
subLexer = undefined; | ||
subLexerToken = undefined; | ||
return { done: false, value }; | ||
} | ||
else { | ||
subLexer = undefined; | ||
subLexerToken = undefined; | ||
return next(); | ||
} | ||
} | ||
else { | ||
return { done: true, value: null }; | ||
} | ||
} | ||
else { | ||
const value = coerceToken(nextElem.value); | ||
return { done: false, value }; | ||
const mooToken = nextElem.value; | ||
if (!subLexer) { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const mooTokenType = mooToken.type; | ||
subLexer = subLexers[mooTokenType]; | ||
if (subLexer) { | ||
subLexerToken = mooToken; | ||
subLexer.reset(mooToken.value); | ||
return next(); | ||
} | ||
} | ||
const value = coerceToken(mooToken, subLexerToken); | ||
return { done: false, value }; | ||
}; | ||
@@ -77,0 +134,0 @@ return { next }; |
@@ -0,7 +1,9 @@ | ||
import { clone } from '../util/clone'; | ||
import { escape } from '../util/regex'; | ||
import { getCounterpartBracketKey, isBracketKey, isRightKey } from './bracket'; | ||
import { fallbackRule } from './rules'; | ||
function copyStateDefinition(state) { | ||
const result = { ...state }; | ||
const result = clone(state); | ||
Object.entries(result).forEach(([key, val]) => { | ||
result[key] = { ...val }; | ||
result[key] = clone(val); | ||
}); | ||
@@ -29,3 +31,3 @@ return result; | ||
counterpartRule.push = '$'; | ||
rootState[counterpartKey] = { ...counterpartRule }; | ||
rootState[counterpartKey] = clone(counterpartRule); | ||
rootState[bracketKey] = { ...bracketRule, pop: 1 }; | ||
@@ -44,51 +46,2 @@ } | ||
} | ||
function varTplState($, strState, { operators = [], symbols }) { | ||
const result = { ...strState }; | ||
let strStateName = null; | ||
Object.entries(result).forEach(([key, val]) => { | ||
if (val.t !== 'fallback') { | ||
const rule = { ...val }; | ||
if (rule.push) { | ||
rule.next = rule.push; | ||
delete rule.push; | ||
} | ||
result[key] = rule; | ||
} | ||
else { | ||
delete result[key]; | ||
strStateName = key; | ||
} | ||
}); | ||
const symbolRule = symbols | ||
? { t: 'regex', type: 'symbol', match: symbols, chunk: null } | ||
: $.symbol; | ||
if (!symbolRule) { | ||
throw new Error(`String definition isn't found for template definition`); | ||
} | ||
result.symbol = symbolRule; | ||
for (const op of operators) { | ||
const opEntry = Object.entries($).find(([key, rule]) => key.startsWith('op$') && rule.t === 'string' && rule.match === op); | ||
if (opEntry) { | ||
const [opKey, opRule] = opEntry; | ||
result[opKey] = { ...opRule }; | ||
} | ||
else { | ||
throw new Error(`Operator is not found: ${op}`); | ||
} | ||
} | ||
if (strStateName) { | ||
result[strStateName] = { | ||
t: 'regex', | ||
type: strStateName, | ||
match: /./, | ||
chunk: null, | ||
lineBreaks: true, | ||
pop: 1, | ||
}; | ||
} | ||
else { | ||
throw new Error(`Fallback value is missing for variable-style template`); | ||
} | ||
return result; | ||
} | ||
export function configStrings(states, opts) { | ||
@@ -101,3 +54,3 @@ if (!opts.length) { | ||
const exprTplPreStates = []; | ||
const varTplPreStates = []; | ||
const tplStates = {}; | ||
opts.forEach((strOpt, strIdx) => { | ||
@@ -121,8 +74,9 @@ const { startsWith: strStart, endsWith: strEnd = strStart, templates: tplOpts, } = strOpt; | ||
tplOpts === null || tplOpts === void 0 ? void 0 : tplOpts.forEach((tplOpt, tplIdx) => { | ||
var _a; | ||
const { startsWith: tplStart } = tplOpt; | ||
const tplToken = `${strToken}$tpl$${tplIdx}`; | ||
const tplStartToken = `${tplToken}$start`; | ||
const tplEndToken = `${tplToken}$end`; | ||
const tplStateName = `${tplToken}$state`; | ||
if (tplOpt.type === 'expr') { | ||
const tplToken = `${strToken}$tpl$${tplIdx}`; | ||
const tplStartToken = `${tplToken}$start`; | ||
const tplEndToken = `${tplToken}$end`; | ||
const tplStateName = `${tplToken}$state`; | ||
strState[tplStartToken] = { | ||
@@ -139,3 +93,38 @@ t: 'string', | ||
if (tplOpt.type === 'var') { | ||
strState[tplStartToken] = { | ||
const tplToken = `${strToken}$tpl$${tplIdx}`; | ||
const tplStartToken = `${tplToken}$start`; | ||
const tplTokenName = `${tplToken}$token`; | ||
const { operators = [], symbols } = tplOpt; | ||
let symRegex = symbols; | ||
if (!symRegex && ((_a = $.symbol) === null || _a === void 0 ? void 0 : _a.t) === 'regex') { | ||
symRegex = $.symbol.match; | ||
} | ||
if (!symRegex) { | ||
throw new Error(`String definition isn't found for template definition`); | ||
} | ||
const start = escape(tplStart); | ||
const symSource = symRegex.source; | ||
let varTplSource = `${start}${symSource}`; | ||
const opRules = {}; | ||
if (operators.length) { | ||
const opSource = `(?:${operators.map(escape).join('|')})`; | ||
varTplSource += `(?:${opSource}${symSource})*`; | ||
operators.forEach((match, idx) => { | ||
const type = `op$${idx}`; | ||
opRules[type] = { | ||
t: 'string', | ||
type, | ||
match, | ||
chunk: match, | ||
}; | ||
}); | ||
} | ||
const match = new RegExp(varTplSource); | ||
strState[tplTokenName] = { | ||
t: 'regex', | ||
type: tplTokenName, | ||
match, | ||
chunk: tplStart, | ||
}; | ||
const tplStartRule = { | ||
t: 'string', | ||
@@ -145,13 +134,14 @@ type: tplStartToken, | ||
chunk: tplStart, | ||
push: tplStateName, | ||
}; | ||
const { operators = [], symbols } = tplOpt; | ||
varTplPreStates.push({ | ||
symbols, | ||
operators, | ||
tplStateName, | ||
tplStart, | ||
strEnd, | ||
strStateName, | ||
}); | ||
const symbolRule = { | ||
t: 'regex', | ||
type: 'symbol', | ||
match: symRegex, | ||
chunk: null, | ||
}; | ||
tplStates[tplTokenName] = { | ||
[tplStartToken]: tplStartRule, | ||
symbol: symbolRule, | ||
...opRules, | ||
}; | ||
} | ||
@@ -168,3 +158,2 @@ }); | ||
}); | ||
const tplStates = {}; | ||
for (const exprTplStateInput of exprTplPreStates) { | ||
@@ -176,11 +165,4 @@ const { tplStateName } = exprTplStateInput; | ||
} | ||
for (const varTplStateInput of varTplPreStates) { | ||
const { tplStateName, strStateName } = varTplStateInput; | ||
const strState = strStates[strStateName]; | ||
if (strState) { | ||
tplStates[tplStateName] = varTplState($, strState, varTplStateInput); | ||
} | ||
} | ||
return { $, ...strStates, ...tplStates }; | ||
} | ||
//# sourceMappingURL=string.js.map |
import type { Token as MooToken } from 'moo'; | ||
import type { Token } from './types'; | ||
export declare function coerceToken({ type, value, offset, line, col, lineBreaks, }: MooToken): Token; | ||
export declare function coerceToken({ type, value, offset, line, col, lineBreaks }: MooToken, parent?: MooToken): Token; | ||
//# sourceMappingURL=token.d.ts.map |
@@ -1,5 +0,13 @@ | ||
export function coerceToken({ type, value, offset, line, col, lineBreaks, }) { | ||
const base = { value, offset, line, col, lineBreaks }; | ||
export function coerceToken({ type, value, offset, line, col, lineBreaks }, parent) { | ||
const base = parent | ||
? { | ||
value, | ||
offset: offset + parent.offset, | ||
line: line + parent.line - 1, | ||
col: col + parent.col - 1, | ||
lineBreaks: lineBreaks + parent.lineBreaks, | ||
} | ||
: { value, offset, line, col, lineBreaks }; | ||
if (typeof type === 'string') { | ||
const [p1, , p3, , p5] = type.split('$'); | ||
const [p1, , p2, , p3] = type.split('$'); | ||
if (p1 === 'newline') { | ||
@@ -12,6 +20,6 @@ return { type: 'newline', ...base }; | ||
else if (p1 === 'bracket') { | ||
if (p3 === 'left') { | ||
if (p2 === 'left') { | ||
return { type: 'bracket-left', ...base }; | ||
} | ||
else if (p3 === 'right') { | ||
else if (p2 === 'right') { | ||
return { type: 'bracket-right', ...base }; | ||
@@ -27,16 +35,16 @@ } | ||
else if (p1 === 'str') { | ||
if (p3 === 'start') { | ||
if (p2 === 'start') { | ||
return { type: 'string-start', ...base }; | ||
} | ||
else if (p3 === 'value') { | ||
else if (p2 === 'value') { | ||
return { type: 'string-value', ...base }; | ||
} | ||
else if (p3 === 'end') { | ||
else if (p2 === 'end') { | ||
return { type: 'string-end', ...base }; | ||
} | ||
else if (p3 === 'tpl') { | ||
if (p5 === 'start') { | ||
else if (p2 === 'tpl') { | ||
if (p3 === 'start') { | ||
return { type: 'template-start', ...base }; | ||
} | ||
else if (p5 === 'end') { | ||
else if (p3 === 'end') { | ||
return { type: 'template-end', ...base }; | ||
@@ -43,0 +51,0 @@ } |
@@ -9,2 +9,4 @@ import type { Cursor } from '../../parser/types'; | ||
readonly type: TreeMatcherType | null; | ||
readonly startsWithValue: string | null; | ||
readonly endsWithValue: string | null; | ||
readonly matcher: Matcher<Ctx> | null; | ||
@@ -11,0 +13,0 @@ readonly maxDepth: number; |
@@ -6,3 +6,3 @@ import { isTree } from '../../parser'; | ||
constructor(config) { | ||
var _a; | ||
var _a, _b, _c; | ||
super(); | ||
@@ -12,2 +12,4 @@ this.walkDepth = 0; | ||
this.type = (_a = config.type) !== null && _a !== void 0 ? _a : null; | ||
this.startsWithValue = (_b = config.startsWith) !== null && _b !== void 0 ? _b : null; | ||
this.endsWithValue = (_c = config.endsWith) !== null && _c !== void 0 ? _c : null; | ||
this.matcher = config.matcher; | ||
@@ -85,2 +87,13 @@ this.maxDepth = | ||
} | ||
if (this.type === 'wrapped-tree') { | ||
const currentTree = rootNode; | ||
if (this.startsWithValue && | ||
currentTree.startsWith.value !== this.startsWithValue) { | ||
return null; | ||
} | ||
if (this.endsWithValue && | ||
currentTree.endsWith.value !== this.endsWithValue) { | ||
return null; | ||
} | ||
} | ||
let context = checkpoint.context; | ||
@@ -87,0 +100,0 @@ context = this.preHandler(context, rootNode); |
@@ -40,2 +40,4 @@ import type { CommentToken, MinorToken, NumberToken, OperatorToken, SymbolToken } from '../lexer/types'; | ||
type?: TreeMatcherType; | ||
startsWith?: string | null; | ||
endsWith?: string | null; | ||
maxDepth?: number | null; | ||
@@ -42,0 +44,0 @@ maxMatches?: number | null; |
{ | ||
"name": "good-enough-parser", | ||
"description": "Parse and query computer programs source code", | ||
"version": "1.1.18", | ||
"version": "1.1.19", | ||
"repository": "https://github.com/zharinov/good-enough-parser.git", | ||
@@ -45,7 +45,7 @@ "author": "Sergei Zharinov", | ||
"@renovate/eslint-plugin": "https://github.com/renovatebot/eslint-plugin#v0.0.4", | ||
"@types/jest": "28.1.6", | ||
"@types/node": "16.11.47", | ||
"@typescript-eslint/eslint-plugin": "5.32.0", | ||
"@typescript-eslint/parser": "5.32.0", | ||
"eslint": "8.21.0", | ||
"@types/jest": "28.1.8", | ||
"@types/node": "16.11.56", | ||
"@typescript-eslint/eslint-plugin": "5.35.1", | ||
"@typescript-eslint/parser": "5.35.1", | ||
"eslint": "8.23.0", | ||
"eslint-config-prettier": "8.5.0", | ||
@@ -56,14 +56,14 @@ "eslint-plugin-import": "2.26.0", | ||
"husky": "8.0.1", | ||
"jest": "28.1.3", | ||
"jest": "29.0.1", | ||
"jest-watch-select-projects": "2.0.0", | ||
"jest-watch-suspend": "1.1.2", | ||
"jest-watch-typeahead": "2.0.0", | ||
"jest-watch-typeahead": "2.1.1", | ||
"npm-run-all": "4.1.5", | ||
"prettier": "2.7.1", | ||
"pretty-quick": "3.1.3", | ||
"release-it": "15.2.0", | ||
"ts-jest": "28.0.7", | ||
"release-it": "15.4.0", | ||
"ts-jest": "28.0.8", | ||
"ts-node": "10.9.1", | ||
"ttypescript": "1.5.13", | ||
"typescript": "4.7.4", | ||
"typescript": "4.8.2", | ||
"upath": "2.0.1" | ||
@@ -70,0 +70,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
444929
331
5964