Moved parser to typescript

This commit is contained in:
Thaum Rystra
2024-02-18 22:45:54 +02:00
parent 5b7d352323
commit c721374278
35 changed files with 1073 additions and 449 deletions

View File

@@ -1,9 +1,11 @@
{
"cSpell.words": [
"autorun",
"blackbox",
"Crits",
"cyrb",
"EJSON",
"nearley",
"uncomputed"
]
}
}

View File

@@ -1,7 +1,19 @@
import { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
import resolve from '/imports/parser/resolve'
import rollDice from '/imports/parser/rollDice';
export default {
export type ParserFunction = {
comment: string;
examples: { input: string, result: string }[];
arguments: string[];
maxResolveLevels?: ResolveLevel[];
minArguments?: number,
maxArguments?: number,
resultType: string;
fn: (...args: any[]) => any;
}
const parserFunctions: { [name: string]: ParserFunction } = {
'abs': {
comment: 'Returns the absolute value of a number',
examples: [
@@ -105,22 +117,23 @@ export default {
arguments: ['array', 'number'],
resultType: 'number',
fn: function tableLookup(arrayNode, number) {
for (let i in arrayNode.values) {
let node = arrayNode.values[i];
for (const i in arrayNode.values) {
const node = arrayNode.values[i];
if (node.value > number) return +i;
}
return arrayNode.values.length;
}
},
'resolve': {
comment: 'Forces the given calcultion to resolve into a number, even in calculations where it would usually keep the unknown values as is',
comment: 'Forces the given calculation to resolve into a number, even in calculations where it would usually keep the unknown values as is',
examples: [
{ input: 'resolve(someUndefinedVariable + 3 + 4)', result: '7' },
{ input: 'resolve(1d6)', result: '4' },
],
arguments: ['parseNode'],
resultType: 'parseNode',
fn: function resolveFn(node) {
let { result } = resolve('reduce', node, this.scope, this.context);
const { result } = resolve('reduce', node, this.scope, this.context);
return result;
}
},
@@ -181,7 +194,7 @@ export default {
maxArguments: 3,
resultType: 'rollArray',
fn: function rerollFn(rollArray, numberToReroll = 1, keepNewRoll = false) {
let rollValues = rollArray.values
const rollValues = rollArray.values
// Iterate through the roll values
for (let i = 0; i < rollValues.length; i += 1) {
// If the number is less than the reroll limit
@@ -218,7 +231,7 @@ export default {
fn: function explodeFn(rollArray, depth = 1, numberToReroll = rollArray.diceSize) {
let overflowErrored = false;
if (depth > 99) depth = 99;
let rollValues = rollArray.values
const rollValues = rollArray.values
// Iterate through the roll values
for (let i = 0; i < rollValues.length; i += 1) {
// If the number is greater than or equal to the reroll limit
@@ -255,7 +268,9 @@ export default {
}
function anyNumberOf(type) {
let argumentArray = [type];
const argumentArray = [type];
argumentArray.anyLength = true;
return argumentArray;
}
export default parserFunctions;

View File

@@ -0,0 +1,28 @@
import { ParseNode } from '/imports/parser/parser';
import { ResolvedResult, Context } from '/imports/parser/resolve';
export type ResolveLevel = 'compile' | 'roll' | 'reduce';
export default interface NodeFactory {
create(node: Partial<ParseNode>): ParseNode;
compile?(
node: ParseNode, scope: Record<string, any>, context: Context
): ResolvedResult;
roll?(
node: ParseNode, scope: Record<string, any>, context: Context
): ResolvedResult;
reduce?(
node: ParseNode, scope: Record<string, any>, context: Context
): ResolvedResult;
resolve?(
fn: ResolveLevel, node: ParseNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: ParseNode): string;
traverse?(node: ParseNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map?(node: ParseNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}

View File

@@ -0,0 +1,29 @@
import { AccessorNode } from './accessor';
import { ArrayNode } from './array';
import { CallNode } from './call';
import { ConstantNode } from './constant';
import { ErrorNode } from './error';
import { IfNode } from './if';
import { IndexNode } from './indexNode';
import { NotNode } from './not';
import { OperatorNode } from './operator';
import { ParenthesisNode } from './parenthesis';
import { RollNode } from './roll';
import { RollArrayNode } from './rollArray';
import { UnaryOperatorNode } from './unaryOperator';
type ParseNode = AccessorNode
| ArrayNode
| CallNode
| ConstantNode
| ErrorNode
| IfNode
| IndexNode
| NotNode
| OperatorNode
| ParenthesisNode
| RollNode
| RollArrayNode
| UnaryOperatorNode
export default ParseNode;

View File

@@ -1,18 +1,19 @@
import accessor from './accessor';
import array from './array.js';
import array from './array';
import call from './call';
import constant from './constant';
import error from './error';
import ifNode from './if';
import index from './index';
import index from './indexNode';
import not from './not';
import operator from './operator';
import parenthesis from './parenthesis';
import roll from './roll';
import rollArray from './rollArray';
import unaryOperator from './unaryOperator';
import NodeFactory from '/imports/parser/parseTree/NodeFactory';
export default {
const factories: Record<string, NodeFactory> = {
accessor,
array,
call,
@@ -29,3 +30,5 @@ export default {
symbol: accessor,
unaryOperator,
};
export default factories;

View File

@@ -1,17 +1,41 @@
import constant from './constant';
import array from './array';
import resolve from '../resolve';
import resolve, { Context, ResolvedResult } from '/imports/parser/resolve';
import { getFromScope } from '/imports/api/creature/creatures/CreatureVariables';
import NodeFactory from '/imports/parser/parseTree/NodeFactory';
const accessor = {
create({ name, path }) {
export type AccessorNode = {
parseType: 'accessor';
path?: string[];
name: string;
}
interface AccessorFactory extends NodeFactory {
create(node: Partial<AccessorNode>): AccessorNode;
compile(
node: AccessorNode, scope: Record<string, any>, context: Context
): ResolvedResult;
roll?: undefined;
resolve?: undefined;
reduce(
node: AccessorNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: AccessorNode): string;
traverse?: undefined;
map?: undefined;
}
const accessor: AccessorFactory = {
create({ name, path }: { name: string, path?: string[] }): AccessorNode {
return {
parseType: 'accessor',
path,
name,
};
},
compile(node, scope, context) {
compile(
node: AccessorNode, scope: Record<string, any>, context: Context
): ResolvedResult {
let value = getFromScope(node.name, scope);
// Get the value from the given path
node.path?.forEach(name => {
@@ -78,7 +102,7 @@ const accessor = {
context,
};
},
reduce(node, scope, context) {
reduce(node, scope, context): ResolvedResult {
let { result } = accessor.compile(node, scope, context);
({ result } = resolve('reduce', result, scope, context));
if (result.parseType === 'accessor') {

View File

@@ -1,55 +0,0 @@
import resolve, { toString, traverse, map } from '../resolve';
import constant from './constant';
const array = {
create({ values }) {
return {
parseType: 'array',
values,
};
},
fromConstantArray(array) {
let values = array.map(value => {
let valueType = typeof value;
if (
valueType === 'string' ||
valueType === 'number' ||
valueType === 'boolean' ||
valueType === 'undefined'
) {
return constant.create({ value, valueType });
} else {
// Gracefully create an empty spot in the array for unsupported types
return undefined;
// throw `Unexpected type in constant array: ${valueType}`
}
});
return array.create({ values });
},
resolve(fn, node, scope, context) {
let values = node.values.map(node => {
let { result } = resolve(fn, node, scope, context);
return result;
});
return {
result: array.create({ values }),
context,
};
},
toString(node) {
return `[${node.values.map(value => toString(value)).join(', ')}]`;
},
traverse(node, fn) {
fn(node);
node.values.forEach(value => traverse(value, fn));
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.values = node.values.map(value => map(value, fn));
}
return resultingNode;
},
}
export default array;

View File

@@ -0,0 +1,75 @@
import resolve, { toString, traverse, map, Context, ResolvedResult } from '/imports/parser/resolve';
import constant from './constant';
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
import ParseNode from '/imports/parser/parseTree/ParseNode';
export type ArrayNode = {
parseType: 'array';
values: ParseNode[];
}
interface ArrayFactory extends NodeFactory {
create(node: Partial<ArrayNode>): ArrayNode;
fromConstantArray(array: (string | number | boolean | undefined)[]): ArrayNode;
compile?: undefined;
roll?: undefined;
reduce?: undefined;
resolve(
fn: ResolveLevel, node: ArrayNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: ArrayNode): string;
traverse(node: ArrayNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: ArrayNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
const array: ArrayFactory = {
create({ values }: { values: ParseNode[] }) {
return {
parseType: 'array',
values,
};
},
fromConstantArray(constantArray) {
const values = constantArray.map(value => {
const valueType = typeof value;
if (
valueType === 'string' ||
valueType === 'number' ||
valueType === 'boolean' ||
valueType === 'undefined'
) {
return constant.create({ value });
} else {
// Gracefully create an empty constant in the array for unsupported types
return constant.create({ value: undefined });
}
});
return array.create({ values });
},
resolve(fn, node, scope, context): ResolvedResult {
const values = node.values.map(node => {
const { result } = resolve(fn, node, scope, context);
return result;
});
return {
result: array.create({ values }),
context,
};
},
toString(node) {
return `[${node.values.map(value => toString(value)).join(', ')}]`;
},
traverse(node, fn) {
fn(node);
node.values.forEach(value => traverse(value, fn));
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.values = node.values.map(value => map(value, fn));
}
return resultingNode;
},
}
export default array;

View File

@@ -1,18 +1,38 @@
import error from './error';
import constant from './constant';
import functions from '/imports/parser/functions';
import resolve, { toString, traverse, map } from '../resolve';
import functions, { ParserFunction } from '/imports/parser/functions';
import resolve, { toString, traverse, map, Context, ResolvedResult } from '/imports/parser/resolve';
import ParseNode from '/imports/parser/parseTree/ParseNode';
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
const call = {
create({ functionName, args }) {
export type CallNode = {
parseType: 'call';
functionName: string;
args: ParseNode[];
}
interface CallFactory extends NodeFactory {
create(node: Partial<CallNode>): CallNode;
resolve(
fn: ResolveLevel, node: CallNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: CallNode): string;
traverse(node: CallNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: CallNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
checkArguments(node: CallNode, fn: ResolveLevel, func: ParserFunction,
resolvedArgs: ParseNode[], context: Context): boolean;
}
const call: CallFactory = {
create({ functionName, args = [] }: { functionName: string, args: ParseNode[] }): CallNode {
return {
parseType: 'call',
functionName,
args,
}
},
resolve(fn, node, scope, context) {
let func = functions[node.functionName];
resolve(fn, node, scope, context): ResolvedResult {
const func = functions[node.functionName];
// Check that the function exists
if (!func) {
context.error(`${node.functionName} is not a supported function`);
@@ -26,9 +46,9 @@ const call = {
}
// Resolve a given node to a maximum depth of resolution
const resolveToLevel = (node, maxResolveFn = 'reduce') => {
const resolveToLevel = (node, maxResolveFn = 'reduce'): ResolvedResult => {
// Determine the actual depth to resolve to
let resolveFn = 'reduce';
let resolveFn: ResolveLevel = 'reduce';
if (fn === 'compile' || maxResolveFn === 'compile') {
resolveFn = 'compile';
} else if (fn === 'roll' || maxResolveFn === 'roll') {
@@ -39,19 +59,13 @@ const call = {
}
// Resolve the arguments
let resolvedArgs = node.args.map((arg, i) => {
let { result } = resolveToLevel(arg, func.maxResolveLevels?.[i]);
const resolvedArgs = node.args.map((arg, i) => {
const { result } = resolveToLevel(arg, func.maxResolveLevels?.[i]);
return result;
});
// Check that the arguments match what is expected
let checkFailed = call.checkArugments({
node,
fn,
resolvedArgs,
func,
context,
});
const checkFailed = call.checkArguments(node, fn, func, resolvedArgs, context);
if (checkFailed) {
if (fn === 'reduce') {
@@ -74,8 +88,8 @@ const call = {
}
}
// Map contant nodes to constants before attempting to run the function
let mappedArgs = resolvedArgs.map((arg, index) => {
// Map constant nodes to constants before attempting to run the function
const mappedArgs = resolvedArgs.map((arg, index) => {
if (
arg.parseType === 'constant' &&
func.arguments[index] !== 'parseNode'
@@ -88,12 +102,12 @@ const call = {
try {
// Run the function
let value = func.fn.apply({
const value = func.fn.apply({
scope,
context,
}, mappedArgs);
let valueType = typeof value;
const valueType = typeof value;
if (valueType === 'number' || valueType === 'string' || valueType === 'boolean') {
// Convert constant results into constant nodes
return {
@@ -129,7 +143,7 @@ const call = {
}
return resultingNode;
},
checkArugments({ node, fn, func, resolvedArgs, context }) {
checkArguments(node, fn, func, resolvedArgs, context) {
const argumentsExpected = func.arguments;
// Check that the number of arguments matches the number expected
if (
@@ -146,7 +160,7 @@ const call = {
let failed = false;
// Check that each argument is of the correct type
resolvedArgs.forEach((node, index) => {
let type;
let type: string;
if (argumentsExpected.anyLength) {
type = argumentsExpected[0];
} else {
@@ -155,8 +169,8 @@ const call = {
if (type === 'parseNode') return;
if (node.parseType !== type && node.valueType !== type) failed = true;
if (failed && fn === 'reduce') {
let typeName = typeof type === 'string' ? type : type.constructor.name;
let nodeName = node.parseType;
const typeName = typeof type === 'string' ? type : type.constructor.name;
const nodeName = node.parseType;
context.error(`Incorrect arguments to ${node.functionName} function` +
`expected ${typeName} got ${nodeName}`);
}

View File

@@ -1,17 +0,0 @@
const constant = {
create({value}){
return {
parseType: 'constant',
valueType: typeof value,
value,
}
},
compile(node, scope, context){
return {result: node, context};
},
toString(node){
return `${node.value}`;
},
}
export default constant;

View File

@@ -0,0 +1,42 @@
import NodeFactory from '/imports/parser/parseTree/NodeFactory';
import { Context, ResolvedResult } from '/imports/parser/resolve';
type ConstantValueType = number | string | boolean | undefined
export type ConstantNode = {
parseType: 'constant';
value: ConstantValueType;
// TODO replace all `constantNode.valueType` with `typeof constantNode.value`
valueType: 'number' | 'string' | 'boolean' | 'undefined';
}
interface ConstantFactory extends NodeFactory {
create({ value }: { value: ConstantValueType }): ConstantNode;
compile(
node: ConstantNode, scope: Record<string, any>, context: Context
): ResolvedResult;
roll?: undefined;
reduce?: undefined;
resolve?: undefined;
toString(node: ConstantNode): string;
traverse?: undefined;
map?: undefined;
}
const constant: ConstantFactory = {
create({ value }): ConstantNode {
return {
parseType: 'constant',
valueType: typeof value as 'number' | 'string' | 'boolean' | 'undefined',
value,
}
},
compile(node, scope, context) {
return { result: node, context };
},
toString(node) {
return `${node.value}`;
},
}
export default constant;

View File

@@ -1,17 +0,0 @@
const error = {
create({ node, error }) {
return {
parseType: 'error',
node,
error,
}
},
compile(node, scope, context) {
return { result: node, context };
},
toString(node) {
return `${node.error.type} error: ${node.error.message}`;
},
}
export default error;

View File

@@ -0,0 +1,40 @@
import NodeFactory from '/imports/parser/parseTree/NodeFactory';
import ParseNode from '/imports/parser/parseTree/ParseNode';
import { Context, ResolvedResult } from '/imports/parser/resolve';
export type ErrorNode = {
parseType: 'error';
node: ParseNode;
error: string;
}
interface ErrorFactory extends NodeFactory {
create(node: Partial<ErrorNode>): ErrorNode;
compile(
node: ErrorNode, scope: Record<string, any>, context: Context
): ResolvedResult;
roll?: undefined;
reduce?: undefined;
resolve?: undefined;
toString(node: ErrorNode): string;
traverse?: undefined;
map?: undefined;
}
const error: ErrorFactory = {
create({ node, error }: { node: ParseNode, error: string }) {
return {
parseType: 'error',
node,
error,
}
},
compile(node, scope, context) {
return { result: node, context };
},
toString(node) {
return node.error;
},
}
export default error;

View File

@@ -1,53 +0,0 @@
import resolve, { traverse, toString, map } from '../resolve';
const ifNode = {
create({condition, consequent, alternative}){
return {
parseType: 'if',
condition,
consequent,
alternative,
};
},
toString(node){
let {condition, consequent, alternative} = node;
return `${toString(condition)} ? ${toString(consequent)} : ${toString(alternative)}`
},
resolve(fn, node, scope, context){
let {result: condition} = resolve(fn, node.condition, scope, context);
if (condition.parseType === 'constant'){
if (condition.value){
return resolve(fn, node.consequent, scope, context);
} else {
return resolve(fn, node.alternative, scope, context);
}
} else {
return {
result: ifNode.create({
condition: condition,
consequent: node.consequent,
alternative: node.alternative,
}),
context,
};
}
},
traverse(node, fn){
fn(node);
traverse(node.condition, fn);
traverse(node.consequent, fn);
traverse(node.alternative, fn);
},
map(node, fn){
const resultingNode = fn(node);
if (resultingNode === node){
node.condition = map(node.condition, fn);
node.consequent = map(node.consequent, fn);
node.alternative = map(node.alternative, fn);
}
return resultingNode;
},
}
export default ifNode;

View File

@@ -0,0 +1,79 @@
import resolve, { traverse, toString, map } from '../resolve';
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
import ParseNode from '/imports/parser/parseTree/ParseNode';
import { Context, ResolvedResult } from '/imports/parser/resolve';
export type IfNode = {
parseType: 'if';
condition: ParseNode;
consequent: ParseNode;
alternative: ParseNode;
}
interface IfFactory extends NodeFactory {
create(node: Partial<IfNode>): IfNode;
compile?: undefined;
roll?: undefined;
reduce?: undefined;
resolve(
fn: ResolveLevel, node: IfNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: IfNode): string;
traverse(node: IfNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: IfNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
const ifNode: IfFactory = {
create(
{ condition, consequent, alternative }:
{ condition: ParseNode, consequent: ParseNode, alternative: ParseNode }
) {
return {
parseType: 'if',
condition,
consequent,
alternative,
};
},
toString(node) {
const { condition, consequent, alternative } = node;
condition.parseType
return `${toString(condition)} ? ${toString(consequent)} : ${toString(alternative)}`
},
resolve(fn, node, scope, context): ResolvedResult {
const { result: condition } = resolve(fn, node.condition, scope, context);
if (condition.parseType === 'constant') {
if (condition.value) {
return resolve(fn, node.consequent, scope, context);
} else {
return resolve(fn, node.alternative, scope, context);
}
} else {
return {
result: ifNode.create({
condition: condition,
consequent: node.consequent,
alternative: node.alternative,
}),
context,
};
}
},
traverse(node, fn) {
fn(node);
traverse(node.condition, fn);
traverse(node.consequent, fn);
traverse(node.alternative, fn);
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.condition = map(node.condition, fn);
node.consequent = map(node.consequent, fn);
node.alternative = map(node.alternative, fn);
}
return resultingNode;
},
}
export default ifNode;

View File

@@ -1,8 +1,29 @@
import resolve, { traverse, toString, map } from '../resolve';
import resolve, { traverse, toString, map, ResolvedResult, Context } from '/imports/parser/resolve';
import error from './error';
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
import ParseNode from '/imports/parser/parseTree/ParseNode';
const indexNode = {
create({ array, index }) {
export type IndexNode = {
parseType: 'index';
array: ParseNode;
index: ParseNode;
}
interface IndexFactory extends NodeFactory {
create(node: Partial<IndexNode>): IndexNode;
compile?: undefined;
roll?: undefined;
reduce?: undefined;
resolve(
fn: ResolveLevel, node: IndexNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: IndexNode): string;
traverse(node: IndexNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: IndexNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
const indexNode: IndexFactory = {
create({ array, index }: { array: ParseNode, index: ParseNode }) {
return {
parseType: 'index',
array,
@@ -10,8 +31,8 @@ const indexNode = {
}
},
resolve(fn, node, scope, context) {
let { result: index } = resolve(fn, node.index, scope, context);
let { result: array } = resolve(fn, node.array, scope, context);
const { result: index } = resolve(fn, node.index, scope, context);
const { result: array } = resolve(fn, node.array, scope, context);
if (
index.valueType === 'number' &&
@@ -25,7 +46,7 @@ const indexNode = {
` of length ${array.values.length}`,
});
}
let selection = array.values[index.value - 1];
const selection = array.values[index.value - 1];
if (selection) {
return resolve(fn, selection, scope, context);
}
@@ -63,12 +84,12 @@ const indexNode = {
toString(node) {
return `${toString(node.array)}[${toString(node.index)}]`;
},
traverse(node, fn) {
traverse(node, fn: (node: ParseNode) => any) {
fn(node);
traverse(node.array, fn);
traverse(node.index, fn);
},
map(node, fn) {
map(node, fn: (node: ParseNode) => any) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.array = map(node.array, fn);

View File

@@ -1,44 +0,0 @@
import resolve, { toString, traverse, map } from '../resolve';
import constant from './constant';
const not = {
create({ right }) {
return {
parseType: 'not',
right,
}
},
resolve(fn, node, scope, context) {
const { result: right } = resolve(fn, node.right, scope, context);
if (right.parseType !== 'constant') {
return {
result: not.create({
right: right,
}),
context,
};
}
return {
result: constant.create({
value: !right.value,
}),
context,
};
},
toString(node) {
return `!${toString(node.right)}`;
},
traverse(node, fn) {
fn(node);
traverse(node.right, fn);
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.right = map(node.right, fn);
}
return resultingNode;
},
}
export default not;

View File

@@ -0,0 +1,64 @@
import resolve, { toString, traverse, map, Context, ResolvedResult } from '/imports/parser/resolve';
import constant from './constant';
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
import ParseNode from '/imports/parser/parseTree/ParseNode';
export type NotNode = {
parseType: 'not';
right: ParseNode;
}
interface NotFactory extends NodeFactory {
create(node: Partial<NotNode>): NotNode;
compile?: undefined;
roll?: undefined;
reduce?: undefined;
resolve(
fn: ResolveLevel, node: NotNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: NotNode): string;
traverse(node: NotNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: NotNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
const not: NotFactory = {
create({ right }: { right: ParseNode }) {
return {
parseType: 'not',
right,
}
},
resolve(fn, node, scope, context) {
const { result: right } = resolve(fn, node.right, scope, context);
if (right.parseType !== 'constant') {
return {
result: not.create({
right: right,
}),
context,
};
}
return {
result: constant.create({
value: !right.value,
}),
context,
};
},
toString(node) {
return `!${toString(node.right)}`;
},
traverse(node, fn) {
fn(node);
traverse(node.right, fn);
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.right = map(node.right, fn);
}
return resultingNode;
},
}
export default not;

View File

@@ -1,12 +1,41 @@
import resolve, { toString, traverse, map } from '../resolve';
import resolve, { toString, traverse, map, ResolvedResult, Context } from '/imports/parser/resolve';
import constant from './constant';
import ParseNode from '/imports/parser/parseTree/ParseNode';
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
type OperatorSymbol = '*' | '/' | '^' | '+' | '-' | '%' | '&' | '&&' | '|' | '||' | '=' |
'==' | '===' | '!=' | '!==' | '>' | '<' | '>=' | '<=';
export type OperatorNode = {
parseType: 'operator';
left: ParseNode;
right: ParseNode;
operator: OperatorSymbol;
}
interface OperatorFactory extends NodeFactory {
create(node: Partial<OperatorNode>): OperatorNode;
compile?: undefined;
roll?: undefined;
reduce?: undefined;
resolve(
fn: ResolveLevel, node: OperatorNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: OperatorNode): string;
traverse(node: OperatorNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: OperatorNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
// Which operators can be considered commutative by the parser
// i.e. 1 + 2 + 3 === 2 + 3 + 1
const commutativeOperators = ['+', '*']
const operator = {
create({ left, right, operator }) {
const operator: OperatorFactory = {
create({
left, right, operator
}: {
left: ParseNode, right: ParseNode, operator: OperatorSymbol
}) {
return {
parseType: 'operator',
left,
@@ -45,7 +74,7 @@ const operator = {
};
},
toString(node) {
let { left, right, operator } = node;
const { left, right, operator } = node;
// special case of adding a negative number
if (operator === '+' && right.valueType === 'number' && right.value < 0) {
return `${toString(left)} - ${-right.value}`
@@ -67,7 +96,7 @@ const operator = {
},
}
function applyOperator(operator, left, right) {
function applyOperator(operator: OperatorSymbol, left: ParseNode, right: ParseNode) {
let result;
switch (operator) {
case '+': result = left + right; break;
@@ -93,7 +122,9 @@ function applyOperator(operator, left, right) {
return result;
}
function reorderCommutativeOperations(node, leftNode, rightNode) {
function reorderCommutativeOperations(
node: OperatorNode, leftNode: ParseNode, rightNode: ParseNode
) {
// Make sure the operator is commutative
if (!commutativeOperators.includes(node.operator)) return;

View File

@@ -1,41 +0,0 @@
import resolve, { toString, traverse, map } from '../resolve';
const parenthesis = {
create({ content }) {
return {
parseType: 'parenthesis',
content,
};
},
resolve(fn, node, scope, context) {
const { result: content } = resolve(fn, node.content, scope, context);
if (
fn === 'reduce' ||
content.parseType === 'constant' ||
content.parseType === 'error'
) {
return { result: content, context };
} else {
return {
result: parenthesis.create({ content }),
context
};
}
},
toString(node) {
return `(${toString(node.content)})`;
},
traverse(node, fn) {
fn(node);
traverse(node.content, fn);
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.content = map(node.content, fn);
}
return resultingNode;
},
}
export default parenthesis;

View File

@@ -0,0 +1,61 @@
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
import ParseNode from '/imports/parser/parseTree/ParseNode';
import resolve, { toString, traverse, map, Context, ResolvedResult } from '/imports/parser/resolve';
export type ParenthesisNode = {
parseType: 'parenthesis';
content: ParseNode;
}
interface ParenthesisFactory extends NodeFactory {
create(node: Partial<ParenthesisNode>): ParenthesisNode;
compile?: undefined;
roll?: undefined;
reduce?: undefined;
resolve(
fn: ResolveLevel, node: ParenthesisNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: ParenthesisNode): string;
traverse(node: ParenthesisNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: ParenthesisNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
const parenthesis: ParenthesisFactory = {
create({ content }: { content: ParseNode }) {
return {
parseType: 'parenthesis',
content,
};
},
resolve(fn, node, scope, context) {
const { result: content } = resolve(fn, node.content, scope, context);
if (
fn === 'reduce' ||
content.parseType === 'constant' ||
content.parseType === 'error'
) {
return { result: content, context };
} else {
return {
result: parenthesis.create({ content }),
context
};
}
},
toString(node) {
return `(${toString(node.content)})`;
},
traverse(node, fn: (node: ParseNode) => any) {
fn(node);
traverse(node.content, fn);
},
map(node, fn: (node: ParseNode) => any) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.content = map(node.content, fn);
}
return resultingNode;
},
}
export default parenthesis;

View File

@@ -1,11 +1,36 @@
import resolve, { toString, traverse, map } from '../resolve';
import resolve, { toString, traverse, map, ResolvedResult, Context } from '../resolve';
import error from './error';
import rollArray from './rollArray';
import rollDice from '/imports/parser/rollDice';
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
import ParseNode from '/imports/parser/parseTree/ParseNode';
import NodeFactory from '/imports/parser/parseTree/NodeFactory';
const rollNode = {
create({ left, right }) {
export type RollNode = {
parseType: 'roll';
left: ParseNode;
right: ParseNode;
}
interface RollNodeFactory extends NodeFactory {
create(node: Partial<RollNode>): RollNode;
compile(
node: RollNode, scope: Record<string, any>, context: Context
): ResolvedResult;
roll(
node: RollNode, scope: Record<string, any>, context: Context
): ResolvedResult;
reduce(
node: RollNode, scope: Record<string, any>, context: Context
): ResolvedResult;
resolve?: undefined;
toString(node: RollNode): string;
traverse(node: RollNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: RollNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
const rollNode: RollNodeFactory = {
create({ left, right }: { left: ParseNode, right: ParseNode }) {
return {
parseType: 'roll',
left,
@@ -22,7 +47,9 @@ const rollNode = {
},
toString(node) {
if (
node.left.valueType === 'number' && node.left.value === 1
node.left.parseType === 'constant'
&& typeof node.left.value === 'number'
&& node.left.value === 1
) {
return `d${toString(node.right)}`;
} else {
@@ -32,10 +59,18 @@ const rollNode = {
roll(node, scope, context) {
const { result: left } = resolve('reduce', node.left, scope, context);
const { result: right } = resolve('reduce', node.right, scope, context);
if (left.valueType !== 'number' && !Number.isInteger(left.value)) {
if (
left.parseType !== 'constant'
|| typeof left.value !== 'number'
|| !Number.isInteger(left.value)
) {
return errorResult('Number of dice is not an integer', node, context);
}
if (right.valueType !== 'number' && !Number.isInteger(right.value)) {
if (
right.parseType !== 'constant'
|| typeof right.value !== 'number'
|| !Number.isInteger(right.value)
) {
return errorResult('Dice size is not an integer', node, context);
}
let number = left.value;
@@ -46,8 +81,8 @@ const rollNode = {
const message = `Can't roll more than ${STORAGE_LIMITS.diceRollValuesCount} dice at once`;
return errorResult(message, node, context);
}
let diceSize = right.value;
let values = rollDice(number, diceSize);
const diceSize = right.value;
const values = rollDice(number, diceSize);
if (context) {
context.rolls.push({ number, diceSize, values });
}
@@ -79,7 +114,7 @@ const rollNode = {
},
}
function errorResult(message, node, context) {
function errorResult(message: string, node: RollNode, context: Context) {
context.error(message);
return {
result: error.create({ node, error: message }),

View File

@@ -1,46 +0,0 @@
import constant from './constant';
const rollArray = {
create({ values, diceSize, diceNum }) {
return {
parseType: 'rollArray',
values: values.map(v => ({ value: v })),
diceSize,
diceNum,
};
},
compile(node, scope, context) {
return {
result: node,
context
};
},
toString(node) {
return `${node.diceNum || ''}d${node.diceSize} [${valuesToString(node.values)}]`;
},
reduce(node, scope, context) {
const total = node.values.reduce((a, b) => {
if (b.disabled) return a;
return a + b.value;
}, 0);
return {
result: constant.create({
value: total,
}),
context,
};
},
}
function valuesToString(values) {
return values.map(v => {
let text = `${v.value}`;
if (v.disabled) text = `~~${text}~~`;
if (v.italics) text = `*${text}*`;
if (v.bold) text = `**${text}**`;
if (v.underline) text = `__${text}__`;
return text;
}).join(', ');
}
export default rollArray;

View File

@@ -0,0 +1,80 @@
import constant from './constant';
import NodeFactory from '/imports/parser/parseTree/NodeFactory';
import { Context, ResolvedResult } from '/imports/parser/resolve';
type RollValue = {
value: number,
disabled?: true,
italics?: true,
bold?: true,
underline?: true,
}
export type RollArrayNode = {
parseType: 'rollArray';
values: RollValue[];
diceSize: number,
diceNum: number,
}
interface RollArrayFactory extends NodeFactory {
create(input: { values: number[], diceSize: number, diceNum: number }): RollArrayNode;
compile(
node: RollArrayNode, scope: Record<string, any>, context: Context
): ResolvedResult;
roll?: undefined;
reduce(
node: RollArrayNode, scope: Record<string, any>, context: Context
): ResolvedResult;
resolve?: undefined;
toString(node: RollArrayNode): string;
traverse?: undefined;
map?: undefined;
}
const rollArray: RollArrayFactory = {
create({
values, diceSize, diceNum
}) {
return {
parseType: 'rollArray',
values: values.map(v => ({ value: v })),
diceSize,
diceNum,
};
},
compile(node, scope, context) {
return {
result: node,
context
};
},
toString(node) {
return `${node.diceNum || ''}d${node.diceSize} [${valuesToString(node.values)}]`;
},
reduce(node, scope, context) {
const total = node.values.reduce((a, b) => {
if (b.disabled) return a;
return a + b.value;
}, 0);
return {
result: constant.create({
value: total,
}),
context,
};
},
}
function valuesToString(values: RollValue[]) {
return values.map(v => {
let text = `${v.value}`;
if (v.disabled) text = `~~${text}~~`;
if (v.italics) text = `*${text}*`;
if (v.bold) text = `**${text}**`;
if (v.underline) text = `__${text}__`;
return text;
}).join(', ');
}
export default rollArray;

View File

@@ -1,53 +0,0 @@
import resolve, { toString, traverse, map } from '../resolve';
import constant from './constant';
const unaryOperator = {
create({ operator, right }) {
return {
parseType: 'unaryOperator',
operator,
right,
};
},
resolve(fn, node, scope, context) {
const { result: rightNode } = resolve(fn, node.right, scope, context);
if (rightNode.valueType !== 'number') {
return {
result: unaryOperator.create({
operator: node.operator,
right: rightNode,
}),
context,
};
}
let right = rightNode.value;
let result;
switch (node.operator) {
case '-': result = -right; break;
case '+': result = +right; break;
}
return {
result: constant.create({
value: result,
parseType: typeof result,
}),
context,
};
},
toString(node) {
return `${node.operator}${toString(node.right)}`;
},
traverse(node, fn) {
fn(node);
traverse(node.right, fn);
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.right = map(node.right, fn);
}
return resultingNode;
},
};
export default unaryOperator;

View File

@@ -0,0 +1,78 @@
import resolve, { toString, traverse, map, Context, ResolvedResult } from '/imports/parser/resolve';
import constant from './constant';
import NodeFactory, { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
import ParseNode from '/imports/parser/parseTree/ParseNode';
type UnaryOperatorSymbol = '+' | '-';
export type UnaryOperatorNode = {
parseType: 'unaryOperator';
operator: UnaryOperatorSymbol;
right: ParseNode;
}
interface UnaryOperatorFactory extends NodeFactory {
create(node: Partial<UnaryOperatorNode>): UnaryOperatorNode;
compile?: undefined;
roll?: undefined;
reduce?: undefined;
resolve(
fn: ResolveLevel, node: UnaryOperatorNode, scope: Record<string, any>, context: Context
): ResolvedResult;
toString(node: UnaryOperatorNode): string;
traverse(node: UnaryOperatorNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
map(node: UnaryOperatorNode, fn: (node: ParseNode) => any): ReturnType<typeof fn>;
}
const unaryOperator: UnaryOperatorFactory = {
create({ operator, right }: { operator: UnaryOperatorSymbol, right: ParseNode }) {
return {
parseType: 'unaryOperator',
operator,
right,
};
},
resolve(fn, node, scope, context) {
const { result: rightNode } = resolve(fn, node.right, scope, context);
if (
rightNode.parseType !== 'constant'
|| typeof rightNode.value !== 'number'
) {
return {
result: unaryOperator.create({
operator: node.operator,
right: rightNode,
}),
context,
};
}
const right = rightNode.value;
let result: number;
switch (node.operator) {
case '-': result = -right; break;
case '+': result = +right; break;
}
return {
result: constant.create({
value: result,
}),
context,
};
},
toString(node) {
return `${node.operator}${toString(node.right)}`;
},
traverse(node, fn) {
fn(node);
traverse(node.right, fn);
},
map(node, fn) {
const resultingNode = fn(node);
if (resultingNode === node) {
node.right = map(node.right, fn);
}
return resultingNode;
},
};
export default unaryOperator;

View File

@@ -1,34 +0,0 @@
import grammar from '/imports/parser/grammar';
import nearley from 'nearley';
const nearleyGrammar = nearley.Grammar.fromCompiled(grammar);
export default function parser() {
return new nearley.Parser(nearleyGrammar);
}
export function parse(string) {
let parser = new nearley.Parser(nearleyGrammar);
parser.feed(string);
let results = parser.results;
if (results.length === 1) {
return results[0];
} else if (results.length === 0) {
// Valid parsing up until now, but need more
throw new EndOfInputError('Unexpected end of input');
} else {
console.warn('Grammar is ambiguous!', { string, results });
return results[0];
}
}
export function prettifyParseError(e) {
if (e.message) e = e.message
return e.toString().split('.')[0];
}
class EndOfInputError extends Error {
constructor(message = '', ...args) {
super(message, ...args);
}
}

View File

@@ -0,0 +1,34 @@
import grammar from '/imports/parser/grammar';
import { Parser, Grammar } from 'nearley';
import ParseNode from '/imports/parser/parseTree/ParseNode';
const nearleyGrammar = Grammar.fromCompiled(grammar);
export default function parser() {
return new Parser(nearleyGrammar);
}
export function parse(string: string): ParseNode {
const parser = new Parser(nearleyGrammar);
parser.feed(string);
const results = parser.results;
if (results.length === 1) {
return results[0];
} else if (results.length === 0) {
// Valid parsing up until now, but need more
throw new EndOfInputError('Unexpected end of input');
} else {
console.warn('Grammar is ambiguous!', { string, results });
return results[0];
}
}
export function prettifyParseError(e: Meteor.Error | Error): string {
return e.message.split('.')[0];
}
class EndOfInputError extends Error {
constructor(message = '') {
super(message);
}
}

View File

@@ -1,32 +1,36 @@
import nodeTypeIndex from './parseTree/_index';
import ParseNode from '/imports/parser/parseTree/ParseNode';
// Takes a parse ndoe and computes it to a set detail level
// Takes a parse node and computes it to a set detail level
// returns {result, context}
export default function resolve(fn, node, scope, context = new Context()) {
if (!node) return { result: undefined, context };
let type = nodeTypeIndex[node.parseType];
if (!type) {
export default function resolve(
fn: 'roll' | 'reduce' | 'compile',
node: ParseNode,
scope: Record<string, any>,
context = new Context()
): ResolvedResult {
if (!node) throw 'Node must be supplied';
const factory = nodeTypeIndex[node.parseType];
const handlerFunction = factory[fn];
if (!factory) {
throw new Meteor.Error(`Parse node type: ${node.parseType} not implemented`);
}
if (type.resolve) {
return type.resolve(fn, node, scope, context);
} else if (type[fn]) {
return type[fn](node, scope, context);
} else if (fn === 'reduce' && type.roll) {
return type.roll(node, scope, context)
} else if (type.compile) {
return type.compile(node, scope, context)
if (factory.resolve) {
return factory.resolve(fn, node, scope, context);
} else if (handlerFunction) {
return handlerFunction(node, scope, context);
} else if (fn === 'reduce' && factory.roll) {
return factory.roll(node, scope, context)
} else if (factory.compile) {
return factory.compile(node, scope, context)
} else {
throw new Meteor.Error('Compile not implemented on ' + node.parseType);
}
}
export function toString(node) {
export function toString(node: ParseNode) {
if (!node) return '';
if (!node.parseType) {
throw new Meteor.Error(`Node does not have a parseType defined, node is type ${typeof node} with parseType ${node.parseType}`)
}
let type = nodeTypeIndex[node.parseType];
const type = nodeTypeIndex[node.parseType];
if (!type?.toString) {
throw new Meteor.Error('toString not implemented on ' + node.parseType);
}
@@ -40,9 +44,9 @@ export function toPrimitiveOrString(node) {
return toString(node);
}
export function traverse(node, fn) {
export function traverse(node: ParseNode, fn: (ParseNode) => any): ReturnType<typeof fn> {
if (!node) return;
let type = nodeTypeIndex[node.parseType];
const type = nodeTypeIndex[node.parseType];
if (!type) {
console.error(node);
throw new Meteor.Error('Not valid parse node');
@@ -53,9 +57,9 @@ export function traverse(node, fn) {
return fn(node);
}
export function map(node, fn) {
export function map(node: ParseNode, fn: (ParseNode) => any): ReturnType<typeof fn> {
if (!node) return;
let type = nodeTypeIndex[node.parseType];
const type = nodeTypeIndex[node.parseType];
if (!type) {
console.error(node);
throw new Meteor.Error('Not valid parse node');
@@ -66,13 +70,23 @@ export function map(node, fn) {
return fn(node);
}
export type ResolvedResult = {
result: ParseNode,
context: Context
}
export class Context {
errors: (Error | { type: string, message: string })[];
rolls: { number: number, diceSize: number, values: number[] }[];
options: { [key: string]: any };
constructor({ errors = [], rolls = [], options = {} } = {}) {
this.errors = errors;
this.rolls = rolls;
this.options = options;
}
error(e) {
error(e: Error | string) {
if (!e) return;
if (typeof e === 'string') {
this.errors.push({
@@ -83,6 +97,7 @@ export class Context {
this.errors.push(e);
}
}
roll(r) {
this.rolls.push(r);
}

View File

@@ -125,7 +125,8 @@
"error",
"single"
],
"@typescript-eslint/no-this-alias": "off"
"@typescript-eslint/no-this-alias": "off",
"@typescript-eslint/no-explicit-any": "off"
}
}
}

21
node_modules/@types/nearley/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

15
node_modules/@types/nearley/README.md generated vendored Normal file
View File

@@ -0,0 +1,15 @@
# Installation
> `npm install --save @types/nearley`
# Summary
This package contains type definitions for nearley (https://github.com/Hardmath123/nearley#readme).
# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nearley.
### Additional Details
* Last updated: Tue, 07 Nov 2023 09:09:39 GMT
* Dependencies: none
# Credits
These definitions were written by [Nikita Litvin](https://github.com/deltaidea), and [BendingBender](https://github.com/BendingBender).

108
node_modules/@types/nearley/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,108 @@
export as namespace nearley;
export class Parser {
/**
* Reserved token for indicating a parse fail.
*/
static fail: {};
grammar: Grammar;
options: ParserOptions;
lexer: Lexer;
lexerState?: LexerState | undefined;
current: number;
/**
* An array of possible parsings. Each element is the thing returned by your grammar.
*
* Note that this is undefined before the first feed() call.
* It isn't typed as `any[] | undefined` to spare you the null checks when it's definitely an array.
*/
results: any[];
constructor(grammar: Grammar, options?: ParserOptions);
/**
* The Parser object can be fed data in parts with .feed(data).
* You can then find an array of parsings with the .results property.
* If results is empty, then there are no parsings.
* If results contains multiple values, then that combination is ambiguous.
*
* @throws If there are no possible parsings, nearley will throw an error
* whose offset property is the index of the offending token.
*/
feed(chunk: string): this;
finish(): any[];
restore(column: { [key: string]: any; lexerState: LexerState }): void;
save(): { [key: string]: any; lexerState: LexerState };
}
export interface ParserOptions {
keepHistory?: boolean | undefined;
lexer?: Lexer | undefined;
}
export class Rule {
static highestId: number;
id: number;
name: string;
symbols: any[];
postprocess?: Postprocessor | undefined;
constructor(name: string, symbols: any[], postprocess?: Postprocessor);
toString(withCursorAt?: number): string;
}
export class Grammar {
static fromCompiled(rules: CompiledRules): Grammar;
rules: Rule[];
start: string;
byName: { [ruleName: string]: Rule[] };
lexer?: Lexer | undefined;
constructor(rules: Rule[]);
}
export interface CompiledRules {
Lexer?: Lexer | undefined;
ParserStart: string;
ParserRules: ParserRule[];
}
export interface ParserRule {
name: string;
symbols: any[];
postprocess?: Postprocessor | undefined;
}
export type Postprocessor = (data: any[], reference?: number, wantedBy?: {}) => void;
export interface Lexer {
/**
* Sets the internal buffer to data, and restores line/col/state info taken from save().
*/
reset(data: string, state?: LexerState): void;
/**
* Returns e.g. {type, value, line, col, …}. Only the value attribute is required.
*/
next(): Token | undefined;
/**
* Returns an object describing the current line/col etc. This allows us
* to preserve this information between feed() calls, and also to support Parser#rewind().
* The exact structure is lexer-specific; nearley doesn't care what's in it.
*/
save(): LexerState;
/**
* Returns a string with an error message describing the line/col of the offending token.
* You might like to include a preview of the line in question.
*/
formatError(token: Token, message: string): string;
}
export type Token = string | { value: string };
export interface LexerState {
[x: string]: any;
}

58
node_modules/@types/nearley/package.json generated vendored Normal file
View File

@@ -0,0 +1,58 @@
{
"_from": "@types/nearley",
"_id": "@types/nearley@2.11.5",
"_inBundle": false,
"_integrity": "sha512-dM7TrN0bVxGGXTYGx4YhGear8ysLO5SOuouAWM9oltjQ3m9oYa13qi8Z1DJp5zxVMPukvQdsrnZmgzpeuTSEQA==",
"_location": "/@types/nearley",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "@types/nearley",
"name": "@types/nearley",
"escapedName": "@types%2fnearley",
"scope": "@types",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/@types/nearley/-/nearley-2.11.5.tgz",
"_shasum": "9087e1634e1c90efb25d661390702381789685cb",
"_spec": "@types/nearley",
"_where": "/Users/stef/github/DiceCloud",
"bugs": {
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Nikita Litvin",
"url": "https://github.com/deltaidea"
},
{
"name": "BendingBender",
"url": "https://github.com/BendingBender"
}
],
"dependencies": {},
"deprecated": false,
"description": "TypeScript definitions for nearley",
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nearley",
"license": "MIT",
"main": "",
"name": "@types/nearley",
"repository": {
"type": "git",
"url": "git+https://github.com/DefinitelyTyped/DefinitelyTyped.git",
"directory": "types/nearley"
},
"scripts": {},
"typeScriptVersion": "4.5",
"types": "index.d.ts",
"typesPublisherContentHash": "2b82830a1a87ef19e588c4f6dcd1c00fde50afd7c9dc5bd8233b054f436578d4",
"version": "2.11.5"
}

11
package-lock.json generated Normal file
View File

@@ -0,0 +1,11 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@types/nearley": {
"version": "2.11.5",
"resolved": "https://registry.npmjs.org/@types/nearley/-/nearley-2.11.5.tgz",
"integrity": "sha512-dM7TrN0bVxGGXTYGx4YhGear8ysLO5SOuouAWM9oltjQ3m9oYa13qi8Z1DJp5zxVMPukvQdsrnZmgzpeuTSEQA=="
}
}
}