diff options
author | Kristóf Marussy <kristof@marussy.com> | 2021-10-31 02:06:07 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2021-10-31 19:26:15 +0100 |
commit | d933f00be208a586143b35d06e689f94a6a6f7e6 (patch) | |
tree | d9d1eddd6058a48f5c5189a2d8bb1b77f2ab5579 /language-web/src/main/js/language | |
parent | fix(web): fix server-side content assist filtering (diff) | |
download | refinery-d933f00be208a586143b35d06e689f94a6a6f7e6.tar.gz refinery-d933f00be208a586143b35d06e689f94a6a6f7e6.tar.zst refinery-d933f00be208a586143b35d06e689f94a6a6f7e6.zip |
feat(web): client support for transformation rules
Diffstat (limited to 'language-web/src/main/js/language')
-rw-r--r-- | language-web/src/main/js/language/folding.ts | 30 | ||||
-rw-r--r-- | language-web/src/main/js/language/indentation.ts | 5 | ||||
-rw-r--r-- | language-web/src/main/js/language/problem.grammar | 26 | ||||
-rw-r--r-- | language-web/src/main/js/language/problemLanguageSupport.ts | 18 |
4 files changed, 61 insertions, 18 deletions
diff --git a/language-web/src/main/js/language/folding.ts b/language-web/src/main/js/language/folding.ts index 54c7294d..5d51f796 100644 --- a/language-web/src/main/js/language/folding.ts +++ b/language-web/src/main/js/language/folding.ts | |||
@@ -75,18 +75,22 @@ export function foldDeclaration(node: SyntaxNode, state: EditorState): FoldRange | |||
75 | * @param node the node to fold | 75 | * @param node the node to fold |
76 | * @returns the folding range or `null` is there is nothing to fold | 76 | * @returns the folding range or `null` is there is nothing to fold |
77 | */ | 77 | */ |
78 | export function foldConjunction(node: SyntaxNode): FoldRange | null { | 78 | function foldWithSibling(node: SyntaxNode): FoldRange | null { |
79 | const { parent } = node; | 79 | const { parent } = node; |
80 | if (parent === null) { | 80 | if (parent === null) { |
81 | return null; | 81 | return null; |
82 | } | 82 | } |
83 | const { cursor } = parent; | 83 | const { firstChild } = parent; |
84 | let nConjunctions = 0; | 84 | if (firstChild === null) { |
85 | while (cursor.next()) { | 85 | return null; |
86 | } | ||
87 | const { cursor } = firstChild; | ||
88 | let nSiblings = 0; | ||
89 | while (cursor.nextSibling()) { | ||
86 | if (cursor.type === node.type) { | 90 | if (cursor.type === node.type) { |
87 | nConjunctions += 1; | 91 | nSiblings += 1; |
88 | } | 92 | } |
89 | if (nConjunctions >= 2) { | 93 | if (nSiblings >= 2) { |
90 | return { | 94 | return { |
91 | from: node.from, | 95 | from: node.from, |
92 | to: node.to, | 96 | to: node.to, |
@@ -95,3 +99,17 @@ export function foldConjunction(node: SyntaxNode): FoldRange | null { | |||
95 | } | 99 | } |
96 | return null; | 100 | return null; |
97 | } | 101 | } |
102 | |||
103 | export function foldWholeNode(node: SyntaxNode): FoldRange { | ||
104 | return { | ||
105 | from: node.from, | ||
106 | to: node.to, | ||
107 | }; | ||
108 | } | ||
109 | |||
110 | export function foldConjunction(node: SyntaxNode): FoldRange | null { | ||
111 | if (node.parent?.type?.name === 'PredicateBody') { | ||
112 | return foldWithSibling(node); | ||
113 | } | ||
114 | return foldWholeNode(node); | ||
115 | } | ||
diff --git a/language-web/src/main/js/language/indentation.ts b/language-web/src/main/js/language/indentation.ts index 973b4a80..78f0a750 100644 --- a/language-web/src/main/js/language/indentation.ts +++ b/language-web/src/main/js/language/indentation.ts | |||
@@ -75,10 +75,13 @@ export function indentDeclaration(context: TreeIndentContext): number { | |||
75 | return indentDeclarationStrategy(context, 1); | 75 | return indentDeclarationStrategy(context, 1); |
76 | } | 76 | } |
77 | 77 | ||
78 | export function indentPredicate(context: TreeIndentContext): number { | 78 | export function indentPredicateOrRule(context: TreeIndentContext): number { |
79 | const clauseIndent = indentDeclarationStrategy(context, 1); | 79 | const clauseIndent = indentDeclarationStrategy(context, 1); |
80 | if (/^\s+(;|\.)/.exec(context.textAfter) !== null) { | 80 | if (/^\s+(;|\.)/.exec(context.textAfter) !== null) { |
81 | return clauseIndent - 2; | 81 | return clauseIndent - 2; |
82 | } | 82 | } |
83 | if (/^\s+(~>)/.exec(context.textAfter) !== null) { | ||
84 | return clauseIndent - 3; | ||
85 | } | ||
83 | return clauseIndent; | 86 | return clauseIndent; |
84 | } | 87 | } |
diff --git a/language-web/src/main/js/language/problem.grammar b/language-web/src/main/js/language/problem.grammar index cf940698..c242a4ba 100644 --- a/language-web/src/main/js/language/problem.grammar +++ b/language-web/src/main/js/language/problem.grammar | |||
@@ -14,9 +14,15 @@ statement { | |||
14 | (EnumBody { "{" sep<",", UniqueNodeName> "}" } | ".") | 14 | (EnumBody { "{" sep<",", UniqueNodeName> "}" } | ".") |
15 | } | | 15 | } | |
16 | PredicateDefinition { | 16 | PredicateDefinition { |
17 | (ckw<"error"> ckw<"pred">? | ckw<"pred">) RelationName ParameterList<Parameter>? | 17 | (ckw<"error"> ckw<"pred">? | ckw<"direct">? ckw<"pred">) |
18 | RelationName ParameterList<Parameter>? | ||
18 | PredicateBody { ("<->" sep<OrOp, Conjunction>)? "." } | 19 | PredicateBody { ("<->" sep<OrOp, Conjunction>)? "." } |
19 | } | | 20 | } | |
21 | RuleDefinition { | ||
22 | ckw<"direct">? ckw<"rule"> | ||
23 | RuleName ParameterList<Parameter>? | ||
24 | RuleBody { ":" sep<OrOp, Conjunction> "~>" sep<OrOp, Action> "." } | ||
25 | } | | ||
20 | Assertion { | 26 | Assertion { |
21 | ckw<"default">? (NotOp | UnknownOp)? RelationName | 27 | ckw<"default">? (NotOp | UnknownOp)? RelationName |
22 | ParameterList<AssertionArgument> (":" LogicValue)? "." | 28 | ParameterList<AssertionArgument> (":" LogicValue)? "." |
@@ -47,9 +53,17 @@ Conjunction { ("," | Literal)+ } | |||
47 | 53 | ||
48 | OrOp { ";" } | 54 | OrOp { ";" } |
49 | 55 | ||
50 | Literal { NotOp? Atom } | 56 | Literal { NotOp? Atom (("=" | ":") sep1<"|", LogicValue>)? } |
57 | |||
58 | Atom { RelationName "+"? ParameterList<Argument> } | ||
51 | 59 | ||
52 | Atom { RelationName ParameterList<Argument>? } | 60 | Action { ("," | ActionLiteral)+ } |
61 | |||
62 | ActionLiteral { | ||
63 | ckw<"new"> VariableName | | ||
64 | ckw<"delete"> VariableName | | ||
65 | Literal | ||
66 | } | ||
53 | 67 | ||
54 | Argument { VariableName | Constant } | 68 | Argument { VariableName | Constant } |
55 | 69 | ||
@@ -67,6 +81,8 @@ Multiplicity { (IntMult "..")? (IntMult | StarMult)} | |||
67 | 81 | ||
68 | RelationName { QualifiedName } | 82 | RelationName { QualifiedName } |
69 | 83 | ||
84 | RuleName { QualifiedName } | ||
85 | |||
70 | UniqueNodeName { QualifiedName } | 86 | UniqueNodeName { QualifiedName } |
71 | 87 | ||
72 | VariableName { QualifiedName } | 88 | VariableName { QualifiedName } |
@@ -83,7 +99,7 @@ ParameterList<content> { "(" sep<",", content> ")" } | |||
83 | 99 | ||
84 | sep<separator, content> { sep1<separator, content>? } | 100 | sep<separator, content> { sep1<separator, content>? } |
85 | 101 | ||
86 | sep1<separator, content> { content (separator content?)* } | 102 | sep1<separator, content> { content (separator content)* } |
87 | 103 | ||
88 | @skip { LineComment | BlockComment | whitespace } | 104 | @skip { LineComment | BlockComment | whitespace } |
89 | 105 | ||
@@ -123,7 +139,7 @@ sep1<separator, content> { content (separator content?)* } | |||
123 | 139 | ||
124 | StarArgument { "*" } | 140 | StarArgument { "*" } |
125 | 141 | ||
126 | "{" "}" "(" ")" "[" "]" "." ".." "," ":" "<->" | 142 | "{" "}" "(" ")" "[" "]" "." ".." "," ":" "<->" "~>" |
127 | } | 143 | } |
128 | 144 | ||
129 | @detectDelim | 145 | @detectDelim |
diff --git a/language-web/src/main/js/language/problemLanguageSupport.ts b/language-web/src/main/js/language/problemLanguageSupport.ts index 80d25d71..ab1c55f9 100644 --- a/language-web/src/main/js/language/problemLanguageSupport.ts +++ b/language-web/src/main/js/language/problemLanguageSupport.ts | |||
@@ -14,11 +14,12 @@ import { | |||
14 | foldBlockComment, | 14 | foldBlockComment, |
15 | foldConjunction, | 15 | foldConjunction, |
16 | foldDeclaration, | 16 | foldDeclaration, |
17 | foldWholeNode, | ||
17 | } from './folding'; | 18 | } from './folding'; |
18 | import { | 19 | import { |
19 | indentBlockComment, | 20 | indentBlockComment, |
20 | indentDeclaration, | 21 | indentDeclaration, |
21 | indentPredicate, | 22 | indentPredicateOrRule, |
22 | } from './indentation'; | 23 | } from './indentation'; |
23 | 24 | ||
24 | const parserWithMetadata = (parser as LRParser).configure({ | 25 | const parserWithMetadata = (parser as LRParser).configure({ |
@@ -26,9 +27,10 @@ const parserWithMetadata = (parser as LRParser).configure({ | |||
26 | styleTags({ | 27 | styleTags({ |
27 | LineComment: t.lineComment, | 28 | LineComment: t.lineComment, |
28 | BlockComment: t.blockComment, | 29 | BlockComment: t.blockComment, |
29 | 'problem class enum pred unique scope': t.definitionKeyword, | 30 | 'problem class enum pred rule unique scope': t.definitionKeyword, |
30 | 'abstract extends refers contains opposite error default': t.modifier, | 31 | 'abstract extends refers contains opposite error direct default': t.modifier, |
31 | 'true false unknown error': t.keyword, | 32 | 'true false unknown error': t.keyword, |
33 | 'new delete': t.operatorKeyword, | ||
32 | NotOp: t.keyword, | 34 | NotOp: t.keyword, |
33 | UnknownOp: t.keyword, | 35 | UnknownOp: t.keyword, |
34 | OrOp: t.keyword, | 36 | OrOp: t.keyword, |
@@ -37,19 +39,21 @@ const parserWithMetadata = (parser as LRParser).configure({ | |||
37 | StarMult: t.number, | 39 | StarMult: t.number, |
38 | String: t.string, | 40 | String: t.string, |
39 | 'RelationName/QualifiedName': t.typeName, | 41 | 'RelationName/QualifiedName': t.typeName, |
42 | 'RuleName/QualifiedName': t.macroName, | ||
40 | 'UniqueNodeName/QualifiedName': t.atom, | 43 | 'UniqueNodeName/QualifiedName': t.atom, |
41 | 'VariableName/QualifiedName': t.variableName, | 44 | 'VariableName/QualifiedName': t.variableName, |
42 | '{ }': t.brace, | 45 | '{ }': t.brace, |
43 | '( )': t.paren, | 46 | '( )': t.paren, |
44 | '[ ]': t.squareBracket, | 47 | '[ ]': t.squareBracket, |
45 | '. .. , :': t.separator, | 48 | '. .. , :': t.separator, |
46 | '<->': t.definitionOperator, | 49 | '<-> ~>': t.definitionOperator, |
47 | }), | 50 | }), |
48 | indentNodeProp.add({ | 51 | indentNodeProp.add({ |
49 | ProblemDeclaration: indentDeclaration, | 52 | ProblemDeclaration: indentDeclaration, |
50 | UniqueDeclaration: indentDeclaration, | 53 | UniqueDeclaration: indentDeclaration, |
51 | ScopeDeclaration: indentDeclaration, | 54 | ScopeDeclaration: indentDeclaration, |
52 | PredicateBody: indentPredicate, | 55 | PredicateBody: indentPredicateOrRule, |
56 | RuleBody: indentPredicateOrRule, | ||
53 | BlockComment: indentBlockComment, | 57 | BlockComment: indentBlockComment, |
54 | }), | 58 | }), |
55 | foldNodeProp.add({ | 59 | foldNodeProp.add({ |
@@ -57,7 +61,9 @@ const parserWithMetadata = (parser as LRParser).configure({ | |||
57 | EnumBody: foldInside, | 61 | EnumBody: foldInside, |
58 | ParameterList: foldInside, | 62 | ParameterList: foldInside, |
59 | PredicateBody: foldInside, | 63 | PredicateBody: foldInside, |
64 | RuleBody: foldInside, | ||
60 | Conjunction: foldConjunction, | 65 | Conjunction: foldConjunction, |
66 | Action: foldWholeNode, | ||
61 | UniqueDeclaration: foldDeclaration, | 67 | UniqueDeclaration: foldDeclaration, |
62 | ScopeDeclaration: foldDeclaration, | 68 | ScopeDeclaration: foldDeclaration, |
63 | BlockComment: foldBlockComment, | 69 | BlockComment: foldBlockComment, |
@@ -75,7 +81,7 @@ const problemLanguage = LRLanguage.define({ | |||
75 | }, | 81 | }, |
76 | line: '%', | 82 | line: '%', |
77 | }, | 83 | }, |
78 | indentOnInput: /^\s*(?:\{|\}|\(|\)|;|\.)$/, | 84 | indentOnInput: /^\s*(?:\{|\}|\(|\)|;|\.|~>)$/, |
79 | }, | 85 | }, |
80 | }); | 86 | }); |
81 | 87 | ||