-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add information about node's original location in the parsed string #3557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
f69808d
1efd653
d3427ea
34ec91e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,10 +39,11 @@ tree generated by `math.parse('sqrt(2 + x)')`. | |
|
|
||
| All nodes have the following methods: | ||
|
|
||
| - `clone() : Node` | ||
| - `clone(options: MetaOptions) : Node` | ||
|
|
||
| Create a shallow clone of the node. | ||
| The node itself is cloned, its childs are not cloned. | ||
| The node itself is cloned, its childs are not cloned. | ||
| Information on available options can be found at [Type Definitions](expression_trees.md#type-definitions) | ||
|
|
||
| - `cloneDeep() : Node` | ||
|
|
||
|
|
@@ -263,7 +264,10 @@ Each `Node` has the following properties: | |
| - `type: string` | ||
|
|
||
| The type of the node, for example `'SymbolNode'` in case of a `SymbolNode`. | ||
|
|
||
|
|
||
| - `sources: SourceMapping[]` | ||
| An array of sources mapping this node back to its tokens in the parsed string. | ||
| The exact mapping will depend on the type of node and is listed in more detail for each node below. | ||
|
|
||
| ## Nodes | ||
|
|
||
|
|
@@ -276,14 +280,15 @@ namespace `math`. | |
| Construction: | ||
|
|
||
| ``` | ||
| new AccessorNode(object: Node, index: IndexNode) | ||
| new AccessorNode(object: Node, index: IndexNode, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `object: Node` | ||
| - `index: IndexNode` | ||
| - `name: string` (read-only) The function or method name. Returns an empty string when undefined. | ||
| - `sources: SourceMapping[]` mappings to tokens defining this accessor. This will be `[` and `]` for array accessors, and `.` for dot notation accessors. | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -302,12 +307,13 @@ const node2 = new math.AccessorNode(object, index) | |
| Construction: | ||
|
|
||
| ``` | ||
| new ArrayNode(items: Node[]) | ||
| new ArrayNode(items: Node[], meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `items: Node[]` | ||
| - `sources: SourceMapping[]` mappings to the `[`, `]`, `,`, and `;` used to define this array in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -326,8 +332,8 @@ const node2 = new math.ArrayNode([one, two, three]) | |
| Construction: | ||
|
|
||
| ``` | ||
| new AssignmentNode(object: SymbolNode, value: Node) | ||
| new AssignmentNode(object: SymbolNode | AccessorNode, index: IndexNode, value: Node) | ||
| new AssignmentNode(object: SymbolNode, value: Node, meta: MetaOptions) | ||
| new AssignmentNode(object: SymbolNode | AccessorNode, index: IndexNode, value: Node, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
@@ -336,6 +342,7 @@ Properties: | |
| - `index: IndexNode | null` | ||
| - `value: Node` | ||
| - `name: string` (read-only) The function or method name. Returns an empty string when undefined. | ||
| - `sources: SourceMapping[]` mapping to the `=` defining this assignment node in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -359,12 +366,13 @@ a semicolon). | |
| Construction: | ||
|
|
||
| ``` | ||
| block = new BlockNode(Array.<{node: Node} | {node: Node, visible: boolean}>) | ||
| block = new BlockNode(Array.<{node: Node} | {node: Node, visible: boolean}>, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `blocks: Array.<{node: Node, visible: boolean}>` | ||
| - `sources: SourceMapping[]` mappings to each `;` token delimiting blocks in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -396,14 +404,15 @@ const block2 = new BlockNode([ | |
| Construction: | ||
|
|
||
| ``` | ||
| new ConditionalNode(condition: Node, trueExpr: Node, falseExpr: Node) | ||
| new ConditionalNode(condition: Node, trueExpr: Node, falseExpr: Node, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `condition: Node` | ||
| - `trueExpr: Node` | ||
| - `falseExpr: Node` | ||
| - `sources: SourceMapping[]` mappings to the `?`, and `:` tokens defining this conditional in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -423,12 +432,13 @@ const node2 = new math.ConditionalNode(condition, trueExpr, falseExpr) | |
| Construction: | ||
|
|
||
| ``` | ||
| new ConstantNode(value: *) | ||
| new ConstantNode(value: *, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `value: *` | ||
| - `sources: SourceMapping[]` mapping to the token representing the constant in the parsed string. | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -445,14 +455,15 @@ const node3 = new math.ConstantNode('foo') | |
| Construction: | ||
|
|
||
| ``` | ||
| new FunctionAssignmentNode(name: string, params: string[], expr: Node) | ||
| new FunctionAssignmentNode(name: string, params: string[], expr: Node, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `name: string` | ||
| - `params: string[]` | ||
| - `expr: Node` | ||
| - `sources: SourceMapping[]` mapping to the `=` for this assignment in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -471,13 +482,14 @@ const node2 = new math.FunctionAssignmentNode('f', ['x'], expr) | |
| Construction: | ||
|
|
||
| ``` | ||
| new FunctionNode(fn: Node | string, args: Node[]) | ||
| new FunctionNode(fn: Node | string, args: Node[], meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `fn: Node | string` (read-only) The object or function name which to invoke. | ||
| - `args: Node[]` | ||
| - `sources: SourceMapping[]` mappings to the `(` and `)` defining this function, as well as any `,` delimiting its parameters. | ||
|
|
||
| Static functions: | ||
|
|
||
|
|
@@ -499,8 +511,8 @@ const node3 = new math.FunctionNode(new SymbolNode('sqrt'), [four]) | |
| Construction: | ||
|
|
||
| ``` | ||
| new IndexNode(dimensions: Node[]) | ||
| new IndexNode(dimensions: Node[], dotNotation: boolean) | ||
| new IndexNode(dimensions: Node[], meta: MetaOptions) | ||
| new IndexNode(dimensions: Node[], dotNotation: boolean, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Each dimension can be a single value, a range, or a property. The values of | ||
|
|
@@ -515,6 +527,7 @@ Properties: | |
|
|
||
| - `dimensions: Node[]` | ||
| - `dotNotation: boolean` | ||
| - `sources: SourceMapping[]` mappings to `,` delimiting items in an array index. If `dotNotation = true`, this will map to the constant following the `.` instead. | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -536,12 +549,13 @@ const node2 = new math.AccessorNode(A, index) | |
| Construction: | ||
|
|
||
| ``` | ||
| new ObjectNode(properties: Object.<string, Node>) | ||
| new ObjectNode(properties: Object.<string, Node>, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `properties: Object.<string, Node>` | ||
| - `sources: SourceMapping[]` mappings to the `{`, `}`, `:`, and `,` tokens defining this object in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -560,7 +574,7 @@ const node2 = new math.ObjectNode({a: a, b: b, c: c}) | |
| Construction: | ||
|
|
||
| ``` | ||
| new OperatorNode(op: string, fn: string, args: Node[], implicit: boolean = false) | ||
| new OperatorNode(op: string, fn: string, args: Node[], implicit: boolean = false, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Additional methods: | ||
|
|
@@ -594,6 +608,7 @@ Properties: | |
| - `fn: string` | ||
| - `args: Node[]` | ||
| - `implicit: boolean` True in case of an implicit multiplication, false otherwise | ||
| - `sources: SourceMapping[]` mapping to the `+` or `-` defining this unary operator in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -610,12 +625,13 @@ const node2 = new math.OperatorNode('+', 'add', [a, b]) | |
| Construction: | ||
|
|
||
| ``` | ||
| new ParenthesisNode(content: Node) | ||
| new ParenthesisNode(content: Node, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `content: Node` | ||
| - `sources: SourceMapping[]` mappings to the `(` and `)` for this node in the parsed string | ||
|
|
||
| Examples: | ||
|
|
||
|
|
@@ -631,15 +647,16 @@ const node2 = new math.ParenthesisNode(a) | |
| Construction: | ||
|
|
||
| ``` | ||
| new RangeNode(start: Node, end: Node [, step: Node]) | ||
| new RangeNode(start: Node, end: Node [, step: Node], meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `start: Node` | ||
| - `end: Node` | ||
| - `step: Node | null` | ||
|
|
||
| - `sources: SourceMapping[]` mappings to the `:` defining this range node in the parsed string. There will be 1 or 2 mappings, depending on whether step size was defined for the range | ||
|
|
||
| Examples: | ||
|
|
||
| ```js | ||
|
|
@@ -660,7 +677,7 @@ const node4 = new math.RangeNode(zero, ten, two) | |
| Construction: | ||
|
|
||
| ``` | ||
| new RelationalNode(conditionals: string[], params: Node[]) | ||
| new RelationalNode(conditionals: string[], params: Node[], meta: MetaOptions) | ||
| ``` | ||
|
|
||
| `conditionals` is an array of strings, each of which may be 'smaller', 'larger', 'smallerEq', 'largerEq', 'equal', or 'unequal'. The `conditionals` array must contain exactly one fewer item than `params`. | ||
|
|
@@ -669,6 +686,7 @@ Properties: | |
|
|
||
| - `conditionals: string[]` | ||
| - `params: Node[]` | ||
| - `sources: SourceMapping[]` mappings to the relational symbol `<`, `>`, `==`, `>=`, or `<=` defining this node in the parsed string. This may include multiple mappings if multiple relationals are chained: `10 < x < 20` | ||
|
|
||
| A `RelationalNode` efficiently represents a chained conditional expression with two or more comparison operators, such as `10 < x <= 50`. The expression is equivalent to `10 < x and x <= 50`, except that `x` is evaluated only once, and evaluation stops (is "short-circuited") once any condition tests false. Operators that are subject to chaining are `<`, `>`, `<=`, `>=`, `==`, and `!=`. For backward compatibility, `math.parse` will return an `OperatorNode` if only a single conditional is present (such as `x > 2`). | ||
|
|
||
|
|
@@ -690,12 +708,13 @@ const node2 = math.parse('10 < x <= 50') | |
| Construction: | ||
|
|
||
| ``` | ||
| new SymbolNode(name: string) | ||
| new SymbolNode(name: string, meta: MetaOptions) | ||
| ``` | ||
|
|
||
| Properties: | ||
|
|
||
| - `name: string` | ||
| - `sources: SourceMapping[]` a single mapping to the symbol defining this node in the parsed string. The text will match whatever symbol is defined. | ||
|
|
||
| Static functions: | ||
|
|
||
|
|
@@ -709,3 +728,25 @@ const node = math.parse('x') | |
|
|
||
| const x = new math.SymbolNode('x') | ||
| ``` | ||
|
|
||
| ## Type Definitions | ||
|
|
||
| A few node methods and properties have complex object structures as their parameters or return types. They are: | ||
|
|
||
| ### MetaOptions | ||
|
|
||
| This object is passed as a final parameter in the constructor of any node, or as the parameter when calling `clone()`. | ||
|
|
||
| Properties: | ||
|
|
||
| - `sources: SourceMapping` sets the sources for the newly created or cloned node | ||
|
|
||
| ### SourceMapping | ||
|
|
||
| Each node has an array of `SourceMapping` objects which map back to the node's corresponding tokens in the original source string | ||
|
|
||
| Properties: | ||
|
|
||
| - `text: string` the token representing this node in the parsed string | ||
| - `index; number` the index of the token in the parsed string | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Small typo, I think the semicolon All is all well documented BTW 👍 |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,5 +33,12 @@ export const DEFAULT_CONFIG = { | |
| // legacy behavior for matrix subset. When true, the subset function | ||
| // returns a matrix or array with the same size as the index (except for scalars). | ||
| // When false, it returns a matrix or array with a size depending on the type of index. | ||
| legacySubset: false | ||
| legacySubset: false, | ||
|
|
||
| // If set to `true` (the default value), `parse` records information about | ||
| // the original source location of each `Node` in the parsed string. See `SourceMapping` and `Node#sources`. | ||
| // If set to `false`, `Node#sources` is always be empty. | ||
| // The only time you want to set this to `false` is when you want to speed up parsing of | ||
| // a large amount of text. | ||
| traceSources: true | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,8 @@ export function configFactory (config, emit) { | |
| * {string} randomSeed | ||
| * Random seed for seeded pseudo random number generator. | ||
| * Set to null to randomly seed. | ||
| * {boolean} traceSources | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you document this new configuration option |
||
| * Enables node's source tracing in the parsed string. Slows down parsing a bit. | ||
| * @return {Object} Returns the current configuration | ||
| */ | ||
| function _config (options) { | ||
|
|
@@ -71,6 +73,11 @@ export function configFactory (config, emit) { | |
| validateOption(options, 'matrix', MATRIX_OPTIONS) | ||
| validateOption(options, 'number', NUMBER_OPTIONS) | ||
|
|
||
| if (options.traceSources !== undefined) { | ||
| if (typeof options.traceSources !== 'boolean') { | ||
| console.warn('Warning: The configuration option "traceSources" must be a boolean.') | ||
| } | ||
| } | ||
| // merge options | ||
| deepExtend(config, options) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ import { | |
| import { getSafeProperty } from '../../utils/customs.js' | ||
| import { factory } from '../../utils/factory.js' | ||
| import { accessFactory } from './utils/access.js' | ||
| import { defaultMetaOptions } from './Node.js' | ||
|
|
||
| const name = 'AccessorNode' | ||
| const dependencies = [ | ||
|
|
@@ -47,9 +48,10 @@ export const createAccessorNode = /* #__PURE__ */ factory(name, dependencies, ({ | |
| * @param {Node} object The object from which to retrieve | ||
| * a property or subset. | ||
| * @param {IndexNode} index IndexNode containing ranges | ||
| * @param {MetaOptions} [meta] The object with additional options for building this node. | ||
| */ | ||
| constructor (object, index) { | ||
| super() | ||
| constructor (object, index, meta = defaultMetaOptions) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thinking aloud here: technically it is not needed to define a default value for |
||
| super(meta) | ||
| if (!isNode(object)) { | ||
| throw new TypeError('Node expected for parameter "object"') | ||
| } | ||
|
|
@@ -133,10 +135,11 @@ export const createAccessorNode = /* #__PURE__ */ factory(name, dependencies, ({ | |
|
|
||
| /** | ||
| * Create a clone of this node, a shallow copy | ||
| * @param {MetaOptions} [meta] An object with additional options for cloning this node | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a more clear explanation would be:
What do you think? |
||
| * @return {AccessorNode} | ||
| */ | ||
| clone () { | ||
| return new AccessorNode(this.object, this.index) | ||
| clone (meta) { | ||
| return new AccessorNode(this.object, this.index, meta ?? { sources: this.sources }) | ||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
optionsargument is optional, and it is namedmetain the source code (consistent with the constructor arguments of the Node classes). Can you document this likeclone(meta?: MetaOptions) : Node?And similarly, the argument
metais optional in the constructors of each of the Node classes, can you udpate that too in this documentation page?