Skip to content

Issue 361 #364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: 242.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class SemanticDataRepository private constructor() {
validatorMap.putAll(CPUSharesOptionValue.validators)
validatorMap.putAll(CgroupSocketBindOptionValue.validators)
validatorMap.putAll(RlimitOptionValue.validators) // Scopes are not supported since they aren't standard unit files.
validatorMap.putAll(NetworkAddressOptionValue.validators)
fileClassToSectionNameToKeyValuesFromDoc["unit"]?.remove(SCOPE_KEYWORD)
fileClassToSectionToKeyAndValidatorMap["unit"]?.remove(SCOPE_KEYWORD)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.Validator
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.EOF
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.GrammarOptionValue
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.IP_ADDR_AND_PREFIX_LENGTH
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.SequenceCombinator

class NetworkAddressOptionValue() : GrammarOptionValue("config_parse_address_section", GRAMMAR) {

companion object {
val GRAMMAR = SequenceCombinator(
IP_ADDR_AND_PREFIX_LENGTH, EOF())

val validators = mapOf(
Validator("config_parse_address_section", "ADDRESS_ADDRESS") to NetworkAddressOptionValue()
)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,21 @@ open class AlternativeCombinator(vararg val tokens: Combinator) : Combinator {
override fun SemanticMatch(value: String, offset: Int): MatchResult {
return match(value, offset, Combinator::SemanticMatch)
}

override fun toString(): String = toStringIndented(0)

override fun toStringIndented(indent: Int): String {
val prefix = " ".repeat(indent)
val sb = StringBuilder()
sb.append(prefix).append("Alt(\n")
for (token in tokens) {
if (token is SequenceCombinator || token is AlternativeCombinator || token is Repeat || token is ZeroOrOne || token is ZeroOrMore || token is OneOrMore) {
sb.append(token.toStringIndented(indent + 1)).append("\n")
} else {
sb.append(" ".repeat(indent + 1)).append(token.toString()).append("\n")
}
}
sb.append(prefix).append(")")
return sb.toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ interface Combinator {
*/
fun SemanticMatch(value : String, offset: Int): MatchResult

fun toStringIndented(indent: Int): String
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,67 @@ package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.gra
val BYTES = RegexTerminal("[0-9]+[a-zA-Z]*\\s*", "[0-9]+[KMGT]?\\s*")
val DEVICE = RegexTerminal("\\S+\\s*", "/[^\\u0000. ]+\\s*")
val IOPS = RegexTerminal("[0-9]+[a-zA-Z]*\\s*", "[0-9]+[KMGT]?\\s*")

var IPV4_OCTET = IntegerTerminal(0, 256)
val DOT = LiteralChoiceTerminal(".")
var IPV4_ADDR = SequenceCombinator(IPV4_OCTET, DOT, IPV4_OCTET, DOT, IPV4_OCTET, DOT, IPV4_OCTET)

val CIDR_SEPARATOR = LiteralChoiceTerminal("/")

val IPV4_ADDR_AND_PREFIX_LENGTH = SequenceCombinator(IPV4_ADDR, CIDR_SEPARATOR, IntegerTerminal(8, 33))

var IPV6_HEXTET = RegexTerminal("[0-9a-fA-F]{1,4}", "[0-9a-fA-F]{1,4}")
val COLON = LiteralChoiceTerminal(":")
val DOUBLE_COLON = LiteralChoiceTerminal("::")


val IPV6_FULL_SPECIFIED = SequenceCombinator(IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET)
val IPV6_ZERO_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(DOUBLE_COLON, ZeroOrOne(SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 8), IPV6_HEXTET)))
val IPV6_ONE_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, DOUBLE_COLON, ZeroOrOne(SequenceCombinator( Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 7), IPV6_HEXTET)))
val IPV6_TWO_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON, IPV6_HEXTET, DOUBLE_COLON, ZeroOrOne(SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 6), IPV6_HEXTET)))
val IPV6_THREE_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, DOUBLE_COLON, ZeroOrOne(SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 5), IPV6_HEXTET)))
val IPV6_FOUR_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, DOUBLE_COLON, ZeroOrOne(SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 4), IPV6_HEXTET)))
val IPV6_FIVE_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, DOUBLE_COLON, ZeroOrOne(SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 3), IPV6_HEXTET)))
val IPV6_SIX_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, DOUBLE_COLON, ZeroOrOne(SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 2), IPV6_HEXTET)))
val IPV6_SEVEN_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, COLON,IPV6_HEXTET, DOUBLE_COLON, ZeroOrOne(IPV6_HEXTET))


