aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/frontend')
-rw-r--r--subprojects/frontend/package.json42
-rw-r--r--subprojects/frontend/src/editor/EditorTheme.ts6
-rw-r--r--subprojects/frontend/src/language/problem.grammar26
-rw-r--r--subprojects/frontend/src/language/problemLanguageSupport.ts14
-rw-r--r--subprojects/frontend/src/language/tokens.ts46
-rw-r--r--subprojects/frontend/src/xtext/ContentAssistService.ts8
-rw-r--r--subprojects/frontend/types/grammar.d.ts6
7 files changed, 110 insertions, 38 deletions
diff --git a/subprojects/frontend/package.json b/subprojects/frontend/package.json
index 0cd99d74..7d5e19d1 100644
--- a/subprojects/frontend/package.json
+++ b/subprojects/frontend/package.json
@@ -30,28 +30,28 @@
30 "dependencies": { 30 "dependencies": {
31 "@codemirror/autocomplete": "^6.12.0", 31 "@codemirror/autocomplete": "^6.12.0",
32 "@codemirror/commands": "^6.3.3", 32 "@codemirror/commands": "^6.3.3",
33 "@codemirror/language": "^6.10.0", 33 "@codemirror/language": "^6.10.1",
34 "@codemirror/lint": "^6.4.2", 34 "@codemirror/lint": "^6.5.0",
35 "@codemirror/search": "^6.5.5", 35 "@codemirror/search": "^6.5.6",
36 "@codemirror/state": "^6.4.0", 36 "@codemirror/state": "^6.4.0",
37 "@codemirror/view": "^6.23.1", 37 "@codemirror/view": "^6.24.0",
38 "@emotion/react": "^11.11.3", 38 "@emotion/react": "^11.11.3",
39 "@emotion/styled": "^11.11.0", 39 "@emotion/styled": "^11.11.0",
40 "@fontsource-variable/jetbrains-mono": "^5.0.19", 40 "@fontsource-variable/jetbrains-mono": "^5.0.19",
41 "@fontsource-variable/open-sans": "^5.0.23", 41 "@fontsource-variable/open-sans": "^5.0.25",
42 "@hpcc-js/wasm": "^2.15.3", 42 "@hpcc-js/wasm": "^2.16.0",
43 "@lezer/common": "^1.2.1", 43 "@lezer/common": "^1.2.1",
44 "@lezer/highlight": "^1.2.0", 44 "@lezer/highlight": "^1.2.0",
45 "@lezer/lr": "^1.4.0", 45 "@lezer/lr": "^1.4.0",
46 "@material-icons/svg": "^1.0.33", 46 "@material-icons/svg": "^1.0.33",
47 "@mui/icons-material": "^5.15.6", 47 "@mui/icons-material": "^5.15.10",
48 "@mui/material": "^5.15.6", 48 "@mui/material": "^5.15.10",
49 "@mui/system": "^5.15.6", 49 "@mui/system": "^5.15.9",
50 "@mui/x-data-grid": "^6.19.2", 50 "@mui/x-data-grid": "^6.19.4",
51 "ansi-styles": "^6.2.1", 51 "ansi-styles": "^6.2.1",
52 "csstype": "^3.1.3", 52 "csstype": "^3.1.3",
53 "d3": "^7.8.5", 53 "d3": "^7.8.5",
54 "d3-graphviz": "patch:d3-graphviz@npm%3A5.2.0#~/.yarn/patches/d3-graphviz-npm-5.2.0-161b1fbad4.patch", 54 "d3-graphviz": "patch:d3-graphviz@npm%3A5.3.0#~/.yarn/patches/d3-graphviz-npm-5.3.0-e0eace978a.patch",
55 "d3-selection": "^3.0.0", 55 "d3-selection": "^3.0.0",
56 "d3-zoom": "patch:d3-zoom@npm%3A3.0.0#~/.yarn/patches/d3-zoom-npm-3.0.0-18f706a421.patch", 56 "d3-zoom": "patch:d3-zoom@npm%3A3.0.0#~/.yarn/patches/d3-zoom-npm-3.0.0-18f706a421.patch",
57 "escape-string-regexp": "^5.0.0", 57 "escape-string-regexp": "^5.0.0",
@@ -61,7 +61,7 @@
61 "mobx": "^6.12.0", 61 "mobx": "^6.12.0",
62 "mobx-react-lite": "^4.0.5", 62 "mobx-react-lite": "^4.0.5",
63 "ms": "^2.1.3", 63 "ms": "^2.1.3",
64 "nanoid": "^5.0.4", 64 "nanoid": "^5.0.5",
65 "notistack": "^3.0.1", 65 "notistack": "^3.0.1",
66 "react": "^18.2.0", 66 "react": "^18.2.0",
67 "react-dom": "^18.2.0", 67 "react-dom": "^18.2.0",
@@ -80,13 +80,13 @@
80 "@types/lodash-es": "^4.17.12", 80 "@types/lodash-es": "^4.17.12",
81 "@types/micromatch": "^4.0.6", 81 "@types/micromatch": "^4.0.6",
82 "@types/ms": "^0.7.34", 82 "@types/ms": "^0.7.34",
83 "@types/node": "^20.11.10", 83 "@types/node": "^20.11.19",
84 "@types/pnpapi": "^0.0.5", 84 "@types/pnpapi": "^0.0.5",
85 "@types/react": "^18.2.48", 85 "@types/react": "^18.2.56",
86 "@types/react-dom": "^18.2.18", 86 "@types/react-dom": "^18.2.19",
87 "@typescript-eslint/eslint-plugin": "^6.20.0", 87 "@typescript-eslint/eslint-plugin": "^6.21.0",
88 "@typescript-eslint/parser": "^6.20.0", 88 "@typescript-eslint/parser": "^6.21.0",
89 "@vitejs/plugin-react-swc": "^3.5.0", 89 "@vitejs/plugin-react-swc": "^3.6.0",
90 "@xstate/cli": "^0.5.17", 90 "@xstate/cli": "^0.5.17",
91 "cross-env": "^7.0.3", 91 "cross-env": "^7.0.3",
92 "eslint": "^8.56.0", 92 "eslint": "^8.56.0",
@@ -103,10 +103,10 @@
103 "html-minifier-terser": "^7.2.0", 103 "html-minifier-terser": "^7.2.0",
104 "micromatch": "^4.0.5", 104 "micromatch": "^4.0.5",
105 "pnpapi": "^0.0.0", 105 "pnpapi": "^0.0.0",
106 "prettier": "^3.2.4", 106 "prettier": "^3.2.5",
107 "typescript": "5.3.3", 107 "typescript": "5.3.3",
108 "vite": "^5.0.12", 108 "vite": "^5.1.3",
109 "vite-plugin-pwa": "^0.17.5", 109 "vite-plugin-pwa": "^0.19.0",
110 "workbox-window": "^7.0.0" 110 "workbox-window": "^7.0.0"
111 } 111 }
112} 112}
diff --git a/subprojects/frontend/src/editor/EditorTheme.ts b/subprojects/frontend/src/editor/EditorTheme.ts
index 1cad4a36..4978c7f7 100644
--- a/subprojects/frontend/src/editor/EditorTheme.ts
+++ b/subprojects/frontend/src/editor/EditorTheme.ts
@@ -40,7 +40,9 @@ function createTypeHashStyles(
40export default styled('div', { 40export default styled('div', {
41 name: 'EditorTheme', 41 name: 'EditorTheme',
42 shouldForwardProp: (propName) => 42 shouldForwardProp: (propName) =>
43 propName !== 'showLineNumbers' && propName !== 'showActiveLine', 43 propName !== 'showLineNumbers' &&
44 propName !== 'showActiveLine' &&
45 propName !== 'colorIdentifiers',
44})<{ 46})<{
45 showLineNumbers: boolean; 47 showLineNumbers: boolean;
46 showActiveLine: boolean; 48 showActiveLine: boolean;
@@ -126,7 +128,7 @@ export default styled('div', {
126 color: theme.palette.text.secondary, 128 color: theme.palette.text.secondary,
127 }, 129 },
128 }, 130 },
129 '.tok-problem-individual': { 131 '.tok-problem-atom': {
130 '&, & .tok-variableName': { 132 '&, & .tok-variableName': {
131 color: theme.palette.text.primary, 133 color: theme.palette.text.primary,
132 }, 134 },
diff --git a/subprojects/frontend/src/language/problem.grammar b/subprojects/frontend/src/language/problem.grammar
index ce3baa02..b69ee73f 100644
--- a/subprojects/frontend/src/language/problem.grammar
+++ b/subprojects/frontend/src/language/problem.grammar
@@ -1,5 +1,5 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
@@ -22,13 +22,16 @@
22@top Problem { statement* } 22@top Problem { statement* }
23 23
24statement { 24statement {
25 ImportStatement {
26 kw<"import"> ModuleName (kw<"as"> ModuleName)? "."
27 } |
25 Assertion { 28 Assertion {
26 kw<"default">? (NotOp | UnknownOp)? RelationName 29 kw<"default">? (NotOp | UnknownOp)? RelationName
27 ParameterList<AssertionArgument> 30 ParameterList<AssertionArgument>
28 (":" Expr)? "." 31 (":" Expr)? "."
29 } | 32 } |
30 ProblemDeclaration { 33 ProblemDeclaration {
31 kw<"problem"> QualifiedName "." 34 (ckw<"module"> | kw<"problem">) ModuleName "."
32 } | 35 } |
33 ClassDefinition { 36 ClassDefinition {
34 kw<"abstract">? kw<"class"> RelationName 37 kw<"abstract">? kw<"class"> RelationName
@@ -37,7 +40,7 @@ statement {
37 } | 40 } |
38 EnumDefinition { 41 EnumDefinition {
39 kw<"enum"> RelationName 42 kw<"enum"> RelationName
40 (EnumBody { "{" sep<",", IndividualNodeName> "}" } | ".") 43 (EnumBody { "{" sep<",", AtomNodeName> "}" } | ".")
41 } | 44 } |
42 PredicateDefinition { 45 PredicateDefinition {
43 ( 46 (
@@ -56,8 +59,11 @@ statement {
56 // RuleName ParameterList<Parameter>? 59 // RuleName ParameterList<Parameter>?
57 // RuleBody { ":" sep<OrOp, Conjunction> "==>" sep<OrOp, Consequent> "." } 60 // RuleBody { ":" sep<OrOp, Conjunction> "==>" sep<OrOp, Consequent> "." }
58 //} | 61 //} |
59 IndividualDeclaration { 62 AtomDeclaration {
60 kw<"indiv"> sep<",", IndividualNodeName> "." 63 kw<"declare">? ckw<"atom"> sep<",", AtomNodeName> "."
64 } |
65 NodeDeclaration {
66 (kw<"declare"> | kw<"declare">? ckw<"multi">) sep<",", NodeName> "."
61 } | 67 } |
62 ScopeDeclaration { 68 ScopeDeclaration {
63 kw<"scope"> sep<",", ScopeElement> "." 69 kw<"scope"> sep<",", ScopeElement> "."
@@ -161,13 +167,15 @@ RelationName { QualifiedName ~name }
161 167
162//RuleName { QualifiedName } 168//RuleName { QualifiedName }
163 169
164IndividualNodeName { QualifiedName } 170AtomNodeName { QualifiedName }
165 171
166VariableName[@dynamicPrecedence=10] { QualifiedName ~name } 172VariableName[@dynamicPrecedence=10] { QualifiedName ~name }
167 173
168NodeName { QualifiedName } 174NodeName { QualifiedName }
169 175
170QualifiedName[implicitCompletion=true] { identifier ("::" identifier)* } 176ModuleName { QualifiedName }
177
178QualifiedName[implicitCompletion=true] { "::"? identifier (QualifiedNameSeparator "::" identifier)* }
171 179
172kw<term> { @specialize[@name={term},implicitCompletion=true]<identifier, term> } 180kw<term> { @specialize[@name={term},implicitCompletion=true]<identifier, term> }
173 181
@@ -181,6 +189,10 @@ sep1<separator, content> { content (separator content)* }
181 189
182@skip { LineComment | BlockComment | whitespace } 190@skip { LineComment | BlockComment | whitespace }
183 191
192@external tokens qualifiedNameSeparator from "./tokens" {
193 QualifiedNameSeparator
194}
195
184@tokens { 196@tokens {
185 whitespace { std.whitespace+ } 197 whitespace { std.whitespace+ }
186 198
diff --git a/subprojects/frontend/src/language/problemLanguageSupport.ts b/subprojects/frontend/src/language/problemLanguageSupport.ts
index 2121e05f..14826363 100644
--- a/subprojects/frontend/src/language/problemLanguageSupport.ts
+++ b/subprojects/frontend/src/language/problemLanguageSupport.ts
@@ -1,5 +1,5 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
@@ -27,7 +27,8 @@ const parserWithMetadata = parser.configure({
27 styleTags({ 27 styleTags({
28 LineComment: t.lineComment, 28 LineComment: t.lineComment,
29 BlockComment: t.blockComment, 29 BlockComment: t.blockComment,
30 'problem class enum pred fn indiv scope': t.definitionKeyword, 30 'module problem class enum pred fn scope': t.definitionKeyword,
31 'import as declare atom multi': t.definitionKeyword,
31 'abstract extends refers contains container opposite': t.modifier, 32 'abstract extends refers contains container opposite': t.modifier,
32 'default error contained containment': t.modifier, 33 'default error contained containment': t.modifier,
33 'true false unknown error': t.keyword, 34 'true false unknown error': t.keyword,
@@ -44,8 +45,9 @@ const parserWithMetadata = parser.configure({
44 String: t.string, 45 String: t.string,
45 'RelationName/QualifiedName': t.typeName, 46 'RelationName/QualifiedName': t.typeName,
46 // 'RuleName/QualifiedName': t.typeName, 47 // 'RuleName/QualifiedName': t.typeName,
47 'IndividualNodeName/QualifiedName': t.atom, 48 'AtomNodeName/QualifiedName': t.atom,
48 'VariableName/QualifiedName': t.variableName, 49 'VariableName/QualifiedName': t.variableName,
50 'ModuleName/QualifiedName': t.typeName,
49 '{ }': t.brace, 51 '{ }': t.brace,
50 '( )': t.paren, 52 '( )': t.paren,
51 '[ ]': t.squareBracket, 53 '[ ]': t.squareBracket,
@@ -54,7 +56,8 @@ const parserWithMetadata = parser.configure({
54 }), 56 }),
55 indentNodeProp.add({ 57 indentNodeProp.add({
56 ProblemDeclaration: indentDeclaration, 58 ProblemDeclaration: indentDeclaration,
57 UniqueDeclaration: indentDeclaration, 59 AtomDeclaration: indentDeclaration,
60 NodeDeclaration: indentDeclaration,
58 ScopeDeclaration: indentDeclaration, 61 ScopeDeclaration: indentDeclaration,
59 PredicateBody: indentPredicateOrRule, 62 PredicateBody: indentPredicateOrRule,
60 FunctionBody: indentPredicateOrRule, 63 FunctionBody: indentPredicateOrRule,
@@ -70,7 +73,8 @@ const parserWithMetadata = parser.configure({
70 // RuleBody: foldInside, 73 // RuleBody: foldInside,
71 Conjunction: foldConjunction, 74 Conjunction: foldConjunction,
72 // Consequent: foldWholeNode, 75 // Consequent: foldWholeNode,
73 UniqueDeclaration: foldDeclaration, 76 AtomDeclaration: foldDeclaration,
77 NodeDeclaration: foldDeclaration,
74 ScopeDeclaration: foldDeclaration, 78 ScopeDeclaration: foldDeclaration,
75 BlockComment: foldBlockComment, 79 BlockComment: foldBlockComment,
76 }), 80 }),
diff --git a/subprojects/frontend/src/language/tokens.ts b/subprojects/frontend/src/language/tokens.ts
new file mode 100644
index 00000000..b5d022f1
--- /dev/null
+++ b/subprojects/frontend/src/language/tokens.ts
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2018-2024 by Marijn Haverbeke <marijnh@gmail.com> and others
3 * Copyright (C) 2024 The Refinery Authors <https://refinery.tools/>
4 *
5 * SPDX-License-Identifier: MIT AND EPL-2.0
6 *
7 * Based on the CSS tokenizer at
8 * https://github.com/lezer-parser/css/blob/790568c968a660a94bf0fbd97a86c66da1c529e5/src/tokens.js
9 */
10
11import { ExternalTokenizer } from '@lezer/lr';
12
13/* eslint-disable-next-line import/no-unresolved --
14 Synthetic import from `@lezer/generator/rollup` cannot be found by ESLint.
15*/
16import { QualifiedNameSeparator } from './problem.grammar.terms';
17
18const colon = 58;
19const underscore = 95;
20
21function isAlpha(ch: number) {
22 return (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122) || ch >= 161;
23}
24
25function isDigit(ch: number) {
26 return ch >= 48 && ch <= 57;
27}
28
29function isIdentifier(ch: number) {
30 return isAlpha(ch) || isDigit(ch) || ch === underscore;
31}
32
33/* eslint-disable-next-line import/prefer-default-export --
34 Lezer requires a named export.
35*/
36export const qualifiedNameSeparator = new ExternalTokenizer((input) => {
37 if (input.peek(0) === colon && input.peek(1) === colon) {
38 const previous = input.peek(-1);
39 if (isIdentifier(previous)) {
40 // Inject an extra 0-length token into the token stream to let Lezer
41 // consume the `::` on its own. Explicitly consuming 2 characters here
42 // leads to inconsistent highlighting of qualified names.
43 input.acceptToken(QualifiedNameSeparator);
44 }
45 }
46});
diff --git a/subprojects/frontend/src/xtext/ContentAssistService.ts b/subprojects/frontend/src/xtext/ContentAssistService.ts
index ac8ab36a..d42dde14 100644
--- a/subprojects/frontend/src/xtext/ContentAssistService.ts
+++ b/subprojects/frontend/src/xtext/ContentAssistService.ts
@@ -1,5 +1,5 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
@@ -108,7 +108,11 @@ function createCompletion(entry: ContentAssistEntry): Completion {
108 boost = -90; 108 boost = -90;
109 break; 109 break;
110 default: 110 default:
111 { 111 if (entry.proposal.startsWith('::')) {
112 // Move absolute names below relative names,
113 // they should only be preferred if no relative name is available.
114 boost = -60;
115 } else {
112 // Penalize qualified names (vs available unqualified names). 116 // Penalize qualified names (vs available unqualified names).
113 const extraSegments = entry.proposal.match(/::/g)?.length || 0; 117 const extraSegments = entry.proposal.match(/::/g)?.length || 0;
114 boost = Math.max(-5 * extraSegments, -50); 118 boost = Math.max(-5 * extraSegments, -50);
diff --git a/subprojects/frontend/types/grammar.d.ts b/subprojects/frontend/types/grammar.d.ts
index 92f99ec3..c7848e33 100644
--- a/subprojects/frontend/types/grammar.d.ts
+++ b/subprojects/frontend/types/grammar.d.ts
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin> and others 2 * Copyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
3 * Copyright (C) 2021-2023 The Refinery Authors <https://refinery.tools/> 3 * Copyright (C) 2021-2024 The Refinery Authors <https://refinery.tools/>
4 * 4 *
5 * SPDX-License-Identifier: MIT 5 * SPDX-License-Identifier: MIT
6 */ 6 */
@@ -10,3 +10,7 @@ declare module '*.grammar' {
10 10
11 export const parser: LRParser; 11 export const parser: LRParser;
12} 12}
13
14declare module '*.terms' {
15 export const QualifiedNameSeparator: number;
16}