diff options
Diffstat (limited to 'subprojects/frontend/src')
-rw-r--r-- | subprojects/frontend/src/index.tsx | 21 | ||||
-rw-r--r-- | subprojects/frontend/src/language/problem.grammar | 59 | ||||
-rw-r--r-- | subprojects/frontend/src/language/problemLanguageSupport.ts | 5 | ||||
-rw-r--r-- | subprojects/frontend/src/xtext/ContentAssistService.ts | 2 |
4 files changed, 48 insertions, 39 deletions
diff --git a/subprojects/frontend/src/index.tsx b/subprojects/frontend/src/index.tsx index b42b8062..0165d7c1 100644 --- a/subprojects/frontend/src/index.tsx +++ b/subprojects/frontend/src/index.tsx | |||
@@ -10,27 +10,24 @@ const initialValue = `class Family { | |||
10 | } | 10 | } |
11 | 11 | ||
12 | class Person { | 12 | class Person { |
13 | Person[] children opposite parent | 13 | refers Person[] children opposite parent |
14 | Person[0..1] parent opposite children | 14 | refers Person[0..1] parent opposite children |
15 | int age | 15 | int age |
16 | TaxStatus taxStatus | 16 | refers TaxStatus taxStatus |
17 | } | 17 | } |
18 | 18 | ||
19 | enum TaxStatus { | 19 | enum TaxStatus { |
20 | child, student, adult, retired | 20 | child, student, adult, retired |
21 | } | 21 | } |
22 | 22 | ||
23 | int ageDifference(Person p, Person q) = | ||
24 | children(p, q), age(p, pAge), age(q, qAge) -> qAge - pAge. | ||
25 | |||
26 | error invalidAgeDifference(Person p, Person q) <-> | ||
27 | children(p, q), ageDifference(p, q) <= 0. | ||
28 | |||
29 | % A child cannot have any dependents. | 23 | % A child cannot have any dependents. |
30 | pred invalidTaxStatus(Person p) <-> | 24 | pred invalidTaxStatus(Person p) <-> |
31 | taxStatus(p, child), | 25 | taxStatus(p, child), |
32 | children(p, _q) | 26 | children(p, _q) |
33 | ; | 27 | ; |
28 | parent(p, q), | ||
29 | age(q) < age(p) | ||
30 | ; | ||
34 | taxStatus(p, retired), | 31 | taxStatus(p, retired), |
35 | parent(p, q), | 32 | parent(p, q), |
36 | !taxStatus(q, retired). | 33 | !taxStatus(q, retired). |
@@ -44,10 +41,8 @@ children(anne, ciri). | |||
44 | ?children(bob, ciri). | 41 | ?children(bob, ciri). |
45 | default children(ciri, *): false. | 42 | default children(ciri, *): false. |
46 | taxStatus(anne, adult). | 43 | taxStatus(anne, adult). |
47 | age(anne, 35). | 44 | age(bob) in 21..35. |
48 | bobAge: 27. | 45 | age(ciri) = 10. |
49 | age(bob, bobAge). | ||
50 | !age(ciri, bobAge). | ||
51 | 46 | ||
52 | scope Family = 1, Person += 5..10. | 47 | scope Family = 1, Person += 5..10. |
53 | `; | 48 | `; |
diff --git a/subprojects/frontend/src/language/problem.grammar b/subprojects/frontend/src/language/problem.grammar index 4235c433..7c4098d5 100644 --- a/subprojects/frontend/src/language/problem.grammar +++ b/subprojects/frontend/src/language/problem.grammar | |||
@@ -3,11 +3,12 @@ | |||
3 | @external prop implicitCompletion from './props' | 3 | @external prop implicitCompletion from './props' |
4 | 4 | ||
5 | @precedence { | 5 | @precedence { |
6 | containment @cut, | ||
7 | prefix, | 6 | prefix, |
8 | exponential @right, | 7 | exponential @right, |
9 | multiplicative @left, | 8 | multiplicative @left, |
10 | additive @left, | 9 | additive @left, |
10 | range @left, | ||
11 | lattice @left, | ||
11 | comparison @left | 12 | comparison @left |
12 | } | 13 | } |
13 | 14 | ||
@@ -20,7 +21,7 @@ statement { | |||
20 | ClassDefinition { | 21 | ClassDefinition { |
21 | kw<"abstract">? kw<"class"> RelationName | 22 | kw<"abstract">? kw<"class"> RelationName |
22 | (kw<"extends"> sep<",", RelationName>)? | 23 | (kw<"extends"> sep<",", RelationName>)? |
23 | (ClassBody { "{" ReferenceDeclaration* "}" } | ".") | 24 | (ClassBody { "{" FeatureDeclaration* "}" } | ".") |
24 | } | | 25 | } | |
25 | EnumDefinition { | 26 | EnumDefinition { |
26 | kw<"enum"> RelationName | 27 | kw<"enum"> RelationName |
@@ -35,7 +36,7 @@ statement { | |||
35 | PredicateBody { ("<->" sep<OrOp, Conjunction>)? "." } | 36 | PredicateBody { ("<->" sep<OrOp, Conjunction>)? "." } |
36 | } | | 37 | } | |
37 | FunctionDefinition { | 38 | FunctionDefinition { |
38 | RelationName RelationName ParameterList<Parameter>? | 39 | PrimitiveType RelationName ParameterList<Parameter>? |
39 | FunctionBody { ("=" sep<OrOp, Case>)? "." } | 40 | FunctionBody { ("=" sep<OrOp, Case>)? "." } |
40 | } | | 41 | } | |
41 | //RuleDefinition { | 42 | //RuleDefinition { |
@@ -45,10 +46,8 @@ statement { | |||
45 | //} | | 46 | //} | |
46 | Assertion { | 47 | Assertion { |
47 | kw<"default">? (NotOp | UnknownOp)? RelationName | 48 | kw<"default">? (NotOp | UnknownOp)? RelationName |
48 | ParameterList<AssertionArgument> (":" LogicValue)? "." | 49 | ParameterList<AssertionArgument> |
49 | } | | 50 | (":" LogicValue | ("=" | kw<"in">) Expr)? "." |
50 | NodeValueAssertion { | ||
51 | QualifiedName ":" Constant "." | ||
52 | } | | 51 | } | |
53 | IndividualDeclaration { | 52 | IndividualDeclaration { |
54 | kw<"individual"> sep<",", IndividualNodeName> "." | 53 | kw<"individual"> sep<",", IndividualNodeName> "." |
@@ -58,15 +57,8 @@ statement { | |||
58 | } | 57 | } |
59 | } | 58 | } |
60 | 59 | ||
61 | ReferenceDeclaration { | 60 | FeatureDeclaration { |
62 | ( | 61 | (ReferenceKind | PrimitiveType | kw<"bool">) RelationName |
63 | ExplicitContainmentReference { | ||
64 | !containment (kw<"refers"> | ckw<"contains"> | kw<"container">) RelationName | ||
65 | } | | ||
66 | ImplicitContainmentReference { | ||
67 | RelationName | ||
68 | } | ||
69 | ) | ||
70 | ("[" Multiplicity? "]")? | 62 | ("[" Multiplicity? "]")? |
71 | RelationName | 63 | RelationName |
72 | (kw<"opposite"> RelationName)? | 64 | (kw<"opposite"> RelationName)? |
@@ -75,7 +67,10 @@ ReferenceDeclaration { | |||
75 | 67 | ||
76 | Parameter { Modality? RelationName? VariableName } | 68 | Parameter { Modality? RelationName? VariableName } |
77 | 69 | ||
78 | Conjunction { ("," | Expr)+ } | 70 | // Use @dynamicPrecedence to prevent a(b) from being parsed as Expr { a } Expr { b } |
71 | // instead of Atom { a(b) } | ||
72 | // Being looser with token sequencing enables more consistent syntactic highlighting. | ||
73 | Conjunction { ("," | NextConjunction[@dynamicPrecedence=-10] { Expr })+ } | ||
79 | 74 | ||
80 | Case { Conjunction ("->" Expr)? } | 75 | Case { Conjunction ("->" Expr)? } |
81 | 76 | ||
@@ -85,8 +80,10 @@ Expr { | |||
85 | UnaryExpr | BinaryExpr | Aggregation | VariableName | Atom | Constant | "(" Expr ")" | 80 | UnaryExpr | BinaryExpr | Aggregation | VariableName | Atom | Constant | "(" Expr ")" |
86 | } | 81 | } |
87 | 82 | ||
88 | BinaryExpr[@dynamicPrecedence=1] { | 83 | BinaryExpr { |
89 | Expr !comparison ComparisonOp Expr | | 84 | Expr !comparison ComparisonOp Expr | |
85 | Expr !lattice (LatticeMeet | "\\/") Expr | | ||
86 | Expr !range ".." Expr | | ||
90 | Expr !additive ("+" | "-") Expr | | 87 | Expr !additive ("+" | "-") Expr | |
91 | Expr !multiplicative (StarMult | Divide) Expr | | 88 | Expr !multiplicative (StarMult | Divide) Expr | |
92 | Expr !exponential "**" Expr | 89 | Expr !exponential "**" Expr |
@@ -110,12 +107,20 @@ Atom { RelationName "+"? ParameterList<Expr> } | |||
110 | // Literal | 107 | // Literal |
111 | //} | 108 | //} |
112 | 109 | ||
113 | AssertionArgument { NodeName | StarArgument | Constant } | 110 | AssertionArgument { NodeName | StarArgument } |
111 | |||
112 | Constant { Real | String | StarMult } | ||
114 | 113 | ||
115 | Constant { Real | String } | 114 | ReferenceKind { |
115 | kw<"refers"> | ckw<"contains"> | kw<"container"> | ||
116 | } | ||
117 | |||
118 | PrimitiveType { | ||
119 | kw<"int"> | kw<"real"> | kw<"string"> | ||
120 | } | ||
116 | 121 | ||
117 | LogicValue { | 122 | LogicValue { |
118 | ckw<"true"> | ckw<"false"> | kw<"unknown"> | kw<"error"> | 123 | kw<"true"> | kw<"false"> | kw<"unknown"> | kw<"error"> |
119 | } | 124 | } |
120 | 125 | ||
121 | Modality { | 126 | Modality { |
@@ -126,10 +131,16 @@ AggregationOp { | |||
126 | ckw<"sum"> | ckw<"prod"> | ckw<"min"> | ckw<"max"> | 131 | ckw<"sum"> | ckw<"prod"> | ckw<"min"> | ckw<"max"> |
127 | } | 132 | } |
128 | 133 | ||
134 | ComparisonOp { SymbolicComparisonOp | kw<"in"> } | ||
135 | |||
129 | ScopeElement { RelationName ("=" | "+=") Multiplicity } | 136 | ScopeElement { RelationName ("=" | "+=") Multiplicity } |
130 | 137 | ||
131 | Multiplicity { (IntMult "..")? (IntMult | StarMult)} | 138 | Multiplicity { (IntMult "..")? (IntMult | StarMult)} |
132 | 139 | ||
140 | // The ~name handles the ambiguity between transitve closure a+(b, c) and addition a+(b) | ||
141 | // in the grammar. We prefer the addition interpretation by applying @dynamicPrecedence=1 | ||
142 | // to the VariableName rule, | ||
143 | // but will go with the transtive closure (and highlight `a` as a relation) if forced. | ||
133 | RelationName { QualifiedName ~name } | 144 | RelationName { QualifiedName ~name } |
134 | 145 | ||
135 | //RuleName { QualifiedName } | 146 | //RuleName { QualifiedName } |
@@ -167,7 +178,9 @@ sep1<separator, content> { content (separator content)* } | |||
167 | 178 | ||
168 | Divide { "/" } | 179 | Divide { "/" } |
169 | 180 | ||
170 | @precedence { BlockComment, LineComment, Divide } | 181 | LatticeMeet { "/\\" } |
182 | |||
183 | @precedence { BlockComment, LineComment, LatticeMeet, Divide } | ||
171 | 184 | ||
172 | identifier { $[A-Za-z_] $[a-zA-Z0-9_]* } | 185 | identifier { $[A-Za-z_] $[a-zA-Z0-9_]* } |
173 | 186 | ||
@@ -186,7 +199,7 @@ sep1<separator, content> { content (separator content)* } | |||
186 | "\"" (![\\"\n] | "\\" (![\n] | "\n"))* "\"" | 199 | "\"" (![\\"\n] | "\\" (![\n] | "\n"))* "\"" |
187 | } | 200 | } |
188 | 201 | ||
189 | ComparisonOp { ">" | ">=" | "<" | "<=" | "==" | "!=" } | 202 | SymbolicComparisonOp { ">" | ">=" | "<" | "<=" | "==" | "!=" } |
190 | 203 | ||
191 | NotOp { "!" } | 204 | NotOp { "!" } |
192 | 205 | ||
diff --git a/subprojects/frontend/src/language/problemLanguageSupport.ts b/subprojects/frontend/src/language/problemLanguageSupport.ts index cde8b157..2a973c93 100644 --- a/subprojects/frontend/src/language/problemLanguageSupport.ts +++ b/subprojects/frontend/src/language/problemLanguageSupport.ts | |||
@@ -24,9 +24,10 @@ const parserWithMetadata = parser.configure({ | |||
24 | 'problem class enum pred individual scope': t.definitionKeyword, | 24 | 'problem class enum pred individual scope': t.definitionKeyword, |
25 | 'abstract extends refers contains container opposite': t.modifier, | 25 | 'abstract extends refers contains container opposite': t.modifier, |
26 | 'default error contained containment': t.modifier, | 26 | 'default error contained containment': t.modifier, |
27 | 'true false unknown error': t.operatorKeyword, | 27 | 'true false unknown error': t.keyword, |
28 | 'int real string bool': t.keyword, | ||
28 | 'may must current': t.operatorKeyword, | 29 | 'may must current': t.operatorKeyword, |
29 | 'sum prod min max': t.operatorKeyword, | 30 | 'sum prod min max in': t.operatorKeyword, |
30 | // 'new delete': t.keyword, | 31 | // 'new delete': t.keyword, |
31 | NotOp: t.operator, | 32 | NotOp: t.operator, |
32 | UnknownOp: t.operator, | 33 | UnknownOp: t.operator, |
diff --git a/subprojects/frontend/src/xtext/ContentAssistService.ts b/subprojects/frontend/src/xtext/ContentAssistService.ts index 101990af..fa894e4d 100644 --- a/subprojects/frontend/src/xtext/ContentAssistService.ts +++ b/subprojects/frontend/src/xtext/ContentAssistService.ts | |||
@@ -17,7 +17,7 @@ const PROPOSALS_LIMIT = 1000; | |||
17 | 17 | ||
18 | const IDENTIFIER_REGEXP_STR = '[a-zA-Z0-9_]*'; | 18 | const IDENTIFIER_REGEXP_STR = '[a-zA-Z0-9_]*'; |
19 | 19 | ||
20 | const HIGH_PRIORITY_KEYWORDS = ['<->', '==>']; | 20 | const HIGH_PRIORITY_KEYWORDS = ['<->', '->', '==>']; |
21 | 21 | ||
22 | const log = getLogger('xtext.ContentAssistService'); | 22 | const log = getLogger('xtext.ContentAssistService'); |
23 | 23 | ||