val IPV6_IPV4_SUFFIX_FULL = SequenceCombinator(IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV4_ADDR)
val IPV6_IPV4_SUFFIX_ZERO_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(DOUBLE_COLON,SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 6), IPV4_ADDR))
val IPV6_IPV4_SUFFIX_ONE_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, DOUBLE_COLON, SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 5), IPV4_ADDR))
val IPV6_IPV4_SUFFIX_TWO_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON, IPV6_HEXTET, DOUBLE_COLON, SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 4), IPV4_ADDR))
val IPV6_IPV4_SUFFIX_THREE_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, DOUBLE_COLON,SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 3), IPV4_ADDR))
val IPV6_IPV4_SUFFIX_FOUR_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, DOUBLE_COLON, SequenceCombinator(Repeat(SequenceCombinator(IPV6_HEXTET, COLON), 0, 2), IPV4_ADDR))
val IPV6_IPV4_SUFFIX_FIVE_HEXTET_BEFORE_ZERO_COMP = SequenceCombinator(IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, COLON, IPV6_HEXTET, DOUBLE_COLON, IPV4_ADDR)

//val IPV6_ALL_ZEROS = DOUBLE_COLON

val IPV6_ADDR = AlternativeCombinator(
IPV6_IPV4_SUFFIX_FULL,
IPV6_IPV4_SUFFIX_ZERO_HEXTET_BEFORE_ZERO_COMP,
IPV6_IPV4_SUFFIX_ONE_HEXTET_BEFORE_ZERO_COMP,
IPV6_IPV4_SUFFIX_TWO_HEXTET_BEFORE_ZERO_COMP,
IPV6_IPV4_SUFFIX_THREE_HEXTET_BEFORE_ZERO_COMP,
IPV6_IPV4_SUFFIX_FOUR_HEXTET_BEFORE_ZERO_COMP,
IPV6_IPV4_SUFFIX_FIVE_HEXTET_BEFORE_ZERO_COMP,
IPV6_FULL_SPECIFIED,
IPV6_SEVEN_HEXTET_BEFORE_ZERO_COMP,
IPV6_SIX_HEXTET_BEFORE_ZERO_COMP,
IPV6_FIVE_HEXTET_BEFORE_ZERO_COMP,
IPV6_FOUR_HEXTET_BEFORE_ZERO_COMP,
IPV6_THREE_HEXTET_BEFORE_ZERO_COMP,
IPV6_TWO_HEXTET_BEFORE_ZERO_COMP,
IPV6_ONE_HEXTET_BEFORE_ZERO_COMP,
// Must go last because it's the most general and can match ::
IPV6_ZERO_HEXTET_BEFORE_ZERO_COMP,

// I suspect maybe that this one is redundant
//IPV6_ALL_ZEROS,
)

val IPV6_ADDR_AND_PREFIX_LENGTH = SequenceCombinator(IPV6_ADDR, CIDR_SEPARATOR, IntegerTerminal(64, 129))


var IP_ADDR_AND_PREFIX_LENGTH = AlternativeCombinator(
IPV4_ADDR_AND_PREFIX_LENGTH,
IPV6_ADDR_AND_PREFIX_LENGTH)
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ class EOF : Combinator {
NoMatch
}
}

override fun toStringIndented(indent: Int): String {
return "EOF"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,15 @@ class FlexibleLiteralChoiceTerminal(vararg val choices: String) : TerminalCombin
return NoMatch.copy(longestMatch = offset)
}

override fun toString(): String {
return if (choices.size == 1) {
"Literal(\"${choices[0]}\")"
} else {
"FlexLitChoice(" + choices.joinToString(",") { "\"$it\"" } + ")"
}
}

