diff options
Diffstat (limited to 'subprojects/frontend')
-rw-r--r-- | subprojects/frontend/package.json | 42 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/EditorTheme.ts | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/language/problem.grammar | 26 | ||||
-rw-r--r-- | subprojects/frontend/src/language/problemLanguageSupport.ts | 14 | ||||
-rw-r--r-- | subprojects/frontend/src/language/tokens.ts | 46 | ||||
-rw-r--r-- | subprojects/frontend/src/xtext/ContentAssistService.ts | 8 | ||||
-rw-r--r-- | subprojects/frontend/types/grammar.d.ts | 6 |
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( | |||
40 | export default styled('div', { | 40 | export 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 | ||
24 | statement { | 24 | statement { |
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 | ||
164 | IndividualNodeName { QualifiedName } | 170 | AtomNodeName { QualifiedName } |
165 | 171 | ||
166 | VariableName[@dynamicPrecedence=10] { QualifiedName ~name } | 172 | VariableName[@dynamicPrecedence=10] { QualifiedName ~name } |
167 | 173 | ||
168 | NodeName { QualifiedName } | 174 | NodeName { QualifiedName } |
169 | 175 | ||
170 | QualifiedName[implicitCompletion=true] { identifier ("::" identifier)* } | 176 | ModuleName { QualifiedName } |
177 | |||
178 | QualifiedName[implicitCompletion=true] { "::"? identifier (QualifiedNameSeparator "::" identifier)* } | ||
171 | 179 | ||
172 | kw<term> { @specialize[@name={term},implicitCompletion=true]<identifier, term> } | 180 | kw<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 | |||
11 | import { 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 | */ | ||
16 | import { QualifiedNameSeparator } from './problem.grammar.terms'; | ||
17 | |||
18 | const colon = 58; | ||
19 | const underscore = 95; | ||
20 | |||
21 | function isAlpha(ch: number) { | ||
22 | return (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122) || ch >= 161; | ||
23 | } | ||
24 | |||
25 | function isDigit(ch: number) { | ||
26 | return ch >= 48 && ch <= 57; | ||
27 | } | ||
28 | |||
29 | function 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 | */ | ||
36 | export 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 | |||
14 | declare module '*.terms' { | ||
15 | export const QualifiedNameSeparator: number; | ||
16 | } | ||