parse assignment
This commit is contained in:
parent
a5bb390370
commit
84f3420369
|
@ -7,17 +7,13 @@ open Expect
|
||||||
let expectParseToBe = (expr, answer) =>
|
let expectParseToBe = (expr, answer) =>
|
||||||
Parse.parse(expr)->Result.flatMap(Parse.castNodeType)->Parse.toStringResult->expect->toBe(answer)
|
Parse.parse(expr)->Result.flatMap(Parse.castNodeType)->Parse.toStringResult->expect->toBe(answer)
|
||||||
|
|
||||||
let testParse = (expr, answer) =>
|
let testParse = (expr, answer) => test(expr, () => expectParseToBe(expr, answer))
|
||||||
test(expr, () => expectParseToBe(expr, answer))
|
|
||||||
|
|
||||||
let testDescParse = (desc, expr, answer) =>
|
let testDescParse = (desc, expr, answer) => test(desc, () => expectParseToBe(expr, answer))
|
||||||
test(desc, () => expectParseToBe(expr, answer))
|
|
||||||
|
|
||||||
let skipTestParse = (expr, answer) =>
|
let skipTestParse = (expr, answer) => Skip.test(expr, () => expectParseToBe(expr, answer))
|
||||||
Skip.test(expr, () => expectParseToBe(expr, answer))
|
|
||||||
|
|
||||||
let skipDescTestParse = (desc, expr, answer) =>
|
let skipDescTestParse = (desc, expr, answer) => Skip.test(desc, () => expectParseToBe(expr, answer))
|
||||||
Skip.test(desc, () => expectParseToBe(expr, answer))
|
|
||||||
|
|
||||||
describe("MathJs parse", () => {
|
describe("MathJs parse", () => {
|
||||||
describe("literals operators paranthesis", () => {
|
describe("literals operators paranthesis", () => {
|
||||||
|
@ -31,7 +27,7 @@ describe("MathJs parse", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("variables", () => {
|
describe("variables", () => {
|
||||||
skipTestParse("x = 1", "???")
|
testParse("x = 1", "x = 1")
|
||||||
skipTestParse("x", "???")
|
skipTestParse("x", "???")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ type errorValue =
|
||||||
| REFunctionExpected(string)
|
| REFunctionExpected(string)
|
||||||
| REJavaScriptExn(option<string>, option<string>) // Javascript Exception
|
| REJavaScriptExn(option<string>, option<string>) // Javascript Exception
|
||||||
| RERecordPropertyNotFound(string, string)
|
| RERecordPropertyNotFound(string, string)
|
||||||
|
| RESyntaxError(string)
|
||||||
| RETodo(string) // To do
|
| RETodo(string) // To do
|
||||||
|
|
||||||
type t = errorValue
|
type t = errorValue
|
||||||
|
@ -24,5 +25,6 @@ let errorToString = err =>
|
||||||
answer
|
answer
|
||||||
}
|
}
|
||||||
| RERecordPropertyNotFound(msg, index) => `${msg}: ${index}`
|
| RERecordPropertyNotFound(msg, index) => `${msg}: ${index}`
|
||||||
|
| RESyntaxError(desc) => `Syntax Error: ${desc}`
|
||||||
| RETodo(msg) => `TODO: ${msg}`
|
| RETodo(msg) => `TODO: ${msg}`
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ open Reducer_ErrorValue
|
||||||
|
|
||||||
type node = {"type": string, "isNode": bool, "comment": string}
|
type node = {"type": string, "isNode": bool, "comment": string}
|
||||||
type arrayNode = {...node, "items": array<node>}
|
type arrayNode = {...node, "items": array<node>}
|
||||||
//assignmentNode
|
|
||||||
//blockNode
|
//blockNode
|
||||||
//conditionalNode
|
//conditionalNode
|
||||||
type constantNode = {...node, "value": unit}
|
type constantNode = {...node, "value": unit}
|
||||||
|
@ -23,9 +22,15 @@ type parenthesisNode = {...node, "content": node}
|
||||||
//rangeNode
|
//rangeNode
|
||||||
//relationalNode
|
//relationalNode
|
||||||
type symbolNode = {...node, "name": string}
|
type symbolNode = {...node, "name": string}
|
||||||
|
type assignmentNode = {...node, "object": symbolNode, "value": node}
|
||||||
|
type assignmentNodeWAccessor = {...node, "object": accessorNode, "value": node}
|
||||||
|
type assignmentNodeWIndex = {...assignmentNodeWAccessor, "index": Js.null<indexNode>}
|
||||||
|
|
||||||
external castAccessorNode: node => accessorNode = "%identity"
|
external castAccessorNode: node => accessorNode = "%identity"
|
||||||
external castArrayNode: node => arrayNode = "%identity"
|
external castArrayNode: node => arrayNode = "%identity"
|
||||||
|
external castAssignmentNode: node => assignmentNode = "%identity"
|
||||||
|
external castAssignmentNodeWAccessor: node => assignmentNodeWAccessor = "%identity"
|
||||||
|
external castAssignmentNodeWIndex: node => assignmentNodeWIndex = "%identity"
|
||||||
external castConstantNode: node => constantNode = "%identity"
|
external castConstantNode: node => constantNode = "%identity"
|
||||||
external castFunctionNode: node => functionNode = "%identity"
|
external castFunctionNode: node => functionNode = "%identity"
|
||||||
external castIndexNode: node => indexNode = "%identity"
|
external castIndexNode: node => indexNode = "%identity"
|
||||||
|
@ -50,6 +55,7 @@ let parse = (expr: string): result<node, errorValue> =>
|
||||||
type mathJsNode =
|
type mathJsNode =
|
||||||
| MjAccessorNode(accessorNode)
|
| MjAccessorNode(accessorNode)
|
||||||
| MjArrayNode(arrayNode)
|
| MjArrayNode(arrayNode)
|
||||||
|
| MjAssignmentNode(assignmentNode)
|
||||||
| MjConstantNode(constantNode)
|
| MjConstantNode(constantNode)
|
||||||
| MjFunctionNode(functionNode)
|
| MjFunctionNode(functionNode)
|
||||||
| MjIndexNode(indexNode)
|
| MjIndexNode(indexNode)
|
||||||
|
@ -58,10 +64,20 @@ type mathJsNode =
|
||||||
| MjParenthesisNode(parenthesisNode)
|
| MjParenthesisNode(parenthesisNode)
|
||||||
| MjSymbolNode(symbolNode)
|
| MjSymbolNode(symbolNode)
|
||||||
|
|
||||||
let castNodeType = (node: node) =>
|
let castNodeType = (node: node) => {
|
||||||
|
let decideAssignmentNode = node => {
|
||||||
|
let iNode = node->castAssignmentNodeWIndex
|
||||||
|
if Js.Null.test(iNode["index"]) && iNode["object"]["type"] == "SymbolNode" {
|
||||||
|
node->castAssignmentNode->MjAssignmentNode->Ok
|
||||||
|
} else {
|
||||||
|
RESyntaxError("Assignment to index or property not supported")->Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch node["type"] {
|
switch node["type"] {
|
||||||
| "AccessorNode" => node->castAccessorNode->MjAccessorNode->Ok
|
| "AccessorNode" => node->castAccessorNode->MjAccessorNode->Ok
|
||||||
| "ArrayNode" => node->castArrayNode->MjArrayNode->Ok
|
| "ArrayNode" => node->castArrayNode->MjArrayNode->Ok
|
||||||
|
| "AssignmentNode" => node->decideAssignmentNode
|
||||||
| "ConstantNode" => node->castConstantNode->MjConstantNode->Ok
|
| "ConstantNode" => node->castConstantNode->MjConstantNode->Ok
|
||||||
| "FunctionNode" => node->castFunctionNode->MjFunctionNode->Ok
|
| "FunctionNode" => node->castFunctionNode->MjFunctionNode->Ok
|
||||||
| "IndexNode" => node->castIndexNode->MjIndexNode->Ok
|
| "IndexNode" => node->castIndexNode->MjIndexNode->Ok
|
||||||
|
@ -71,6 +87,7 @@ let castNodeType = (node: node) =>
|
||||||
| "SymbolNode" => node->castSymbolNode->MjSymbolNode->Ok
|
| "SymbolNode" => node->castSymbolNode->MjSymbolNode->Ok
|
||||||
| _ => RETodo(`Argg, unhandled MathJsNode: ${node["type"]}`)->Error
|
| _ => RETodo(`Argg, unhandled MathJsNode: ${node["type"]}`)->Error
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let rec toString = (mathJsNode: mathJsNode): string => {
|
let rec toString = (mathJsNode: mathJsNode): string => {
|
||||||
let toStringValue = (a: 'a): string =>
|
let toStringValue = (a: 'a): string =>
|
||||||
|
@ -89,7 +106,8 @@ let rec toString = (mathJsNode: mathJsNode): string => {
|
||||||
let toStringFunctionNode = (fnode: functionNode): string =>
|
let toStringFunctionNode = (fnode: functionNode): string =>
|
||||||
`${fnode["fn"]}(${fnode["args"]->toStringNodeArray})`
|
`${fnode["fn"]}(${fnode["args"]->toStringNodeArray})`
|
||||||
|
|
||||||
let toStringObjectEntry = ((key: string, value: node)): string => `${key}: ${value->toStringMathJsNode}`
|
let toStringObjectEntry = ((key: string, value: node)): string =>
|
||||||
|
`${key}: ${value->toStringMathJsNode}`
|
||||||
|
|
||||||
let toStringObjectNode = (oNode: objectNode): string =>
|
let toStringObjectNode = (oNode: objectNode): string =>
|
||||||
`{${oNode["properties"]
|
`{${oNode["properties"]
|
||||||
|
@ -103,16 +121,21 @@ let rec toString = (mathJsNode: mathJsNode): string => {
|
||||||
->Belt.Array.map(each => toStringResult(each->castNodeType))
|
->Belt.Array.map(each => toStringResult(each->castNodeType))
|
||||||
->Js.String.concatMany("")
|
->Js.String.concatMany("")
|
||||||
|
|
||||||
|
let toStringSymbolNode = (sNode: symbolNode): string => sNode["name"]
|
||||||
|
|
||||||
switch mathJsNode {
|
switch mathJsNode {
|
||||||
| MjAccessorNode(aNode) => `${aNode["object"]->toStringMathJsNode}[${aNode["index"]->toStringIndexNode}]`
|
| MjAccessorNode(aNode) =>
|
||||||
|
`${aNode["object"]->toStringMathJsNode}[${aNode["index"]->toStringIndexNode}]`
|
||||||
| MjArrayNode(aNode) => `[${aNode["items"]->toStringNodeArray}]`
|
| MjArrayNode(aNode) => `[${aNode["items"]->toStringNodeArray}]`
|
||||||
|
| MjAssignmentNode(aNode) =>
|
||||||
|
`${aNode["object"]->toStringSymbolNode} = ${aNode["value"]->toStringMathJsNode}`
|
||||||
| MjConstantNode(cNode) => cNode["value"]->toStringValue
|
| MjConstantNode(cNode) => cNode["value"]->toStringValue
|
||||||
| MjFunctionNode(fNode) => fNode->toStringFunctionNode
|
| MjFunctionNode(fNode) => fNode->toStringFunctionNode
|
||||||
| MjIndexNode(iNode) => iNode->toStringIndexNode
|
| MjIndexNode(iNode) => iNode->toStringIndexNode
|
||||||
| MjObjectNode(oNode) => oNode->toStringObjectNode
|
| MjObjectNode(oNode) => oNode->toStringObjectNode
|
||||||
| MjOperatorNode(opNode) => opNode->castOperatorNodeToFunctionNode->toStringFunctionNode
|
| MjOperatorNode(opNode) => opNode->castOperatorNodeToFunctionNode->toStringFunctionNode
|
||||||
| MjParenthesisNode(pNode) => `(${toStringMathJsNode(pNode["content"])})`
|
| MjParenthesisNode(pNode) => `(${toStringMathJsNode(pNode["content"])})`
|
||||||
| MjSymbolNode(sNode) => sNode["name"]
|
| MjSymbolNode(sNode) => sNode->toStringSymbolNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
and toStringResult = (rMathJsNode: result<mathJsNode, errorValue>): string =>
|
and toStringResult = (rMathJsNode: result<mathJsNode, errorValue>): string =>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user