wyreframe 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +195 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
- package/src/parser/Core/Bounds.mjs +61 -0
- package/src/parser/Core/Bounds.res +65 -0
- package/src/parser/Core/Grid.mjs +268 -0
- package/src/parser/Core/Grid.res +265 -0
- package/src/parser/Core/Position.mjs +83 -0
- package/src/parser/Core/Position.res +54 -0
- package/src/parser/Core/Types.mjs +435 -0
- package/src/parser/Core/Types.res +331 -0
- package/src/parser/Core/__tests__/Bounds_test.mjs +326 -0
- package/src/parser/Core/__tests__/Bounds_test.res +412 -0
- package/src/parser/Core/__tests__/Grid_test.mjs +322 -0
- package/src/parser/Core/__tests__/Grid_test.res +319 -0
- package/src/parser/Core/__tests__/Types_test.mjs +614 -0
- package/src/parser/Core/__tests__/Types_test.res +650 -0
- package/src/parser/Detector/BoxTracer.mjs +302 -0
- package/src/parser/Detector/BoxTracer.res +374 -0
- package/src/parser/Detector/HierarchyBuilder.mjs +158 -0
- package/src/parser/Detector/HierarchyBuilder.res +315 -0
- package/src/parser/Detector/ShapeDetector.mjs +134 -0
- package/src/parser/Detector/ShapeDetector.res +236 -0
- package/src/parser/Detector/__tests__/BoxTracer_test.mjs +70 -0
- package/src/parser/Detector/__tests__/BoxTracer_test.res +92 -0
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +489 -0
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +849 -0
- package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +377 -0
- package/src/parser/Detector/__tests__/ShapeDetector_test.res +563 -0
- package/src/parser/Errors/ErrorContext.mjs +106 -0
- package/src/parser/Errors/ErrorContext.res +191 -0
- package/src/parser/Errors/ErrorMessages.mjs +289 -0
- package/src/parser/Errors/ErrorMessages.res +303 -0
- package/src/parser/Errors/ErrorTypes.mjs +105 -0
- package/src/parser/Errors/ErrorTypes.res +169 -0
- package/src/parser/Interactions/InteractionMerger.mjs +266 -0
- package/src/parser/Interactions/InteractionMerger.res +450 -0
- package/src/parser/Interactions/InteractionParser.mjs +88 -0
- package/src/parser/Interactions/InteractionParser.res +127 -0
- package/src/parser/Interactions/SimpleInteractionParser.mjs +278 -0
- package/src/parser/Interactions/SimpleInteractionParser.res +262 -0
- package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +576 -0
- package/src/parser/Interactions/__tests__/InteractionMerger_test.res +646 -0
- package/src/parser/Parser.gen.tsx +96 -0
- package/src/parser/Parser.mjs +212 -0
- package/src/parser/Parser.res +481 -0
- package/src/parser/Scanner/__tests__/Grid_manual.mjs +214 -0
- package/src/parser/Scanner/__tests__/Grid_manual.res +141 -0
- package/src/parser/Semantic/ASTBuilder.mjs +197 -0
- package/src/parser/Semantic/ASTBuilder.res +288 -0
- package/src/parser/Semantic/AlignmentCalc.mjs +41 -0
- package/src/parser/Semantic/AlignmentCalc.res +104 -0
- package/src/parser/Semantic/Elements/ButtonParser.mjs +58 -0
- package/src/parser/Semantic/Elements/ButtonParser.res +131 -0
- package/src/parser/Semantic/Elements/CheckboxParser.mjs +58 -0
- package/src/parser/Semantic/Elements/CheckboxParser.res +79 -0
- package/src/parser/Semantic/Elements/CodeTextParser.mjs +50 -0
- package/src/parser/Semantic/Elements/CodeTextParser.res +111 -0
- package/src/parser/Semantic/Elements/ElementParser.mjs +15 -0
- package/src/parser/Semantic/Elements/ElementParser.res +83 -0
- package/src/parser/Semantic/Elements/EmphasisParser.mjs +46 -0
- package/src/parser/Semantic/Elements/EmphasisParser.res +67 -0
- package/src/parser/Semantic/Elements/InputParser.mjs +41 -0
- package/src/parser/Semantic/Elements/InputParser.res +97 -0
- package/src/parser/Semantic/Elements/LinkParser.mjs +60 -0
- package/src/parser/Semantic/Elements/LinkParser.res +156 -0
- package/src/parser/Semantic/Elements/TextParser.mjs +19 -0
- package/src/parser/Semantic/Elements/TextParser.res +42 -0
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +189 -0
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +257 -0
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +202 -0
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +250 -0
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +293 -0
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +134 -0
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +253 -0
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +304 -0
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +289 -0
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +402 -0
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +149 -0
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +167 -0
- package/src/parser/Semantic/ParserRegistry.mjs +82 -0
- package/src/parser/Semantic/ParserRegistry.res +145 -0
- package/src/parser/Semantic/SemanticParser.mjs +850 -0
- package/src/parser/Semantic/SemanticParser.res +1368 -0
- package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +187 -0
- package/src/parser/Semantic/__tests__/ASTBuilder_test.res +192 -0
- package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +154 -0
- package/src/parser/Semantic/__tests__/ParserRegistry_test.res +191 -0
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +768 -0
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +1069 -0
- package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +1329 -0
- package/src/parser/Semantic/__tests__/SemanticParser_manual.res +544 -0
- package/src/parser/TestMain.mjs +21 -0
- package/src/parser/TestMain.res +14 -0
- package/src/parser/TextExtractor.mjs +179 -0
- package/src/parser/TextExtractor.res +264 -0
- package/src/parser/__tests__/GridScanner_integration.test.mjs +632 -0
- package/src/parser/__tests__/GridScanner_integration.test.res +816 -0
- package/src/parser/__tests__/Performance.test.mjs +244 -0
- package/src/parser/__tests__/Performance.test.res +371 -0
- package/src/parser/__tests__/PerformanceFixtures.mjs +200 -0
- package/src/parser/__tests__/PerformanceFixtures.res +284 -0
- package/src/parser/__tests__/WyreframeParser_integration.test.mjs +770 -0
- package/src/parser/__tests__/WyreframeParser_integration.test.res +1008 -0
- package/src/parser/__tests__/fixtures/alignment-test.txt +9 -0
- package/src/parser/__tests__/fixtures/all-elements.txt +16 -0
- package/src/parser/__tests__/fixtures/login-scene.txt +17 -0
- package/src/parser/__tests__/fixtures/multi-scene.txt +25 -0
- package/src/parser/__tests__/fixtures/nested-boxes.txt +15 -0
- package/src/parser/__tests__/fixtures/simple-box.txt +5 -0
- package/src/parser/__tests__/fixtures/with-dividers.txt +14 -0
- package/src/renderer/Renderer.gen.tsx +32 -0
- package/src/renderer/Renderer.mjs +391 -0
- package/src/renderer/Renderer.res +558 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Types from "../Core/Types.mjs";
|
|
4
|
+
import * as Core__Int from "@rescript/core/src/Core__Int.mjs";
|
|
5
|
+
import * as Core__Option from "@rescript/core/src/Core__Option.mjs";
|
|
6
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
7
|
+
import * as SimpleInteractionParser from "./SimpleInteractionParser.mjs";
|
|
8
|
+
|
|
9
|
+
function extractPosition(message) {
|
|
10
|
+
let jsPattern = /Line (\d+)/i;
|
|
11
|
+
let result = jsPattern.exec(message);
|
|
12
|
+
if (result === null) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let lineOpt = Core__Option.flatMap(result[1], x => {
|
|
16
|
+
if (x == null) {
|
|
17
|
+
return;
|
|
18
|
+
} else {
|
|
19
|
+
return Primitive_option.some(x);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
if (lineOpt === undefined) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
let line = Core__Int.fromString(lineOpt, undefined);
|
|
26
|
+
if (line !== undefined) {
|
|
27
|
+
return Types.Position.make(line - 1 | 0, 0);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parse(input) {
|
|
32
|
+
let sceneInteractions = SimpleInteractionParser.parse(input);
|
|
33
|
+
if (sceneInteractions.TAG === "Ok") {
|
|
34
|
+
return {
|
|
35
|
+
TAG: "Ok",
|
|
36
|
+
_0: sceneInteractions._0
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
let errorMsg = sceneInteractions._0;
|
|
40
|
+
let position = extractPosition(errorMsg);
|
|
41
|
+
return {
|
|
42
|
+
TAG: "Error",
|
|
43
|
+
_0: {
|
|
44
|
+
message: errorMsg,
|
|
45
|
+
position: position
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function parseWithDetailedError(input) {
|
|
51
|
+
let result = parse(input);
|
|
52
|
+
if (result.TAG === "Ok") {
|
|
53
|
+
return {
|
|
54
|
+
TAG: "Ok",
|
|
55
|
+
_0: result._0
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
let match = result._0;
|
|
59
|
+
let position = match.position;
|
|
60
|
+
let positionStr = position !== undefined ? ` at ` + Types.Position.toString(position) : "";
|
|
61
|
+
return {
|
|
62
|
+
TAG: "Error",
|
|
63
|
+
_0: `Interaction DSL parsing failed` + positionStr + `: ` + match.message
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isValid(input) {
|
|
68
|
+
let match = parse(input);
|
|
69
|
+
return match.TAG === "Ok";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getSceneIds(sceneInteractions) {
|
|
73
|
+
return sceneInteractions.map(si => si.sceneId);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function getElementIds(sceneInteraction) {
|
|
77
|
+
return sceneInteraction.interactions.map(i => i.elementId);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
extractPosition,
|
|
82
|
+
parse,
|
|
83
|
+
parseWithDetailedError,
|
|
84
|
+
isValid,
|
|
85
|
+
getSceneIds,
|
|
86
|
+
getElementIds,
|
|
87
|
+
}
|
|
88
|
+
/* Types Not a pure module */
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InteractionParser.res
|
|
3
|
+
*
|
|
4
|
+
* Main parser module for the Interaction DSL.
|
|
5
|
+
* Uses SimpleInteractionParser for lightweight, dependency-free parsing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Error type for interaction parsing failures.
|
|
10
|
+
* Contains error message and optional position information.
|
|
11
|
+
*/
|
|
12
|
+
type parseError = {
|
|
13
|
+
message: string,
|
|
14
|
+
position: option<Types.Position.t>,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Result type for parsing operations
|
|
19
|
+
*/
|
|
20
|
+
type parseResult = result<array<Types.sceneInteractions>, parseError>
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Extract position information from an error message.
|
|
24
|
+
*
|
|
25
|
+
* Error messages may include position in the format:
|
|
26
|
+
* "Line X: ..."
|
|
27
|
+
*
|
|
28
|
+
* @param message - The error message
|
|
29
|
+
* @returns Option<Position.t> - Extracted position or None
|
|
30
|
+
*/
|
|
31
|
+
let extractPosition = (message: string): option<Types.Position.t> => {
|
|
32
|
+
let jsPattern: Js.Re.t = %re("/Line (\d+)/i")
|
|
33
|
+
|
|
34
|
+
switch Js.Re.exec_(jsPattern, message) {
|
|
35
|
+
| Some(result) => {
|
|
36
|
+
let captures = Js.Re.captures(result)
|
|
37
|
+
let lineOpt = captures->Array.get(1)->Option.flatMap(x => Js.Nullable.toOption(x))
|
|
38
|
+
|
|
39
|
+
switch lineOpt {
|
|
40
|
+
| Some(lineStr) =>
|
|
41
|
+
switch Int.fromString(lineStr) {
|
|
42
|
+
| Some(line) => Some(Types.Position.make(line - 1, 0))
|
|
43
|
+
| None => None
|
|
44
|
+
}
|
|
45
|
+
| None => None
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
| None => None
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Main parsing function for the Interaction DSL.
|
|
54
|
+
*
|
|
55
|
+
* Uses SimpleInteractionParser for lightweight parsing without external dependencies.
|
|
56
|
+
*
|
|
57
|
+
* @param input - The interaction DSL string to parse
|
|
58
|
+
* @returns Result with array of scene interactions or parse error
|
|
59
|
+
*/
|
|
60
|
+
let parse = (input: string): parseResult => {
|
|
61
|
+
switch SimpleInteractionParser.parse(input) {
|
|
62
|
+
| Ok(sceneInteractions) => Ok(sceneInteractions)
|
|
63
|
+
| Error(errorMsg) => {
|
|
64
|
+
let position = extractPosition(errorMsg)
|
|
65
|
+
Error({
|
|
66
|
+
message: errorMsg,
|
|
67
|
+
position: position,
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Convenience function that returns a more detailed error message.
|
|
75
|
+
* Useful for debugging and user-facing error displays.
|
|
76
|
+
*
|
|
77
|
+
* @param input - The interaction DSL string to parse
|
|
78
|
+
* @returns Result with detailed error information
|
|
79
|
+
*/
|
|
80
|
+
let parseWithDetailedError = (input: string): result<array<Types.sceneInteractions>, string> => {
|
|
81
|
+
switch parse(input) {
|
|
82
|
+
| Ok(result) => Ok(result)
|
|
83
|
+
| Error({message, position}) => {
|
|
84
|
+
let positionStr = switch position {
|
|
85
|
+
| Some(pos) => ` at ${Types.Position.toString(pos)}`
|
|
86
|
+
| None => ""
|
|
87
|
+
}
|
|
88
|
+
Error(`Interaction DSL parsing failed${positionStr}: ${message}`)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Validate that the input can be parsed without returning the result.
|
|
95
|
+
* Useful for validation-only scenarios.
|
|
96
|
+
*
|
|
97
|
+
* @param input - The interaction DSL string to validate
|
|
98
|
+
* @returns true if valid, false otherwise
|
|
99
|
+
*/
|
|
100
|
+
let isValid = (input: string): bool => {
|
|
101
|
+
switch parse(input) {
|
|
102
|
+
| Ok(_) => true
|
|
103
|
+
| Error(_) => false
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get all scene IDs from parsed interactions.
|
|
109
|
+
* Helper function for validation and debugging.
|
|
110
|
+
*
|
|
111
|
+
* @param sceneInteractions - Parsed scene interactions
|
|
112
|
+
* @returns Array of scene IDs
|
|
113
|
+
*/
|
|
114
|
+
let getSceneIds = (sceneInteractions: array<Types.sceneInteractions>): array<string> => {
|
|
115
|
+
sceneInteractions->Array.map(si => si.sceneId)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get all element IDs referenced in a scene's interactions.
|
|
120
|
+
* Useful for validation against the wireframe AST.
|
|
121
|
+
*
|
|
122
|
+
* @param sceneInteraction - A single scene's interactions
|
|
123
|
+
* @returns Array of element IDs
|
|
124
|
+
*/
|
|
125
|
+
let getElementIds = (sceneInteraction: Types.sceneInteractions): array<string> => {
|
|
126
|
+
sceneInteraction.interactions->Array.map(i => i.elementId)
|
|
127
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Core__Option from "@rescript/core/src/Core__Option.mjs";
|
|
4
|
+
|
|
5
|
+
let scenePattern = /^@scene:\s*(\w+)\s*$/;
|
|
6
|
+
|
|
7
|
+
let inputSelectorPattern = /^#(\w+):\s*$/;
|
|
8
|
+
|
|
9
|
+
let buttonSelectorPattern = /^\[([^\]]+)\]:\s*$/;
|
|
10
|
+
|
|
11
|
+
let linkSelectorPattern = /^\"([^\"]+)\":\s*$/;
|
|
12
|
+
|
|
13
|
+
let propertyPattern = /^\s{2}(\w+):\s*(.+?)\s*$/;
|
|
14
|
+
|
|
15
|
+
let actionPattern = /^\s{2}@(\w+)\s*->\s*(.+?)\s*$/;
|
|
16
|
+
|
|
17
|
+
let sceneSeparator = /^---\s*$/;
|
|
18
|
+
|
|
19
|
+
function parseStringValue(value) {
|
|
20
|
+
let trimmed = value.trim();
|
|
21
|
+
if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) {
|
|
22
|
+
return trimmed.slice(1, -1);
|
|
23
|
+
} else {
|
|
24
|
+
return trimmed;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getCapture(result, index) {
|
|
29
|
+
return result.slice(1)[index];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function parseActionExpr(expr) {
|
|
33
|
+
let gotoPattern = /^goto\s*\(\s*(\w+)(?:\s*,\s*([\w-]+))?\s*\)$/;
|
|
34
|
+
let backPattern = /^back\s*\(\s*\)$/;
|
|
35
|
+
let forwardPattern = /^forward\s*\(\s*\)$/;
|
|
36
|
+
let result = gotoPattern.exec(expr);
|
|
37
|
+
if (result == null) {
|
|
38
|
+
if (backPattern.test(expr)) {
|
|
39
|
+
return "Back";
|
|
40
|
+
}
|
|
41
|
+
if (forwardPattern.test(expr)) {
|
|
42
|
+
return "Forward";
|
|
43
|
+
}
|
|
44
|
+
let callPattern = /^(\w+)\s*\(([^)]*)\)$/;
|
|
45
|
+
let result$1 = callPattern.exec(expr);
|
|
46
|
+
if (result$1 == null) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
let funcName = result$1.slice(1)[0];
|
|
50
|
+
let argsStr = Core__Option.getOr(result$1.slice(1)[1], "");
|
|
51
|
+
if (funcName === undefined) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let args = argsStr.trim() === "" ? [] : argsStr.split(",").map(prim => prim.trim());
|
|
55
|
+
return {
|
|
56
|
+
TAG: "Call",
|
|
57
|
+
function: funcName,
|
|
58
|
+
args: args,
|
|
59
|
+
condition: undefined
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
let target = result.slice(1)[0];
|
|
63
|
+
let transition = Core__Option.getOr(result.slice(1)[1], "fade");
|
|
64
|
+
if (target !== undefined) {
|
|
65
|
+
return {
|
|
66
|
+
TAG: "Goto",
|
|
67
|
+
target: target,
|
|
68
|
+
transition: transition,
|
|
69
|
+
condition: undefined
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function selectorToId(selectorType, text) {
|
|
75
|
+
switch (selectorType) {
|
|
76
|
+
case "button" :
|
|
77
|
+
case "link" :
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
return text;
|
|
81
|
+
}
|
|
82
|
+
return text.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function createState() {
|
|
86
|
+
return {
|
|
87
|
+
currentScene: undefined,
|
|
88
|
+
currentElementId: undefined,
|
|
89
|
+
currentProperties: {},
|
|
90
|
+
currentActions: [],
|
|
91
|
+
sceneInteractions: [],
|
|
92
|
+
currentInteractions: []
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function flushElement(state) {
|
|
97
|
+
let elementId = state.currentElementId;
|
|
98
|
+
if (elementId === undefined) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let interaction_properties = state.currentProperties;
|
|
102
|
+
let interaction_actions = state.currentActions;
|
|
103
|
+
let interaction = {
|
|
104
|
+
elementId: elementId,
|
|
105
|
+
properties: interaction_properties,
|
|
106
|
+
actions: interaction_actions
|
|
107
|
+
};
|
|
108
|
+
state.currentInteractions.push(interaction);
|
|
109
|
+
state.currentElementId = undefined;
|
|
110
|
+
state.currentProperties = {};
|
|
111
|
+
state.currentActions = [];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function flushScene(state) {
|
|
115
|
+
flushElement(state);
|
|
116
|
+
let sceneId = state.currentScene;
|
|
117
|
+
if (sceneId === undefined) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (state.currentInteractions.length > 0) {
|
|
121
|
+
let si_interactions = state.currentInteractions;
|
|
122
|
+
let si = {
|
|
123
|
+
sceneId: sceneId,
|
|
124
|
+
interactions: si_interactions
|
|
125
|
+
};
|
|
126
|
+
state.sceneInteractions.push(si);
|
|
127
|
+
}
|
|
128
|
+
state.currentScene = undefined;
|
|
129
|
+
state.currentInteractions = [];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function parse(input) {
|
|
133
|
+
let state = {
|
|
134
|
+
currentScene: undefined,
|
|
135
|
+
currentElementId: undefined,
|
|
136
|
+
currentProperties: {},
|
|
137
|
+
currentActions: [],
|
|
138
|
+
sceneInteractions: [],
|
|
139
|
+
currentInteractions: []
|
|
140
|
+
};
|
|
141
|
+
let lines = input.split("\n");
|
|
142
|
+
let lineNum = {
|
|
143
|
+
contents: 0
|
|
144
|
+
};
|
|
145
|
+
let error = {
|
|
146
|
+
contents: undefined
|
|
147
|
+
};
|
|
148
|
+
lines.forEach(line => {
|
|
149
|
+
lineNum.contents = lineNum.contents + 1 | 0;
|
|
150
|
+
if (Core__Option.isSome(error.contents)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
let trimmed = line.trim();
|
|
154
|
+
if (trimmed === "" || trimmed.startsWith("//")) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (sceneSeparator.test(trimmed)) {
|
|
158
|
+
return flushScene(state);
|
|
159
|
+
}
|
|
160
|
+
let result = scenePattern.exec(trimmed);
|
|
161
|
+
if (result == null) {
|
|
162
|
+
let result$1 = inputSelectorPattern.exec(trimmed);
|
|
163
|
+
if (result$1 == null) {
|
|
164
|
+
let result$2 = buttonSelectorPattern.exec(trimmed);
|
|
165
|
+
if (result$2 == null) {
|
|
166
|
+
let result$3 = linkSelectorPattern.exec(trimmed);
|
|
167
|
+
if (result$3 == null) {
|
|
168
|
+
let result$4 = propertyPattern.exec(line);
|
|
169
|
+
if (result$4 == null) {
|
|
170
|
+
let result$5 = actionPattern.exec(line);
|
|
171
|
+
if (result$5 == null) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
let matches = result$5.slice(1);
|
|
175
|
+
let actionExpr = matches[1];
|
|
176
|
+
let match = state.currentElementId;
|
|
177
|
+
if (actionExpr === undefined) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (match === undefined) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
let action = parseActionExpr(actionExpr);
|
|
184
|
+
if (action !== undefined) {
|
|
185
|
+
state.currentActions.push(action);
|
|
186
|
+
} else {
|
|
187
|
+
error.contents = `Line ` + lineNum.contents.toString() + `: Invalid action`;
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
let matches$1 = result$4.slice(1);
|
|
192
|
+
let key = matches$1[0];
|
|
193
|
+
let value = matches$1[1];
|
|
194
|
+
let match$1 = state.currentElementId;
|
|
195
|
+
if (key === undefined) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (value === undefined) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (match$1 === undefined) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
let parsedValue = parseStringValue(value);
|
|
205
|
+
state.currentProperties[key] = parsedValue;
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
flushElement(state);
|
|
209
|
+
let matches$2 = result$3.slice(1);
|
|
210
|
+
let text = matches$2[0];
|
|
211
|
+
if (text === undefined) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
let id = selectorToId("link", text);
|
|
215
|
+
state.currentElementId = id;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
flushElement(state);
|
|
219
|
+
let matches$3 = result$2.slice(1);
|
|
220
|
+
let text$1 = matches$3[0];
|
|
221
|
+
if (text$1 === undefined) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
let id$1 = selectorToId("button", text$1);
|
|
225
|
+
state.currentElementId = id$1;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
flushElement(state);
|
|
229
|
+
let matches$4 = result$1.slice(1);
|
|
230
|
+
let id$2 = matches$4[0];
|
|
231
|
+
if (id$2 !== undefined) {
|
|
232
|
+
state.currentElementId = id$2;
|
|
233
|
+
return;
|
|
234
|
+
} else {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
flushScene(state);
|
|
239
|
+
let matches$5 = result.slice(1);
|
|
240
|
+
let sceneId = matches$5[0];
|
|
241
|
+
if (sceneId !== undefined) {
|
|
242
|
+
state.currentScene = sceneId;
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
flushScene(state);
|
|
247
|
+
let msg = error.contents;
|
|
248
|
+
if (msg !== undefined) {
|
|
249
|
+
return {
|
|
250
|
+
TAG: "Error",
|
|
251
|
+
_0: msg
|
|
252
|
+
};
|
|
253
|
+
} else {
|
|
254
|
+
return {
|
|
255
|
+
TAG: "Ok",
|
|
256
|
+
_0: state.sceneInteractions
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export {
|
|
262
|
+
scenePattern,
|
|
263
|
+
inputSelectorPattern,
|
|
264
|
+
buttonSelectorPattern,
|
|
265
|
+
linkSelectorPattern,
|
|
266
|
+
propertyPattern,
|
|
267
|
+
actionPattern,
|
|
268
|
+
sceneSeparator,
|
|
269
|
+
parseStringValue,
|
|
270
|
+
getCapture,
|
|
271
|
+
parseActionExpr,
|
|
272
|
+
selectorToId,
|
|
273
|
+
createState,
|
|
274
|
+
flushElement,
|
|
275
|
+
flushScene,
|
|
276
|
+
parse,
|
|
277
|
+
}
|
|
278
|
+
/* No side effect */
|