Skip to content

Commit 52412e7

Browse files
author
Steve Ramage
committed
feat: Add support for Token Based validators (WIP #2)
1 parent 141df26 commit 52412e7

File tree

2 files changed

+176
-170
lines changed
  • src
    • main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar
    • test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar

2 files changed

+176
-170
lines changed

src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/GrammarOptionValue.kt

Lines changed: 86 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.gra
33
import com.intellij.openapi.project.Project
44
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.Validator
55
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.OptionValueInformation
6+
import org.apache.ivy.plugins.version.Match
67

78
interface Combinator {
89

@@ -29,7 +30,7 @@ interface Combinator {
2930
*
3031
* The return value is -1 for no match, or a new offset if this token matched something.
3132
*/
32-
fun SyntacticMatch(value : String, offset: Int): Int
33+
fun SyntacticMatch(value : String, offset: Int): MatchResult
3334

3435
/**
3536
* This checks the value string, starting at offset for a semantic match.
@@ -38,29 +39,31 @@ interface Combinator {
3839
*
3940
* The return value is -1 for no match, or a new offset if this token matched something.
4041
*/
41-
fun SemanticMatch(value : String, offset: Int): Int
42+
fun SemanticMatch(value : String, offset: Int): MatchResult
4243

4344

4445
}
4546

47+
data class MatchResult(val tokens: List<String>, val matchResult: Int)
4648

49+
val NoMatch = MatchResult(emptyList(), -1)
4750

4851
class RegexTerminal(val syntaticMatchStr : String, val semanticMatchStr: String ) : Combinator {
4952

5053
val syntaticMatch = syntaticMatchStr.toRegex()
5154
val semanticMatch = semanticMatchStr.toRegex()
5255

53-
override fun SyntacticMatch(value: String, offset: Int): Int {
54-
val matchResult = syntaticMatch.matchAt(value, offset) ?: return -1
56+
override fun SyntacticMatch(value: String, offset: Int): MatchResult {
57+
val matchResult = syntaticMatch.matchAt(value, offset) ?: return NoMatch
5558

56-
return offset + matchResult.value.length
59+
return MatchResult(listOf(matchResult.value), offset + matchResult.value.length)
5760

5861
}
5962

60-
override fun SemanticMatch(value: String, offset: Int): Int {
61-
val matchResult = semanticMatch.matchAt(value, offset) ?: return -1
63+
override fun SemanticMatch(value: String, offset: Int): MatchResult {
64+
val matchResult = semanticMatch.matchAt(value, offset) ?: return NoMatch
6265

63-
return offset + matchResult.value.length
66+
return MatchResult(listOf(matchResult.value), offset + matchResult.value.length)
6467
}
6568
}
6669

@@ -69,22 +72,22 @@ val DEVICE = RegexTerminal("\\S+\\s*", "/[^\\u0000.]+\\s*")
6972
val IOPS = RegexTerminal("[0-9]+[a-zA-Z]*\\s*", "[0-9]+[KMGT]?\\s*")
7073

7174
class LiteralChoiceTerminal(vararg val choices: String) : Combinator {
72-
override fun SyntacticMatch(value: String, offset: Int): Int {
75+
override fun SyntacticMatch(value: String, offset: Int): MatchResult {
7376
for (choice in choices) {
7477
if (value.substring(offset).startsWith(choice)) {
75-
return offset + choice.length
78+
return MatchResult(listOf(choice), offset + choice.length)
7679
}
7780
}
78-
return -1
81+
return NoMatch
7982
}
8083

81-
override fun SemanticMatch(value: String, offset: Int): Int {
84+
override fun SemanticMatch(value: String, offset: Int): MatchResult {
8285
for (choice in choices) {
8386
if (value.substring(offset).startsWith(choice)) {
84-
return offset + choice.length
87+
return MatchResult(listOf(choice), offset + choice.length)
8588
}
8689
}
87-
return -1
90+
return NoMatch
8891
}
8992
}
9093

@@ -108,30 +111,39 @@ val IMAGE_POLICY_COMBINATOR = SequenceCombinator(IMAGE_POLICY, ZeroOrMore(Sequen
108111
* This is a sequence of tokens that must match all of them.
109112
*/
110113
class SequenceCombinator(vararg val tokens: Combinator) : Combinator{
111-
override fun SyntacticMatch(value: String, offset: Int): Int {
114+
override fun SyntacticMatch(value: String, offset: Int): MatchResult {
112115
var index = offset
116+
val resultTokens = mutableListOf<String>()
117+
113118
for (token in tokens) {
114119
val match = token.SyntacticMatch(value, index)
115-
if (match == -1) {
120+
121+
if (match.matchResult == -1) {
116122
// No forward progress
117-
return -1
123+
return NoMatch
118124
}
119-
index = match
125+
index = match.matchResult
126+
resultTokens.addAll(match.tokens)
120127
}
121-
return index
128+
return MatchResult(resultTokens, index)
122129
}
123130

124-
override fun SemanticMatch(value: String, offset: Int): Int {
131+
override fun SemanticMatch(value: String, offset: Int): MatchResult {
125132
var index = offset
133+
134+
val resultTokens = mutableListOf<String>()
135+
126136
for (token in tokens) {
127137
val match = token.SemanticMatch(value, index)
128-
if (match == -1) {
138+
if (match.matchResult == -1) {
129139
// No forward progress
130-
return -1
140+
return NoMatch
131141
}
132-
index = match
142+
index = match.matchResult
143+
resultTokens.addAll(match.tokens)
144+
133145
}
134-
return index
146+
return MatchResult(resultTokens, index)
135147
}
136148
}
137149

@@ -140,24 +152,24 @@ class SequenceCombinator(vararg val tokens: Combinator) : Combinator{
140152
* This is a sequence of tokens that must match any of them.
141153
*/
142154
class AlternativeCombinator(vararg val tokens: Combinator) : Combinator {
143-
override fun SyntacticMatch(value: String, offset: Int): Int {
155+
override fun SyntacticMatch(value: String, offset: Int): MatchResult {
144156
for (token in tokens) {
145157
val match = token.SyntacticMatch(value, offset)
146-
if (match != -1) {
158+
if (match.matchResult != -1) {
147159
return match
148160
}
149161
}
150-
return -1
162+
return NoMatch
151163
}
152164

153-
override fun SemanticMatch(value: String, offset: Int): Int {
165+
override fun SemanticMatch(value: String, offset: Int): MatchResult {
154166
for (token in tokens) {
155167
val match = token.SemanticMatch(value, offset)
156-
if (match != -1) {
168+
if (match.matchResult != -1) {
157169
return match
158170
}
159171
}
160-
return -1
172+
return NoMatch
161173
}
162174
}
163175

@@ -166,34 +178,32 @@ class AlternativeCombinator(vararg val tokens: Combinator) : Combinator {
166178
*/
167179

168180
class OneOrMore(val combinator : Combinator) : Combinator {
169-
override fun SyntacticMatch(value: String, offset: Int): Int {
181+
182+
private fun match(value: String, offset: Int, f: (String, Int) -> MatchResult): MatchResult {
170183
var index = offset
171-
var match = combinator.SyntacticMatch(value, index)
184+
var match = f(value, index)
172185

173-
if (match == -1) {
174-
return -1
186+
val tokens = mutableListOf<String>()
187+
if (match.matchResult == -1) {
188+
return NoMatch
175189
}
176190

177-
while (match != -1) {
178-
index = match
179-
match = combinator.SyntacticMatch(value, index)
191+
while (match.matchResult != -1) {
192+
index = match.matchResult
193+
tokens.addAll(match.tokens)
194+
195+
match = f(value, index)
180196
}
181-
return index
182-
}
183197

184-
override fun SemanticMatch(value: String, offset: Int): Int {
185-
var index = offset
186-
var match = combinator.SemanticMatch(value, index)
198+
return MatchResult(tokens, index)
199+
}
187200

188-
if (match == -1) {
189-
return -1
190-
}
201+
override fun SyntacticMatch(value: String, offset: Int): MatchResult {
202+
return match(value, offset, combinator::SyntacticMatch)
203+
}
191204

192-
while (match != -1) {
193-
index = match
194-
match = combinator.SemanticMatch(value, index)
195-
}
196-
return index
205+
override fun SemanticMatch(value: String, offset: Int): MatchResult {
206+
return match(value, offset, combinator::SemanticMatch)
197207
}
198208
}
199209

@@ -202,52 +212,50 @@ class OneOrMore(val combinator : Combinator) : Combinator {
202212
*/
203213

204214
class ZeroOrMore(val combinator : Combinator) : Combinator {
205-
override fun SyntacticMatch(value: String, offset: Int): Int {
215+
216+
private fun match(value: String, offset: Int, f: (String, Int) -> MatchResult): MatchResult {
206217
var index = offset
207-
var match = combinator.SyntacticMatch(value, index)
218+
var match = f(value, index)
208219

209-
if (match == -1) {
210-
return offset
220+
val tokens = mutableListOf<String>()
221+
if (match.matchResult == -1) {
222+
return MatchResult(tokens, offset)
211223
}
212224

213-
while (match != -1) {
214-
index = match
215-
match = combinator.SyntacticMatch(value, index)
225+
while (match.matchResult != -1) {
226+
index = match.matchResult
227+
tokens.addAll(match.tokens)
228+
229+
match = f(value, index)
216230
}
217-
return index
218-
}
219231

220-
override fun SemanticMatch(value: String, offset: Int): Int {
221-
var index = offset
222-
var match = combinator.SemanticMatch(value, index)
232+
return MatchResult(tokens, index)
233+
}
223234

224-
if (match == -1) {
225-
return offset
226-
}
235+
override fun SyntacticMatch(value: String, offset: Int): MatchResult {
236+
return match(value, offset, combinator::SyntacticMatch)
237+
}
227238

228-
while (match != -1) {
229-
index = match
230-
match = combinator.SemanticMatch(value, index)
231-
}
232-
return index
239+
override fun SemanticMatch(value: String, offset: Int): MatchResult {
240+
return match(value, offset, combinator::SemanticMatch)
233241
}
234242
}
235243

236244

237245
class EOF : Combinator {
238-
override fun SyntacticMatch(value: String, offset: Int): Int {
246+
override fun SyntacticMatch(value: String, offset: Int): MatchResult {
239247
return if (offset == value.length) {
240-
offset
248+
MatchResult(emptyList(), offset)
241249
} else {
242-
-1
250+
NoMatch
243251
}
244252
}
245253

246-
override fun SemanticMatch(value: String, offset: Int): Int {
254+
override fun SemanticMatch(value: String, offset: Int): MatchResult {
247255
return if (offset == value.length) {
248-
offset
256+
MatchResult(emptyList(), offset)
249257
} else {
250-
-1
258+
NoMatch
251259
}
252260
}
253261
}
@@ -265,13 +273,13 @@ open class GrammarOptionValue(
265273
override fun getErrorMessage(value: String): String? {
266274
val syntaticMatch = combinator.SyntacticMatch(value, 0)
267275

268-
if (syntaticMatch == -1) {
276+
if (syntaticMatch.matchResult == -1) {
269277
return "Could not parse value"
270278
}
271279

272280
val semanticMatch = combinator.SemanticMatch(value, 0)
273281

274-
if (semanticMatch == -1) {
282+
if (semanticMatch.matchResult == -1) {
275283
return "Value did not semantically match"
276284
}
277285

0 commit comments

Comments
 (0)