@mathigon/hilbert
Advanced tools
Comparing version 0.5.3 to 0.5.4
@@ -752,4 +752,8 @@ 'use strict'; | ||
} | ||
function matchBrackets(tokens) { | ||
function matchBrackets(tokens, context) { | ||
const stack = [[]]; | ||
// When these identifiers appear immediately before parenthesis, like x(y), | ||
// they will be treated as variables with implicit multiplication, rather | ||
// than a custom function call. | ||
const safeVariables = ['π', ...((context === null || context === void 0 ? void 0 : context.variables) || [])]; | ||
for (const t of tokens) { | ||
@@ -763,7 +767,5 @@ const lastOpen = core.last(stack).length ? core.last(stack)[0].o : undefined; | ||
const term = core.last(stack); | ||
// Check if this is a normal bracket, or a function call. | ||
// Terms like x(y) are treated as functions, rather than implicit | ||
// multiplication, except for π(y). | ||
const isFn = (isOperator(t, ')') && core.last(term) instanceof ExprIdentifier && | ||
core.last(term).i !== 'π'); | ||
const lastTerm = core.last(term); | ||
const isFn = isOperator(t, ')') && lastTerm instanceof ExprIdentifier && | ||
!safeVariables.includes(lastTerm.i); | ||
const fnName = isFn ? term.pop().i : closed[0].o; | ||
@@ -859,5 +861,10 @@ // Support multiple arguments for function calls. | ||
// ============================================================================= | ||
/** Parses a string to an expression. */ | ||
function parse(str, collapse = false) { | ||
const expr = matchBrackets(tokenize(str)); | ||
/** | ||
* Parses a string to an expression. | ||
* | ||
* If `context` is supplied, interpret `f(a+b)` as `f*(a+b)` if `f` is in | ||
* `context.variables`. | ||
*/ | ||
function parse(str, collapse = false, context) { | ||
const expr = matchBrackets(tokenize(str), context); | ||
return collapse ? expr.collapse() : expr; | ||
@@ -864,0 +871,0 @@ } |
@@ -748,4 +748,8 @@ import { words, unique, flatten, isOneOf, join, last, cache } from '@mathigon/core'; | ||
} | ||
function matchBrackets(tokens) { | ||
function matchBrackets(tokens, context) { | ||
const stack = [[]]; | ||
// When these identifiers appear immediately before parenthesis, like x(y), | ||
// they will be treated as variables with implicit multiplication, rather | ||
// than a custom function call. | ||
const safeVariables = ['π', ...((context === null || context === void 0 ? void 0 : context.variables) || [])]; | ||
for (const t of tokens) { | ||
@@ -759,7 +763,5 @@ const lastOpen = last(stack).length ? last(stack)[0].o : undefined; | ||
const term = last(stack); | ||
// Check if this is a normal bracket, or a function call. | ||
// Terms like x(y) are treated as functions, rather than implicit | ||
// multiplication, except for π(y). | ||
const isFn = (isOperator(t, ')') && last(term) instanceof ExprIdentifier && | ||
last(term).i !== 'π'); | ||
const lastTerm = last(term); | ||
const isFn = isOperator(t, ')') && lastTerm instanceof ExprIdentifier && | ||
!safeVariables.includes(lastTerm.i); | ||
const fnName = isFn ? term.pop().i : closed[0].o; | ||
@@ -855,5 +857,10 @@ // Support multiple arguments for function calls. | ||
// ============================================================================= | ||
/** Parses a string to an expression. */ | ||
function parse(str, collapse = false) { | ||
const expr = matchBrackets(tokenize(str)); | ||
/** | ||
* Parses a string to an expression. | ||
* | ||
* If `context` is supplied, interpret `f(a+b)` as `f*(a+b)` if `f` is in | ||
* `context.variables`. | ||
*/ | ||
function parse(str, collapse = false, context) { | ||
const expr = matchBrackets(tokenize(str), context); | ||
return collapse ? expr.collapse() : expr; | ||
@@ -860,0 +867,0 @@ } |
{ | ||
"name": "@mathigon/hilbert", | ||
"version": "0.5.3", | ||
"version": "0.5.4", | ||
"description": "JavaScript expression parsing, MathML rendering and CAS.", | ||
@@ -35,10 +35,10 @@ "keywords": [ | ||
"@types/tape": "4.13.0", | ||
"rollup": "2.26.0", | ||
"rollup": "2.26.10", | ||
"tape": "5.0.1", | ||
"ts-node": "8.10.2", | ||
"ts-node": "9.0.0", | ||
"tslib": "2.0.1", | ||
"typescript": "3.9.7", | ||
"@typescript-eslint/eslint-plugin": "3.9.0", | ||
"@typescript-eslint/parser": "3.9.0", | ||
"eslint": "7.7.0", | ||
"typescript": "4.0.2", | ||
"@typescript-eslint/eslint-plugin": "4.0.1", | ||
"@typescript-eslint/parser": "4.0.1", | ||
"eslint": "7.8.1", | ||
"eslint-config-google": "0.14.0", | ||
@@ -45,0 +45,0 @@ "eslint-plugin-import": "2.22.0" |
{ | ||
"extends": ["config:base"], | ||
"schedule": ["every weekend"], | ||
"schedule": ["before 5am on Saturday"], | ||
"packageRules": [{ | ||
"packagePatterns": ["eslint"], | ||
"groupName": "lint", | ||
"automerge": true, | ||
"automergeType": "branch" | ||
}, { | ||
"packagePatterns": ["^@mathigon"], | ||
"groupName": "mathigon", | ||
"automerge": true, | ||
"automergeType": "branch" | ||
}, { | ||
"packagePatterns": ["ts-node", "^typescript"], | ||
"groupName": "typescript", | ||
"automerge": true, | ||
"automergeType": "branch" | ||
}, { | ||
"packagePatterns": ["^@types/"], | ||
"groupName": "types", | ||
"automerge": true, | ||
"automergeType": "branch" | ||
}, { | ||
"packagePatterns": ["^rollup", "^@rollup"], | ||
"groupName": "rollup", | ||
"automerge": true, | ||
"automergeType": "branch" | ||
}, { | ||
"updateTypes": ["patch", "pin", "digest"], | ||
"automerge": true | ||
}, | ||
{ | ||
"packagePatterns": ["eslint", "^@types"], | ||
"automerge": true | ||
"groupName": "versions", | ||
"automerge": true, | ||
"automergeType": "branch" | ||
}] | ||
} |
@@ -14,5 +14,10 @@ // ============================================================================= | ||
/** Parses a string to an expression. */ | ||
function parse(str: string, collapse = false) { | ||
const expr = matchBrackets(tokenize(str)); | ||
/** | ||
* Parses a string to an expression. | ||
* | ||
* If `context` is supplied, interpret `f(a+b)` as `f*(a+b)` if `f` is in | ||
* `context.variables`. | ||
*/ | ||
function parse(str: string, collapse = false, context?: {variables?: string[]}) { | ||
const expr = matchBrackets(tokenize(str), context); | ||
return collapse ? expr.collapse() : expr; | ||
@@ -19,0 +24,0 @@ } |
@@ -178,5 +178,10 @@ // ============================================================================= | ||
export function matchBrackets(tokens: ExprElement[]) { | ||
export function matchBrackets(tokens: ExprElement[], context?: {variables?: string[]}) { | ||
const stack: ExprElement[][] = [[]]; | ||
// When these identifiers appear immediately before parenthesis, like x(y), | ||
// they will be treated as variables with implicit multiplication, rather | ||
// than a custom function call. | ||
const safeVariables = ['π', ...(context?.variables || [])]; | ||
for (const t of tokens) { | ||
@@ -194,7 +199,6 @@ const lastOpen = last(stack).length ? (last(stack)[0] as ExprOperator).o : undefined; | ||
// Check if this is a normal bracket, or a function call. | ||
// Terms like x(y) are treated as functions, rather than implicit | ||
// multiplication, except for π(y). | ||
const isFn = (isOperator(t, ')') && last(term) instanceof ExprIdentifier && | ||
(last(term) as ExprIdentifier).i !== 'π'); | ||
const lastTerm = last(term); | ||
const isFn = isOperator(t, ')') && lastTerm instanceof ExprIdentifier && | ||
!safeVariables.includes(lastTerm.i); | ||
const fnName = isFn ? (term.pop() as ExprIdentifier).i : (closed![0] as ExprOperator).o; | ||
@@ -201,0 +205,0 @@ |
@@ -88,1 +88,16 @@ // ============================================================================= | ||
}); | ||
tape('extract functions and variables', (test) => { | ||
const terms = expr('x * f(a+b)').collapse(); | ||
test.same(terms.functions, ['×', 'f', '+']); | ||
test.same(terms.variables, ['x', 'a', 'b']); | ||
test.end(); | ||
}); | ||
tape('context', (test) => { | ||
const solution = expr('2x*(a+b)').collapse(); | ||
const context = {variables: solution.variables}; | ||
const student = Expression.parse('2x(a+b)', false, context).collapse(); | ||
test.equals(student.toString(), solution.toString()); | ||
test.end(); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
505835
25
13848