override fun toStringIndented(indent: Int): String {
return toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ class IntegerTerminal(private val minInclusive: Int,private val maxExclusive: In

return MatchResult(listOf(matchResult.value), offset + matchResult.value.length, listOf(this), offset + matchResult.value.length)
}

override fun toString(): String {
return "Int($minInclusive,$maxExclusive)"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ class LiteralChoiceTerminal(vararg var choices: String) : TerminalCombinator {
override fun SemanticMatch(value: String, offset: Int): MatchResult {
return match(value, offset)
}

override fun toString(): String {
return if (choices.size == 1) {
"Literal(\"${choices[0]}\")"
} else {
"LitChoice(" + choices.joinToString(",") { "\"$it\"" } + ")"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,19 @@ class OneOrMore(val combinator : Combinator) : Combinator {
override fun SemanticMatch(value: String, offset: Int): MatchResult {
return match(value, offset, combinator::SemanticMatch)
}

override fun toString(): String = toStringIndented(0)

override fun toStringIndented(indent: Int): String {
val prefix = " ".repeat(indent)
val sb = StringBuilder()
sb.append(prefix).append("OneOrMore(\n")
if (combinator is SequenceCombinator || combinator is AlternativeCombinator || combinator is Repeat || combinator is ZeroOrOne || combinator is ZeroOrMore || combinator is OneOrMore) {
sb.append(combinator.toStringIndented(indent + 1)).append("\n")
} else {
sb.append(" ".repeat(indent + 1)).append(combinator.toString()).append("\n")
}
sb.append(prefix).append(")")
return sb.toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,9 @@ class OptionalWhitespacePrefix(val combinator: Combinator):
SequenceCombinator(WhitespaceTerminal(), combinator),
combinator
) {
//
// override fun SyntacticMatch(value: String, offset: Int): MatchResult {
// var newOffset = offset
// for(o in offset..<value.length) {
// if (value[o].isWhitespace()) {
// newOffset = o + 1
// } else {
// break
// }
// }
//
// return combinator.SyntacticMatch(value, newOffset)
// }
//
// override fun SemanticMatch(value: String, offset: Int): MatchResult {
// var newOffset = offset
// for(o in offset..<value.length) {
// if (value[o].isWhitespace()) {
// newOffset = o + 1
// } else {
// break
// }
// }
//
// return combinator.SemanticMatch(value, newOffset)
// }


override fun toString(): String {
return "\\s*{${combinator}}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ class RegexTerminal(syntaticMatchStr : String, semanticMatchStr: String ) : Term

return MatchResult(listOf(matchResult.value), offset + matchResult.value.length, listOf(this), offset + matchResult.value.length)
}

override fun toString(): String {
return "Regex(\"${semanticMatch.pattern}\")"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar

import kotlin.math.max

/**
* Repeat Combinator
*/
class Repeat(val combinator : Combinator, val minInclusive: Int, val maxExclusive: Int) : Combinator {

init {
if (minInclusive < 0) {
throw IllegalArgumentException("minInclusive must be >= 0")
}
if (maxExclusive < minInclusive) {
throw IllegalArgumentException("maxExclusive must be >= minInclusive")
}
}


private fun match(value: String, offset: Int, f: (String, Int) -> MatchResult): MatchResult {
var index = offset
val tokens = mutableListOf<String>()
val terminals = mutableListOf<TerminalCombinator>()

var match = f(value, index)
var matches = 0

if (match.matchResult == -1) {
if (minInclusive != 0) {
// This will return a match result = -1
return match
}

return MatchResult(tokens, offset, terminals, match.longestMatch)
}

var maxLength = match.longestMatch


while (match.matchResult != -1 && matches < maxExclusive) {
matches++
index = match.matchResult
tokens.addAll(match.tokens)
terminals.addAll(match.terminals)

match = f(value, index)
maxLength = max(maxLength, match.longestMatch)
}

if (matches < minInclusive) {
return MatchResult(emptyList<String>(), -1, emptyList<TerminalCombinator>(), maxLength)
} else {
return MatchResult(tokens, index, terminals, maxLength)
}
}

override fun SyntacticMatch(value: String, offset: Int): MatchResult {
return match(value, offset, combinator::SyntacticMatch)
}

override fun SemanticMatch(value: String, offset: Int): MatchResult {
return match(value, offset, combinator::SemanticMatch)
}

override fun toString(): String = toStringIndented(0)

override fun toStringIndented(indent: Int): String {
val prefix = " ".repeat(indent)
val sb = StringBuilder()
sb.append(prefix).append("Repeat($minInclusive,$maxExclusive\n")
if (combinator is SequenceCombinator || combinator is AlternativeCombinator || combinator is Repeat || combinator is ZeroOrOne || combinator is ZeroOrMore || combinator is OneOrMore) {
sb.append(combinator.toStringIndented(indent + 1)).append("\n")
} else {
sb.append(" ".repeat(indent + 1)).append(combinator.toString()).append("\n")
}
sb.append(prefix).append(")")
return sb.toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,21 @@ open class SequenceCombinator(vararg val tokens: Combinator) : Combinator {
}
return MatchResult(resultTokens, index, resultTerminals, maxLength)
}

override fun toString(): String = toStringIndented(0)

override fun toStringIndented(indent: Int): String {
val prefix = " ".repeat(indent)
val sb = StringBuilder()
sb.append(prefix).append("Seq(\n")
for (token in tokens) {
if (token is SequenceCombinator || token is AlternativeCombinator || token is Repeat || token is ZeroOrOne || token is ZeroOrMore || token is OneOrMore) {
sb.append(token.toStringIndented(indent + 1)).append("\n")
} else {
sb.append(" ".repeat(indent + 1)).append(token.toString()).append("\n")
}
}
sb.append(prefix).append(")")
return sb.toString()
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar

interface TerminalCombinator : Combinator
interface TerminalCombinator : Combinator {
override fun toStringIndented(indent: Int): String {
return toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,12 @@ class WhitespaceTerminal : TerminalCombinator {
override fun SemanticMatch(value: String, offset: Int): MatchResult {
return match(value, offset)
}

override fun toString(): String {
return "\\s+"
}

override fun toStringIndented(indent: Int): String {
return toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,19 @@ class ZeroOrMore(val combinator : Combinator) : Combinator {
override fun SemanticMatch(value: String, offset: Int): MatchResult {
return match(value, offset, combinator::SemanticMatch)
}

override fun toString(): String = toStringIndented(0)

override fun toStringIndented(indent: Int): String {
val prefix = " ".repeat(indent)
val sb = StringBuilder()
sb.append(prefix).append("ZeroOrMore(\n")
if (combinator is SequenceCombinator || combinator is AlternativeCombinator || combinator is Repeat || combinator is ZeroOrOne || combinator is ZeroOrMore || combinator is OneOrMore) {
sb.append(combinator.toStringIndented(indent + 1)).append("\n")
} else {
sb.append(" ".repeat(indent + 1)).append(combinator.toString()).append("\n")
}
sb.append(prefix).append(")")
return sb.toString()
}
}
Loading
Loading