simpler parser, allow for negated conditions

This commit is contained in:
octarine-noise
2021-07-26 16:29:54 +02:00
parent b4824b77ae
commit e689a44687
6 changed files with 44 additions and 33 deletions

View File

@@ -31,34 +31,42 @@ TOKEN : {
< parenStart : "(" > | < parenStart : "(" > |
< parenEnd : ")" > | < parenEnd : ")" > |
< dot : "." > | < dot : "." > |
< comma : "," > < comma : "," > |
< exclamation : "!" >
} }
void matchFile(List<Node.MatchAll> parent) : { List<Node.MatchAll> matchFile() : {
Token t; Token t; Node n; List<Node.MatchAll> rules = new LinkedList<Node.MatchAll>();
} { } {
( (
t = "match" t = "match"
{ List<Node> nodes = new LinkedList<Node>(); } { List<Node> nodes = new LinkedList<Node>(); }
(match(nodes))* (n = match() { nodes.add(n); })*
"end" "end"
{ parent.add(new Node.MatchAll(getSource(t), nodes)); } { rules.add(new Node.MatchAll(getSource(t), nodes)); }
)* )*
{ return rules; }
} }
void match(List<Node> parent) : { Node match() : {
Token t; Token t2; MatchMethod mm; List<Node.Value> values; Node.Value v; Token t; Token t2; MatchMethod mm; List<Node.Value> values; Node.Value v; Node n;
} { } {
"block." matchBlock(parent) <exclamation> n = match() { return new Node.Negate(n); }
|
t = "block.class." mm = matchMethod() <parenStart> values = matchValueList() <parenEnd>
{ return new Node.MatchValueList(Node.MatchSource.BLOCK_CLASS, mm, getSource(t), values); }
|
t = "block.name." mm = matchMethod() <parenStart> values = matchValueList() <parenEnd>
{ return new Node.MatchValueList(Node.MatchSource.BLOCK_NAME, mm, getSource(t), values); }
| |
t = "model." mm = matchMethod() <parenStart> values = matchValueList() <parenEnd> t = "model." mm = matchMethod() <parenStart> values = matchValueList() <parenEnd>
{ parent.add(new Node.MatchValueList(Node.MatchSource.MODEL_LOCATION, mm, getSource(t), values)); } { return new Node.MatchValueList(Node.MatchSource.MODEL_LOCATION, mm, getSource(t), values); }
| |
t = "isParam" <parenStart> t2 = <stringLiteral> <comma> values = matchValueList() <parenEnd> t = "isParam" <parenStart> t2 = <stringLiteral> <comma> values = matchValueList() <parenEnd>
{ parent.add(new Node.MatchParam(t2.image, values, getSource(t))); } { return new Node.MatchParam(t2.image, values, getSource(t)); }
| |
t = "setParam" <parenStart> t2 = <stringLiteral> <comma> v = matchValue() <parenEnd> t = "setParam" <parenStart> t2 = <stringLiteral> <comma> v = matchValue() <parenEnd>
{ parent.add(new Node.SetParam(t2.image, v, getSource(t))); } { return new Node.SetParam(t2.image, v, getSource(t)); }
} }
MatchMethod matchMethod() : {} { MatchMethod matchMethod() : {} {
@@ -67,26 +75,13 @@ MatchMethod matchMethod() : {} {
"contains" { return MatchMethod.CONTAINS; } "contains" { return MatchMethod.CONTAINS; }
} }
void matchBlock(List<Node> parent) : {
Token t; MatchMethod mm; List<Node.Value> values;
} {
t = "class." mm = matchMethod() <parenStart> values = matchValueList() <parenEnd>
{ parent.add(new Node.MatchValueList(Node.MatchSource.BLOCK_CLASS, mm, getSource(t), values)); }
|
t = "name." mm = matchMethod() <parenStart> values = matchValueList() <parenEnd>
{ parent.add(new Node.MatchValueList(Node.MatchSource.BLOCK_NAME, mm, getSource(t), values)); }
}
List<Node.Value> matchValueList() : { List<Node.Value> matchValueList() : {
List<Node.Value> values = new LinkedList<Node.Value>(); List<Node.Value> values = new LinkedList<Node.Value>();
} {
matchValueToList(values) (<comma> matchValueToList(values))* { return values; }
}
void matchValueToList(List<Node.Value> values) : {
Node.Value v; Node.Value v;
} { } {
v = matchValue() { values.add(v); } v = matchValue() { values.add(v); }
(<comma> v = matchValue() { values.add(v); } )*
{ return values; }
} }
Node.Value matchValue() : { Node.Value matchValue() : {

View File

@@ -21,7 +21,7 @@ class BlockConfig : HasLogger() {
val parser = BlockConfigParser(resource.inputStream) val parser = BlockConfigParser(resource.inputStream)
.apply { configFile = configLocation.stripStart("config/betterfoliage/").toString() } .apply { configFile = configLocation.stripStart("config/betterfoliage/").toString() }
try { try {
mutableListOf<Node.MatchAll>().apply { parser.matchFile(this) } parser.matchFile()
} catch (e: ParseException) { } catch (e: ParseException) {
parseError(e, configLocation) parseError(e, configLocation)
} catch (e: TokenMgrError) { } catch (e: TokenMgrError) {

View File

@@ -71,6 +71,11 @@ class MListAny(val list: List<MValue<Boolean>>) : MAnything<Boolean> {
override val immutable get() = list.all { it.immutable } override val immutable get() = list.all { it.immutable }
} }
class MNegated(val inner: MAnything<Boolean>) : MAnything<Boolean> {
override val value get() = !inner.value
override val immutable get() = inner.immutable
}
/** /**
* Value with metadata related to rule matching applied. * Value with metadata related to rule matching applied.
* *

View File

@@ -25,6 +25,10 @@ sealed class Node {
override val configSource: ConfigSource, override val configSource: ConfigSource,
) : Node() ) : Node()
class Negate(val node: Node) : Node() {
override val configSource get() = node.configSource
}
class SetParam(val name: String, val value: Value, override val configSource: ConfigSource) : Node() class SetParam(val name: String, val value: Value, override val configSource: ConfigSource) : Node()
class MatchAll(override val configSource: ConfigSource, val list: List<Node>) : Node() class MatchAll(override val configSource: ConfigSource, val list: List<Node>) : Node()

View File

@@ -17,18 +17,23 @@ object MatchRules {
fun visitRoot(ctx: RuleProcessingContext, node: Node.MatchAll): MListAll { fun visitRoot(ctx: RuleProcessingContext, node: Node.MatchAll): MListAll {
val results = mutableListOf<MAnything<Boolean>>() val results = mutableListOf<MAnything<Boolean>>()
for (rule in node.list) { for (rule in node.list) {
val result = when(rule) { val result = mNode(ctx, rule)
is Node.MatchValueList -> mMatchList(ctx, rule)
is Node.MatchParam -> mParam(ctx, rule)
is Node.SetParam -> mParamSet(ctx, rule)
else -> rule.error("match type not implemented: ${rule::class.java.name.quoted}").left
}
results.add(result) results.add(result)
if (!result.value) break if (!result.value) break
} }
return MListAll(results) return MListAll(results)
} }
fun mNode(ctx: RuleProcessingContext, node: Node): MAnything<Boolean> = when(node) {
is Node.MatchValueList -> mMatchList(ctx, node)
is Node.MatchParam -> mParam(ctx, node)
is Node.SetParam -> mParamSet(ctx, node)
is Node.Negate -> mNegate(ctx, node)
else -> node.error("match type not implemented: ${node::class.java.name.quoted}").left
}
fun mNegate(ctx: RuleProcessingContext, node: Node.Negate) = MNegated(mNode(ctx, node.node))
fun mMatchList(ctx: RuleProcessingContext, node: Node.MatchValueList) = node.values.map { value -> fun mMatchList(ctx: RuleProcessingContext, node: Node.MatchValueList) = node.values.map { value ->
when (node.matchSource) { when (node.matchSource) {
Node.MatchSource.BLOCK_CLASS -> mBlockClass(ctx, node, value) Node.MatchSource.BLOCK_CLASS -> mBlockClass(ctx, node, value)

View File

@@ -4,6 +4,7 @@ import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.config.match.MAnything import mods.betterfoliage.config.match.MAnything
import mods.betterfoliage.config.match.MListAll import mods.betterfoliage.config.match.MListAll
import mods.betterfoliage.config.match.MListAny import mods.betterfoliage.config.match.MListAny
import mods.betterfoliage.config.match.MNegated
import mods.betterfoliage.config.match.MValue import mods.betterfoliage.config.match.MValue
import mods.betterfoliage.config.match.MatchRules import mods.betterfoliage.config.match.MatchRules
import mods.betterfoliage.util.HasLogger import mods.betterfoliage.util.HasLogger
@@ -89,6 +90,7 @@ class RuleBasedDiscovery : AbstractModelDiscovery() {
} }
is MListAny -> if (match.value) match.list.first { it.value }.let { logResult(it) } is MListAny -> if (match.value) match.list.first { it.value }.let { logResult(it) }
else match.list.forEach { logResult(it) } else match.list.forEach { logResult(it) }
is MNegated -> logResult(match.inner)
is MValue<Boolean> -> detailLogger.log(Level.INFO, "[${match.configSource}] ${match.description}") is MValue<Boolean> -> detailLogger.log(Level.INFO, "[${match.configSource}] ${match.description}")
} }
} }