diff --git a/src/MiniZinc.Client/MiniZincProcess.cs b/src/MiniZinc.Client/MiniZincProcess.cs
index 544a517..85bcd24 100644
--- a/src/MiniZinc.Client/MiniZincProcess.cs
+++ b/src/MiniZinc.Client/MiniZincProcess.cs
@@ -378,8 +378,8 @@ public void Dispose()
public override string ToString() => CommandString;
private MiniZincResult Result(
- in DataNode? objectiveValue = null,
- in DataNode? objectiveBoundValue = null,
+ in Datum? objectiveValue = null,
+ in Datum? objectiveBoundValue = null,
string? error = null
)
{
diff --git a/src/MiniZinc.Client/MiniZincResult.cs b/src/MiniZinc.Client/MiniZincResult.cs
index 411179d..52c2f36 100644
--- a/src/MiniZinc.Client/MiniZincResult.cs
+++ b/src/MiniZinc.Client/MiniZincResult.cs
@@ -74,18 +74,18 @@ public sealed record MiniZincResult
///
/// Text content of the message
///
- public required DataNode? Objective { get; init; }
+ public required Datum? Objective { get; init; }
///
/// Upper or lower bound (solver-dependent)
///
- public required DataNode? ObjectiveBound { get; init; }
+ public required Datum? ObjectiveBound { get; init; }
///
/// Absolute Gap to optimality
/// `abs(objective - bound)`
///
- public required DataNode? AbsoluteGapToOptimality { get; init; }
+ public required Datum? AbsoluteGapToOptimality { get; init; }
///
/// Relative Gap to optimality
@@ -98,7 +98,7 @@ public sealed record MiniZincResult
/// the previous iteration
/// `objective[i] - objective[i-1]`
///
- public required DataNode? AbsoluteIterationGap { get; init; }
+ public required Datum? AbsoluteIterationGap { get; init; }
///
/// Relative difference between this iteration and
diff --git a/src/MiniZinc.Parser/Data/BoolDatum.cs b/src/MiniZinc.Parser/Data/BoolDatum.cs
new file mode 100644
index 0000000..e8e650f
--- /dev/null
+++ b/src/MiniZinc.Parser/Data/BoolDatum.cs
@@ -0,0 +1,19 @@
+namespace MiniZinc.Parser;
+
+public sealed class BoolDatum(bool value) : MiniZincDatum
+{
+ public bool Value => value;
+
+ public static implicit operator bool(BoolDatum expr) => expr.Value;
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is not bool other)
+ return false;
+ if (!value.Equals(other))
+ return false;
+ return true;
+ }
+
+ public override string ToString() => Value.ToString();
+}
\ No newline at end of file
diff --git a/src/MiniZinc.Parser/Data/BoolSet.cs b/src/MiniZinc.Parser/Data/BoolSet.cs
new file mode 100644
index 0000000..6de0123
--- /dev/null
+++ b/src/MiniZinc.Parser/Data/BoolSet.cs
@@ -0,0 +1,3 @@
+namespace MiniZinc.Parser;
+
+public sealed class BoolSet(List values) : SetDatum(values) { }
diff --git a/src/MiniZinc.Parser/Data/BoolSetData.cs b/src/MiniZinc.Parser/Data/BoolSetData.cs
deleted file mode 100644
index f70bd8c..0000000
--- a/src/MiniZinc.Parser/Data/BoolSetData.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace MiniZinc.Parser;
-
-public sealed class BoolSetData(List values) : SetData(values) { }
\ No newline at end of file
diff --git a/src/MiniZinc.Parser/Data/DataNode.cs b/src/MiniZinc.Parser/Data/DataNode.cs
deleted file mode 100644
index f9b83bd..0000000
--- a/src/MiniZinc.Parser/Data/DataNode.cs
+++ /dev/null
@@ -1,156 +0,0 @@
-namespace MiniZinc.Parser;
-
-using System.Text.Json;
-using System.Text.Json.Nodes;
-
-public abstract class DataNode
-{
- public string Write(WriteOptions? options = null)
- {
- var writer = new Writer(options);
- writer.WriteValue(this);
- var mzn = writer.ToString();
- return mzn;
- }
-
- public static readonly DataNode Empty = new EmptyData();
-
- public static readonly DataNode True = new BoolData(true);
-
- public static readonly DataNode False = new BoolData(false);
-
- public static DataNode Float(decimal f) => new FloatData(f);
-
- public static DataNode Int(int i) => new IntData(i);
-
- public static DataNode String(string s) => new StringData(s);
-
- public static DataNode FromJson(JsonNode? node)
- {
- switch (node)
- {
- case JsonArray array:
- return FromJson(array);
- case JsonObject obj:
- return FromJson(obj);
- case JsonValue val:
- return FromJson(val);
- default:
- return Empty;
- }
- }
-
- public static DataNode FromSyntax(JsonObject obj)
- {
- Dictionary dict = [];
- foreach (var (key, node) in obj)
- {
- var value = FromJson(node);
- dict[key] = value;
- }
-
- var data = new RecordData(dict);
- return data;
- }
-
- public static DataNode FromSyntax(JsonArray array)
- {
- List items = new();
- foreach (var node in array)
- {
- var item = FromJson(node);
- items.Add(item);
- }
- var data = new ArrayData(items);
- return data;
- }
-
- public static DataNode FromSyntax(JsonValue node) =>
- node.GetValueKind() switch
- {
- JsonValueKind.Null => Empty,
- JsonValueKind.True => True,
- JsonValueKind.False => False,
- JsonValueKind.Number when node.TryGetValue(out var dec) => Float(dec),
- JsonValueKind.Number when node.TryGetValue(out var i) => Int(i),
- JsonValueKind.String => String(node.GetValue()),
- _ => throw new ArgumentException()
- };
-}
-
-public sealed class IntData(int value) : DataNode
-{
- public int Value => value;
-
- public static implicit operator int(IntData expr) => expr.Value;
-
- public override bool Equals(object? obj)
- {
- if (obj is not int other)
- return false;
- if (!value.Equals(other))
- return false;
- return true;
- }
-
- public override string ToString() => Value.ToString();
-}
-
-public sealed class BoolData(bool value) : DataNode
-{
- public bool Value => value;
-
- public static implicit operator bool(BoolData expr) => expr.Value;
-
- public override bool Equals(object? obj)
- {
- if (obj is not bool other)
- return false;
- if (!value.Equals(other))
- return false;
- return true;
- }
-
- public override string ToString() => Value.ToString();
-}
-
-public sealed class FloatData(decimal value) : DataNode
-{
- public decimal Value => value;
-
- public static implicit operator decimal(FloatData expr) => expr.Value;
-
- public override bool Equals(object? obj)
- {
- if (obj is not decimal other)
- return false;
- if (!value.Equals(other))
- return false;
- return true;
- }
-
- public override string ToString() => Value.ToString();
-}
-
-public sealed class StringData(string value) : DataNode
-{
- public string Value => value;
-
- public static implicit operator string(StringData expr) => expr.Value;
-
- public override bool Equals(object? obj)
- {
- if (obj is not string other)
- return false;
- if (!value.Equals(other))
- return false;
- return true;
- }
-
- public override string ToString() => Value;
-}
-
-public sealed class EmptyData : DataNode
-{
- public override bool Equals(object? obj) => obj is EmptyData;
-}
diff --git a/src/MiniZinc.Parser/Data/Datum.cs b/src/MiniZinc.Parser/Data/Datum.cs
new file mode 100644
index 0000000..4900e18
--- /dev/null
+++ b/src/MiniZinc.Parser/Data/Datum.cs
@@ -0,0 +1,83 @@
+namespace MiniZinc.Parser;
+
+using System.Text.Json;
+using System.Text.Json.Nodes;
+
+///
+/// The values that that appear in MiniZinc data files or
+/// syntax.
+///
+public abstract class MiniZincDatum
+{
+ public string Write(WriteOptions? options = null)
+ {
+ var writer = new Writer(options);
+ writer.WriteValue(this);
+ var mzn = writer.ToString();
+ return mzn;
+ }
+
+ public static readonly MiniZincDatum Empty = new EmptyDatum();
+
+ public static readonly MiniZincDatum True = new BoolDatum(true);
+
+ public static readonly MiniZincDatum False = new BoolDatum(false);
+
+ public static MiniZincDatum Float(decimal f) => new FloatDatum(f);
+
+ public static MiniZincDatum Int(int i) => new IntDatum(i);
+
+ public static MiniZincDatum String(string s) => new StringDatum(s);
+
+ public static MiniZincDatum FromJson(JsonNode? node)
+ {
+ switch (node)
+ {
+ case JsonArray array:
+ return FromJson((JsonNode?)array);
+ case JsonObject obj:
+ return FromJson((JsonNode?)obj);
+ case JsonValue val:
+ return FromJson((JsonNode?)val);
+ default:
+ return Empty;
+ }
+ }
+
+ public static MiniZincDatum FromJson(JsonObject obj)
+ {
+ Dictionary dict = [];
+ foreach (var (key, node) in obj)
+ {
+ var value = FromJson(node);
+ dict[key] = value;
+ }
+
+ var data = new RecordDatum(dict);
+ return data;
+ }
+
+ public static MiniZincDatum FromJson(JsonArray array)
+ {
+ List items = [];
+ foreach (var node in array)
+ {
+ var item = FromJson(node);
+ items.Add(item);
+ }
+ var data = new DatumArray(items);
+ return data;
+ }
+
+ public static MiniZincDatum FromJson(JsonValue node) =>
+ node.GetValueKind() switch
+ {
+ JsonValueKind.Null => Empty,
+ JsonValueKind.True => True,
+ JsonValueKind.False => False,
+ JsonValueKind.Number when node.TryGetValue(out var dec) => Float(dec),
+ JsonValueKind.Number when node.TryGetValue(out var i) => Int(i),
+ JsonValueKind.String => String(node.GetValue()),
+ _ => throw new ArgumentException($"Could not parse {node} as a datum")
+ };
+}
diff --git a/src/MiniZinc.Parser/Data/ArrayData.cs b/src/MiniZinc.Parser/Data/DatumArray.cs
similarity index 53%
rename from src/MiniZinc.Parser/Data/ArrayData.cs
rename to src/MiniZinc.Parser/Data/DatumArray.cs
index 47bf18f..711027e 100644
--- a/src/MiniZinc.Parser/Data/ArrayData.cs
+++ b/src/MiniZinc.Parser/Data/DatumArray.cs
@@ -2,8 +2,10 @@
using System.Collections;
-public abstract class ArrayData(List values) : DataNode, IReadOnlyList
+public abstract class ArrayDatum(List values) : Datum, IReadOnlyList
{
+ public override DatumKind Kind => DatumKind.Array;
+
public IEnumerator GetEnumerator() => values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
@@ -12,7 +14,7 @@ public abstract class ArrayData(List values) : DataNode, IReadOnlyList
public T this[int index] => values[index];
- public bool Equals(ArrayData? other)
+ public bool Equals(ArrayDatum? other)
{
if (other is null)
return false;
@@ -34,17 +36,17 @@ public bool Equals(ArrayData? other)
return true;
}
- public override bool Equals(object? obj) => Equals(obj as ArrayData);
+ public override bool Equals(object? obj) => Equals(obj as ArrayDatum);
}
-public sealed class IntArrayData(List list) : ArrayData(list) { }
+public sealed class IntArray(List list) : ArrayDatum(list) { }
-public sealed class FloatArrayData(List list) : ArrayData(list) { }
+public sealed class FloatArray(List list) : ArrayDatum(list) { }
-public sealed class BoolArrayData(List list) : ArrayData(list) { }
+public sealed class BoolArray(List list) : ArrayDatum(list) { }
-public sealed class StringArrayData(List list) : ArrayData(list) { }
+public sealed class StringArray(List list) : ArrayDatum(list) { }
-public sealed class ArrayData(List list) : ArrayData(list) { }
+public sealed class DatumArray(List list) : ArrayDatum(list) { }
-public sealed class TupleData(List list) : ArrayData(list) { }
+public sealed class DatumTuple(List list) : ArrayDatum(list) { }
diff --git a/src/MiniZinc.Parser/Data/EmptyDatum.cs b/src/MiniZinc.Parser/Data/EmptyDatum.cs
new file mode 100644
index 0000000..f65bb6a
--- /dev/null
+++ b/src/MiniZinc.Parser/Data/EmptyDatum.cs
@@ -0,0 +1,6 @@
+namespace MiniZinc.Parser;
+
+public sealed class EmptyDatum : MiniZincDatum
+{
+ public override bool Equals(object? obj) => obj is EmptyDatum;
+}
\ No newline at end of file
diff --git a/src/MiniZinc.Parser/Data/FloatDatum.cs b/src/MiniZinc.Parser/Data/FloatDatum.cs
new file mode 100644
index 0000000..44b3895
--- /dev/null
+++ b/src/MiniZinc.Parser/Data/FloatDatum.cs
@@ -0,0 +1,19 @@
+namespace MiniZinc.Parser;
+
+public sealed class FloatDatum(decimal value) : MiniZincDatum
+{
+ public decimal Value => value;
+
+ public static implicit operator decimal(FloatDatum expr) => expr.Value;
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is not decimal other)
+ return false;
+ if (!value.Equals(other))
+ return false;
+ return true;
+ }
+
+ public override string ToString() => Value.ToString();
+}
\ No newline at end of file
diff --git a/src/MiniZinc.Parser/Data/FloatRangeData.cs b/src/MiniZinc.Parser/Data/FloatRange.cs
similarity index 72%
rename from src/MiniZinc.Parser/Data/FloatRangeData.cs
rename to src/MiniZinc.Parser/Data/FloatRange.cs
index ac88352..a7be3e4 100644
--- a/src/MiniZinc.Parser/Data/FloatRangeData.cs
+++ b/src/MiniZinc.Parser/Data/FloatRange.cs
@@ -1,11 +1,14 @@
namespace MiniZinc.Parser;
-public sealed class FloatRangeData : DataNode
+public sealed class FloatRange : Datum
{
public readonly decimal Lower;
+
public readonly decimal Upper;
- public FloatRangeData(decimal lower, decimal upper)
+ public override DatumKind Kind => DatumKind.Set;
+
+ public FloatRange(decimal lower, decimal upper)
{
Lower = lower;
Upper = upper;
@@ -13,7 +16,7 @@ public FloatRangeData(decimal lower, decimal upper)
public override bool Equals(object? obj)
{
- if (obj is FloatRangeData range)
+ if (obj is FloatRange range)
{
if (!Lower.Equals(range.Lower))
return false;
@@ -23,7 +26,7 @@ public override bool Equals(object? obj)
return true;
}
- else if (obj is FloatSetData set)
+ else if (obj is FloatSet set)
{
if (!set.Equals(this))
return false;
@@ -34,4 +37,4 @@ public override bool Equals(object? obj)
return false;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/MiniZinc.Parser/Data/FloatSetData.cs b/src/MiniZinc.Parser/Data/FloatSet.cs
similarity index 66%
rename from src/MiniZinc.Parser/Data/FloatSetData.cs
rename to src/MiniZinc.Parser/Data/FloatSet.cs
index 372d329..200e899 100644
--- a/src/MiniZinc.Parser/Data/FloatSetData.cs
+++ b/src/MiniZinc.Parser/Data/FloatSet.cs
@@ -1,13 +1,16 @@
namespace MiniZinc.Parser;
-public sealed class FloatSetData(List values) : SetData(values)
+public sealed class FloatSet : SetDatum
{
+ public FloatSet(List values)
+ : base(values) { }
+
public override bool Equals(object? obj)
{
- if (obj is FloatRangeData { Lower: var lo, Upper: var hi })
+ if (obj is FloatRange { Lower: var lo, Upper: var hi })
{
// Can only compare float set/range equality for the singleton set
- if (values is not [var value])
+ if (_values is not [var value])
return false;
if (!lo.Equals(value))
@@ -23,4 +26,4 @@ public override bool Equals(object? obj)
return base.Equals(obj);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/MiniZinc.Parser/Data/IntDatum.cs b/src/MiniZinc.Parser/Data/IntDatum.cs
new file mode 100644
index 0000000..df6cc9b
--- /dev/null
+++ b/src/MiniZinc.Parser/Data/IntDatum.cs
@@ -0,0 +1,19 @@
+namespace MiniZinc.Parser;
+
+public sealed class IntDatum(int value) : MiniZincDatum
+{
+ public int Value => value;
+
+ public static implicit operator int(IntDatum expr) => expr.Value;
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is not int other)
+ return false;
+ if (!value.Equals(other))
+ return false;
+ return true;
+ }
+
+ public override string ToString() => Value.ToString();
+}
\ No newline at end of file
diff --git a/src/MiniZinc.Parser/Data/IntRangeData.cs b/src/MiniZinc.Parser/Data/IntRange.cs
similarity index 54%
rename from src/MiniZinc.Parser/Data/IntRangeData.cs
rename to src/MiniZinc.Parser/Data/IntRange.cs
index 8aac047..098b330 100644
--- a/src/MiniZinc.Parser/Data/IntRangeData.cs
+++ b/src/MiniZinc.Parser/Data/IntRange.cs
@@ -1,13 +1,17 @@
namespace MiniZinc.Parser;
-public sealed class IntRangeData : DataNode
+using System.Collections;
+
+public sealed class IntRange : Datum, IEnumerable
{
public readonly int Lower;
public readonly int Upper;
public readonly int Size;
public readonly int Count;
- public IntRangeData(int lower, int upper)
+ public override DatumKind Kind => DatumKind.Set;
+
+ public IntRange(int lower, int upper)
{
Lower = lower;
Upper = upper;
@@ -15,9 +19,17 @@ public IntRangeData(int lower, int upper)
Count = Size + 1;
}
+ public bool Contains(int i) => i >= Lower && i <= Upper;
+
+ public IEnumerable Enumerate()
+ {
+ for (int i = Lower; i <= Upper; i++)
+ yield return i;
+ }
+
public override bool Equals(object? obj)
{
- if (obj is IntRangeData range)
+ if (obj is IntRange range)
{
if (!Lower.Equals(range.Lower))
return false;
@@ -25,7 +37,7 @@ public override bool Equals(object? obj)
return false;
return true;
}
- else if (obj is IntSetData set)
+ else if (obj is IntSet set)
{
if (!set.Equals(this))
return false;
@@ -36,4 +48,8 @@ public override bool Equals(object? obj)
return false;
}
}
-}
\ No newline at end of file
+
+ public IEnumerator GetEnumerator() => Enumerate().GetEnumerator();
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+}
diff --git a/src/MiniZinc.Parser/Data/IntSetData.cs b/src/MiniZinc.Parser/Data/IntSet.cs
similarity index 72%
rename from src/MiniZinc.Parser/Data/IntSetData.cs
rename to src/MiniZinc.Parser/Data/IntSet.cs
index 2dc73db..7040a00 100644
--- a/src/MiniZinc.Parser/Data/IntSetData.cs
+++ b/src/MiniZinc.Parser/Data/IntSet.cs
@@ -1,10 +1,13 @@
namespace MiniZinc.Parser;
-public sealed class IntSetData(List values) : SetData(values)
+public sealed class IntSet : SetDatum
{
+ public IntSet(List values)
+ : base(values) { }
+
public override bool Equals(object? obj)
{
- if (obj is IntRangeData range)
+ if (obj is IntRange range)
{
if (Count is 0)
return false;
@@ -15,7 +18,7 @@ public override bool Equals(object? obj)
int i = 0;
for (int v = range.Lower; v <= range.Upper; v++)
{
- if (values[i++] != v)
+ if (_values[i++] != v)
return false;
}
diff --git a/src/MiniZinc.Parser/Data/RecordData.cs b/src/MiniZinc.Parser/Data/RecordDatum.cs
similarity index 61%
rename from src/MiniZinc.Parser/Data/RecordData.cs
rename to src/MiniZinc.Parser/Data/RecordDatum.cs
index 9488bd2..38513bd 100644
--- a/src/MiniZinc.Parser/Data/RecordData.cs
+++ b/src/MiniZinc.Parser/Data/RecordDatum.cs
@@ -7,28 +7,30 @@
/// MiniZinc record literal
///
/// (bool: a, int: c, float: f)
-public sealed class RecordData(Dictionary dict)
- : DataNode,
- IReadOnlyDictionary
+public sealed class RecordDatum(Dictionary dict)
+ : Datum,
+ IReadOnlyDictionary
{
- public IEnumerator> GetEnumerator() => dict.GetEnumerator();
+ public IEnumerator> GetEnumerator() => dict.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ public override DatumKind Kind => DatumKind.Record;
+
public int Count => dict.Count;
public bool ContainsKey(string key) => dict.ContainsKey(key);
- public bool TryGetValue(string key, [NotNullWhen(true)] out DataNode? value) =>
+ public bool TryGetValue(string key, [NotNullWhen(true)] out Datum? value) =>
dict.TryGetValue(key, out value);
- public DataNode this[string key] => dict[key];
+ public Datum this[string key] => dict[key];
public IEnumerable Keys => dict.Keys;
- public IEnumerable Values => dict.Values;
+ public IEnumerable Values => dict.Values;
- public bool Equals(IReadOnlyDictionary? other)
+ public bool Equals(IReadOnlyDictionary? other)
{
if (other is null)
return false;
@@ -46,6 +48,5 @@ public bool Equals(IReadOnlyDictionary? other)
return true;
}
- public override bool Equals(object? obj) =>
- Equals(obj as IReadOnlyDictionary);
+ public override bool Equals(object? obj) => Equals(obj as IReadOnlyDictionary);
}
diff --git a/src/MiniZinc.Parser/Data/SetData.cs b/src/MiniZinc.Parser/Data/SetDatum.cs
similarity index 54%
rename from src/MiniZinc.Parser/Data/SetData.cs
rename to src/MiniZinc.Parser/Data/SetDatum.cs
index a983489..9c5ae33 100644
--- a/src/MiniZinc.Parser/Data/SetData.cs
+++ b/src/MiniZinc.Parser/Data/SetDatum.cs
@@ -2,17 +2,26 @@
using System.Collections;
-public abstract class SetData(List values) : DataNode, IReadOnlyList
+public abstract class SetDatum : Datum, IReadOnlyList
{
- public IEnumerator GetEnumerator() => values.GetEnumerator();
+ protected readonly List _values;
+
+ public override DatumKind Kind => DatumKind.Set;
+
+ protected SetDatum(List values)
+ {
+ _values = values;
+ }
+
+ public IEnumerator GetEnumerator() => _values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
- public int Count => values.Count;
+ public int Count => _values.Count;
- public T this[int index] => values[index];
+ public T this[int index] => _values[index];
- public bool Equals(SetData? other)
+ public bool Equals(SetDatum? other)
{
if (other is null)
return false;
@@ -36,7 +45,7 @@ public bool Equals(SetData? other)
return true;
}
- public override bool Equals(object? obj) => Equals(obj as SetData);
+ public override bool Equals(object? obj) => Equals(obj as SetDatum);
}
-public sealed class SetData(List values) : SetData(values) { }
+public sealed class SetDatum(List values) : SetDatum(values) { }
diff --git a/src/MiniZinc.Parser/Data/StringDatum.cs b/src/MiniZinc.Parser/Data/StringDatum.cs
new file mode 100644
index 0000000..888255e
--- /dev/null
+++ b/src/MiniZinc.Parser/Data/StringDatum.cs
@@ -0,0 +1,19 @@
+namespace MiniZinc.Parser;
+
+public sealed class StringDatum(string value) : MiniZincDatum
+{
+ public string Value => value;
+
+ public static implicit operator string(StringDatum expr) => expr.Value;
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is not string other)
+ return false;
+ if (!value.Equals(other))
+ return false;
+ return true;
+ }
+
+ public override string ToString() => Value;
+}
\ No newline at end of file
diff --git a/src/MiniZinc.Parser/Expressions/BoolLiteralSyntax.cs b/src/MiniZinc.Parser/Expressions/BoolLiteralSyntax.cs
index 625856e..216ff2b 100644
--- a/src/MiniZinc.Parser/Expressions/BoolLiteralSyntax.cs
+++ b/src/MiniZinc.Parser/Expressions/BoolLiteralSyntax.cs
@@ -6,12 +6,6 @@ public sealed class BoolLiteralSyntax : ExpressionSyntax
{
public bool Value { get; }
- public BoolLiteralSyntax(in Token start)
- : base(start)
- {
- Value = start.BoolValue;
- }
-
public BoolLiteralSyntax(in Token start, bool value)
: base(start)
{
diff --git a/src/MiniZinc.Parser/MiniZincData.cs b/src/MiniZinc.Parser/MiniZincData.cs
index 7c89bca..afb3804 100644
--- a/src/MiniZinc.Parser/MiniZincData.cs
+++ b/src/MiniZinc.Parser/MiniZincData.cs
@@ -6,19 +6,19 @@
using MiniZinc;
///
-/// Result of parsing a minizinc data from a file (.dzn) or string.
+/// Result of parsing minizinc data from a file (.dzn) or string.
///
///
-/// Data is different from a in that it can only
-/// contain assignments of the form `$name = $expr;`
+/// This is different from a in that it can only
+/// contain assignments of the form `$name = $datum;`
///
[DebuggerDisplay("{SourceText}")]
-public sealed class MiniZincData(IReadOnlyDictionary? dict = null)
- : IEquatable>,
- IReadOnlyDictionary
+public sealed class MiniZincData(IReadOnlyDictionary? dict = null)
+ : IEquatable>,
+ IReadOnlyDictionary
{
- private readonly IReadOnlyDictionary _dict =
- dict ?? new Dictionary();
+ private readonly IReadOnlyDictionary _dict =
+ dict ?? new Dictionary();
public string Write(WriteOptions? options = null)
{
@@ -30,7 +30,7 @@ public string Write(WriteOptions? options = null)
public string SourceText => Write(WriteOptions.Minimal);
- public bool Equals(IReadOnlyDictionary? other)
+ public bool Equals(IReadOnlyDictionary? other)
{
if (other is null)
return false;
@@ -64,23 +64,22 @@ public bool Equals(IReadOnlyDictionary? other)
return true;
}
- public IEnumerator> GetEnumerator() => _dict.GetEnumerator();
+ public IEnumerator> GetEnumerator() => _dict.GetEnumerator();
- public override bool Equals(object? obj) =>
- Equals(obj as IReadOnlyDictionary);
+ public override bool Equals(object? obj) => Equals(obj as IReadOnlyDictionary);
public override int GetHashCode() => SourceText.GetHashCode();
- public bool TryGetValue(string key, [NotNullWhen(true)] out DataNode? value) =>
+ public bool TryGetValue(string key, [NotNullWhen(true)] out Datum? value) =>
_dict.TryGetValue(key, out value);
public bool ContainsKey(string key) => _dict.ContainsKey(key);
- public DataNode this[string name] => _dict[name];
+ public Datum this[string name] => _dict[name];
public IEnumerable Keys => _dict.Keys;
- public IEnumerable Values => _dict.Values;
+ public IEnumerable Values => _dict.Values;
public int Count => _dict.Count;
diff --git a/src/MiniZinc.Parser/ModelSyntax.cs b/src/MiniZinc.Parser/ModelSyntax.cs
index f68cc68..d87daa5 100644
--- a/src/MiniZinc.Parser/ModelSyntax.cs
+++ b/src/MiniZinc.Parser/ModelSyntax.cs
@@ -1,4 +1,6 @@
-namespace MiniZinc.Parser.Syntax;
+namespace MiniZinc.Parser;
+
+using Syntax;
///
/// Result of parsing a minizinc model from a file (.mzn) or string
diff --git a/src/MiniZinc.Parser/Parser.cs b/src/MiniZinc.Parser/Parser.cs
index 8434bb8..2cff0c3 100644
--- a/src/MiniZinc.Parser/Parser.cs
+++ b/src/MiniZinc.Parser/Parser.cs
@@ -246,7 +246,7 @@ internal bool ParseStatement([NotNullWhen(true)] out StatementSyntax? statement)
/// a = 1;b = 2; c= true;
internal bool ParseData(out MiniZincData data)
{
- Dictionary values = new();
+ Dictionary values = new();
data = new MiniZincData(values);
while (true)
@@ -260,7 +260,7 @@ internal bool ParseData(out MiniZincData data)
if (!Expect(TokenKind.EQUAL))
return false;
- if (!ParseValue(out var value))
+ if (!ParseDatum(out var value))
return false;
if (values.ContainsKey(name.StringValue))
@@ -733,12 +733,12 @@ internal bool ParseExprAtom([NotNullWhen(true)] out ExpressionSyntax? expr)
case TokenKind.KEYWORD_TRUE:
Step();
- expr = new BoolLiteralSyntax(token);
+ expr = new BoolLiteralSyntax(token, true);
break;
case TokenKind.KEYWORD_FALSE:
Step();
- expr = new BoolLiteralSyntax(token);
+ expr = new BoolLiteralSyntax(token, false);
break;
case TokenKind.STRING_LITERAL:
@@ -832,50 +832,199 @@ internal bool ParseExprAtom([NotNullWhen(true)] out ExpressionSyntax? expr)
private bool IsOk => _errorMessage is null;
- /// Parse array data into the most refined type possible
- internal bool ParseArrayData([NotNullWhen(true)] out DataNode? array)
+ /// Parse an int range data starting at the given token
+ /// The parser will step over the given lower bound
+ /// Will only return false in the case of an error
+ internal bool ParseIntDatum(out int i, out IntRange? range)
{
+ range = null;
+ Token start = _current;
+ i = start.IntValue;
Step();
+ if (!Skip(TokenKind.CLOSED_RANGE))
+ return true;
+ if (!Expect(TokenKind.INT_LITERAL, out Token upper))
+ return false;
+ range = new IntRange(i, upper.IntValue);
+ return true;
+ }
+
+ /// Parse a float range starting at the given token
+ /// The parser will step over the given lower bound
+ /// Will only return false in the case of an error
+ internal bool ParseFloatDatum(out decimal f, out FloatRange? range)
+ {
+ range = null;
+ Token start = _current;
+ f = start.FloatValue;
+ if (!Skip(TokenKind.CLOSED_RANGE))
+ return true;
+ if (!Expect(TokenKind.FLOAT_LITERAL, out Token upper))
+ return false;
+ range = new FloatRange(f, upper.FloatValue);
+ return true;
+ }
+
+ /// Parse array data into the most refined type possible
+ internal bool ParseArrayDatum([NotNullWhen(true)] out Datum? array)
+ {
array = null;
+ if (!Skip(TokenKind.OPEN_BRACKET))
+ return false;
+
List? ints = null;
List? bools = null;
List? floats = null;
List? strings = null;
- List? values = null;
-
+ List? values = null;
+ DatumKind type = default;
+ bool opt = false;
while (_kind is not TokenKind.CLOSE_BRACKET)
{
- switch (_kind)
+ switch (_kind, type, opt)
{
- case TokenKind.INT_LITERAL:
- (ints ??= []).Add(_current.IntValue);
- Step();
+ // First value is <>
+ case (TokenKind.EMPTY, DatumKind.Unknown, false):
+ values = [Datum.Empty];
+ opt = true;
break;
- case TokenKind.FLOAT_LITERAL:
- (floats ??= []).Add(_current.DecimalValue);
- Step();
+ // <> found in IntArray
+ case (TokenKind.EMPTY, DatumKind.Int, false):
+ values = [];
+ foreach (var ix in ints!)
+ values.Add(Datum.Int(ix));
+ values.Add(Datum.Empty);
+ opt = true;
break;
- case TokenKind.KEYWORD_TRUE:
+ // <> found in FloatArray
+ case (TokenKind.EMPTY, DatumKind.Float, false):
+ values = [];
+ foreach (var fx in floats!)
+ values.Add(Datum.Float(fx));
+ values.Add(Datum.Empty);
+ opt = true;
+ break;
+
+ // <> found in StringArray
+ case (TokenKind.EMPTY, DatumKind.String, false):
+ values = [];
+ foreach (var s in strings!)
+ values.Add(Datum.String(s));
+ values.Add(Datum.Empty);
+ opt = true;
+ break;
+
+ // <> found in BoolArray
+ case (TokenKind.EMPTY, DatumKind.Bool, false):
+ values = [];
+ foreach (var b in bools!)
+ values.Add(Datum.Bool(b));
+ values.Add(Datum.Empty);
+ opt = true;
+ break;
+
+ // <> occured
+ case (TokenKind.EMPTY, _, _):
+ values!.Add(Datum.Empty);
+ opt = true;
+ break;
+
+ // Int or IntRange
+ case (TokenKind.INT_LITERAL, _, _):
+ if (!ParseIntDatum(out int i, out var intRange))
+ {
+ return false;
+ }
+ else if (intRange is not null)
+ {
+ (values ??= []).Add(intRange);
+ if (type is not DatumKind.Set)
+ return Expected($"datum of type {type}, got IntRange");
+ type = DatumKind.Set;
+ }
+ else if (opt)
+ {
+ values!.Add(Datum.Int(i));
+ type = DatumKind.Int;
+ }
+ else
+ {
+ (ints ??= []).Add(i);
+ type = DatumKind.Int;
+ }
+ break;
+
+ // Float or FloatRange
+ case (TokenKind.FLOAT_LITERAL, _, _):
+ if (!ParseFloatDatum(out decimal f, out var floatRange))
+ {
+ return false;
+ }
+ else if (floatRange is not null)
+ {
+ (values ??= []).Add(floatRange);
+ if (type is not DatumKind.Set)
+ return Expected($"datum of type {type}, got FloatRange");
+ type = DatumKind.Set;
+ }
+ else if (opt)
+ {
+ values!.Add(Datum.Float(f));
+ type = DatumKind.Float;
+ }
+ else
+ {
+ (floats ??= []).Add(f);
+ type = DatumKind.Float;
+ }
+ break;
+
+ case (TokenKind.KEYWORD_TRUE, DatumKind.Unknown or DatumKind.Bool, false):
(bools ??= []).Add(true);
+ type = DatumKind.Bool;
Step();
break;
- case TokenKind.KEYWORD_FALSE:
+ case (TokenKind.KEYWORD_TRUE, DatumKind.Unknown or DatumKind.Bool, true):
+ values!.Add(Datum.True);
+ type = DatumKind.Bool;
+ Step();
+ break;
+
+ case (TokenKind.KEYWORD_FALSE, DatumKind.Unknown or DatumKind.Bool, false):
(bools ??= []).Add(false);
+ type = DatumKind.Bool;
+ Step();
+ break;
+
+ case (TokenKind.KEYWORD_FALSE, DatumKind.Unknown or DatumKind.Bool, true):
+ values!.Add(Datum.False);
+ type = DatumKind.Bool;
Step();
break;
- case TokenKind.STRING_LITERAL:
+ case (TokenKind.STRING_LITERAL, DatumKind.Unknown or DatumKind.String, false):
(strings ??= []).Add(_current.StringValue);
+ type = DatumKind.String;
+ Step();
+ break;
+
+ case (TokenKind.STRING_LITERAL, DatumKind.Unknown or DatumKind.String, true):
+ values!.Add(Datum.String(_current.StringValue));
+ type = DatumKind.String;
Step();
break;
default:
- if (!ParseValueAtom(out var value))
+ if (!ParseDatum(out var datum))
return false;
- (values ??= []).Add(value);
+ if (type is not DatumKind.Unknown)
+ if (type != datum.Kind)
+ return Expected($"Datum of type {type}, got {datum.Kind}");
+ type = datum.Kind;
+ (values ??= []).Add(datum);
break;
}
@@ -887,48 +1036,50 @@ internal bool ParseArrayData([NotNullWhen(true)] out DataNode? array)
return false;
if (ints is not null)
- array = new IntArrayData(ints);
+ array = new IntArray(ints);
else if (floats is not null)
- array = new FloatArrayData(floats);
+ array = new FloatArray(floats);
else if (bools is not null)
- array = new BoolArrayData(bools);
+ array = new BoolArray(bools);
else if (strings is not null)
- array = new StringArrayData(strings);
+ array = new StringArray(strings);
else
- array = new ArrayData(values ?? []);
+ array = new DatumArray(values ?? []);
return true;
}
/// Parse set data into the most refined type possible
- internal bool ParseSetData([NotNullWhen(true)] out DataNode? value)
+ internal bool ParseSetDatum([NotNullWhen(true)] out Datum? set)
{
- Step();
- value = null;
- List? intSet = null;
- List? boolSet = null;
- List? floatSet = null;
- List? set = null;
+ set = null;
+ if (!Skip(TokenKind.OPEN_BRACE))
+ return false;
+
+ List? ints = null;
+ List? bools = null;
+ List? floats = null;
+ List? data = null;
while (_kind is not TokenKind.CLOSE_BRACE)
{
var token = _current;
Step();
- switch (_kind)
+ switch (token.Kind)
{
case TokenKind.INT_LITERAL:
- (intSet ??= []).Add(token.IntValue);
+ (ints ??= []).Add(token.IntValue);
break;
case TokenKind.FLOAT_LITERAL:
- (floatSet ??= []).Add(token.DecimalValue);
+ (floats ??= []).Add(token.FloatValue);
break;
case TokenKind.KEYWORD_TRUE:
- (boolSet ??= []).Add(true);
+ (bools ??= []).Add(true);
break;
case TokenKind.KEYWORD_FALSE:
- (boolSet ??= []).Add(false);
+ (bools ??= []).Add(false);
break;
default:
@@ -942,68 +1093,103 @@ internal bool ParseSetData([NotNullWhen(true)] out DataNode? value)
if (!Expect(TokenKind.CLOSE_BRACE))
return false;
- if (intSet is not null)
- value = new IntSetData(intSet);
- else if (floatSet is not null)
- value = new FloatSetData(floatSet);
- else if (boolSet is not null)
- value = new BoolSetData(boolSet);
+ if (ints is not null)
+ set = new IntSet(ints);
+ else if (floats is not null)
+ set = new FloatSet(floats);
+ else if (bools is not null)
+ set = new BoolSet(bools);
else
- value = new SetData(set ?? []);
+ set = new SetDatum(data ?? []);
return true;
}
///
- /// Parse a Value.
- /// A value is a subset of Expressions that can be found in MiniZinc data files.
+ /// Parse a .
///
/// 1
/// true
/// {1,2,3}
/// 1..10
- internal bool ParseValue([NotNullWhen(true)] out DataNode? value)
+ public bool ParseDatum([NotNullWhen(true)] out Datum? datum)
{
- value = null;
-
+ datum = null;
switch (_kind)
{
case TokenKind.OPEN_BRACE:
- if (!ParseSetData(out value))
+ if (!ParseSetDatum(out datum))
return false;
break;
case TokenKind.OPEN_BRACKET:
- if (!ParseArrayData(out value))
+ if (!ParseArrayDatum(out datum))
return false;
break;
case TokenKind.OPEN_PAREN when Peek().Kind is TokenKind.IDENTIFIER:
- if (!ParseRecordData(out value))
+ if (!ParseRecordDatum(out datum))
return false;
break;
case TokenKind.OPEN_PAREN:
- if (!ParseTupleData(out value))
+ if (!ParseTupleDatum(out datum))
return false;
break;
- default:
- if (!ParseValueAtom(out value))
+ case TokenKind.INT_LITERAL:
+ if (!ParseIntDatum(out int i, out var intRange))
+ return false;
+ else if (intRange is not null)
+ datum = intRange;
+ else
+ datum = new IntDatum(i);
+ break;
+
+ case TokenKind.FLOAT_LITERAL:
+ if (!ParseFloatDatum(out decimal f, out var floatRange))
return false;
+ else if (floatRange is not null)
+ datum = floatRange;
+ else
+ datum = new FloatDatum(f);
+ break;
+
+ case TokenKind.KEYWORD_TRUE:
+ Step();
+ datum = Datum.True;
break;
+
+ case TokenKind.KEYWORD_FALSE:
+ Step();
+ datum = Datum.False;
+ break;
+
+ case TokenKind.STRING_LITERAL:
+ var s = _current.StringValue;
+ Step();
+ datum = new StringDatum(s);
+ break;
+
+ case TokenKind.EMPTY:
+ Step();
+ datum = Datum.Empty;
+ break;
+
+ default:
+ return Error($"Unexpected token {_current}");
}
return true;
}
- internal bool ParseTupleData([NotNullWhen(true)] out DataNode? value)
+ internal bool ParseTupleDatum([NotNullWhen(true)] out Datum? value)
{
Step();
value = null;
- List values = [];
+ List values = [];
while (_kind is not TokenKind.CLOSE_PAREN)
{
- if (!ParseValue(out value))
+ if (!ParseDatum(out value))
return false;
values.Add(value);
if (!Skip(TokenKind.COMMA))
@@ -1013,19 +1199,19 @@ internal bool ParseTupleData([NotNullWhen(true)] out DataNode? value)
if (!Expect(TokenKind.CLOSE_PAREN))
return false;
- value = new TupleData(values);
+ value = new DatumTuple(values);
return true;
}
- internal bool ParseRecordData([NotNullWhen(true)] out DataNode? value)
+ internal bool ParseRecordDatum([NotNullWhen(true)] out Datum? value)
{
value = null;
if (!Expect(TokenKind.OPEN_PAREN))
return false;
- Dictionary fields = [];
- value = new RecordData(fields);
+ Dictionary fields = [];
+ value = new RecordDatum(fields);
while (_kind is not TokenKind.CLOSE_PAREN)
{
@@ -1037,7 +1223,7 @@ internal bool ParseRecordData([NotNullWhen(true)] out DataNode? value)
if (!Expect(TokenKind.COLON))
return false;
- if (!ParseValue(out var fieldValue))
+ if (!ParseDatum(out var fieldValue))
return false;
if (fields.ContainsKey(fieldName))
@@ -1060,61 +1246,12 @@ internal bool ParseRecordData([NotNullWhen(true)] out DataNode? value)
///
/// 1
/// true
- internal bool ParseValueAtom([NotNullWhen(true)] out DataNode? value)
+ internal bool ParseSimpleDatum([NotNullWhen(true)] out Datum? value)
{
value = null;
Token token = _current;
- Token right;
switch (_kind)
{
- case TokenKind.INT_LITERAL:
- Step();
- if (Skip(TokenKind.CLOSED_RANGE))
- {
- if (!Expect(TokenKind.INT_LITERAL, out right))
- return false;
- value = new IntRangeData(token.IntValue, right.IntValue);
- }
- else
- {
- value = new IntData(token.IntValue);
- }
- break;
-
- case TokenKind.FLOAT_LITERAL:
- Step();
- if (Skip(TokenKind.CLOSED_RANGE))
- {
- if (!Expect(TokenKind.FLOAT_LITERAL, out right))
- return false;
- value = new FloatRangeData(token.DecimalValue, right.DecimalValue);
- }
- else
- {
- value = new FloatData(token.DecimalValue);
- }
- break;
-
- case TokenKind.KEYWORD_TRUE:
- Step();
- value = DataNode.True;
- break;
-
- case TokenKind.KEYWORD_FALSE:
- Step();
- value = DataNode.False;
- break;
-
- case TokenKind.STRING_LITERAL:
- Step();
- value = new StringData(token.ToString());
- break;
-
- case TokenKind.EMPTY:
- Step();
- value = DataNode.Empty;
- break;
-
default:
return false;
}
@@ -1125,11 +1262,6 @@ internal bool ParseValueAtom([NotNullWhen(true)] out DataNode? value)
///
/// Parse an Expression
///
- ///
- ///
- ///
- ///
- ///
/// a + b + 100
/// sum([1,2,3])
/// arr[1] * arr[2]
@@ -2511,6 +2643,8 @@ private bool ParseListType([NotNullWhen(true)] out TypeSyntax? list)
private bool Expected(string msg) => Error($"Expected {msg}");
+ private bool Unexpected(string msg) => Error($"Unexpected {msg}");
+
/// Record the given message as an error and return false
private bool Error(string? msg = null)
{
@@ -2588,7 +2722,7 @@ public static ParseResult ParseModelString(string text, out ModelSyntax model)
return result;
}
- ///
+ ///
public static ParseResult ParseModelFile(FileInfo file, out ModelSyntax model) =>
ParseModelFile(file.FullName, out model);
@@ -2617,6 +2751,40 @@ public static ParseResult ParseDataFile(string path, out MiniZincData data)
return result;
}
+ ///
+ /// Parse a from the given string.
+ ///
+ ///
+ /// Parser.ParseDatum("{1, 2, 3}"); // IntSet([1,2,3]);
+ ///
+ public static bool ParseDatum(string text, [NotNullWhen(true)] out Datum? datum)
+ {
+ datum = null;
+ var parser = new Parser(text);
+ if (!parser.ParseDatum(out datum))
+ return false;
+ return true;
+ }
+
+ ///
+ /// Parse a from the given string.
+ ///
+ ///
+ /// Parser.ParseDatum%ltIntArray%gt("[1,2,1,2,3]"); // IntArray([1,2,3]);
+ ///
+ public static bool ParseDatum(string text, [NotNullWhen(true)] out T? datum)
+ where T : Datum
+ {
+ datum = null;
+ var parser = new Parser(text);
+ if (!parser.ParseDatum(out var mzDatum))
+ return false;
+ if (mzDatum is not T t)
+ return false;
+ datum = t;
+ return true;
+ }
+
///
/// Parse the given minizinc data string.
/// Data strings only allow assignments eg: `a = 10;`
diff --git a/src/MiniZinc.Parser/SyntaxExtensions.cs b/src/MiniZinc.Parser/SyntaxExtensions.cs
index 158b1e5..797cc5c 100644
--- a/src/MiniZinc.Parser/SyntaxExtensions.cs
+++ b/src/MiniZinc.Parser/SyntaxExtensions.cs
@@ -36,8 +36,8 @@ public static T Clone(this T node)
///
/// Name of the model variable
/// The variable does not exists or was not of the expected type
- public static T Get(this IReadOnlyDictionary dict, string id)
- where T : DataNode
+ public static T Get(this IReadOnlyDictionary dict, string id)
+ where T : Datum
{
var data = dict[id];
var value = (T)data;
@@ -45,12 +45,12 @@ public static T Get(this IReadOnlyDictionary dict, string i
}
/// Try to get the solution assigned to the given variable
- public static DataNode? TryGet(this IReadOnlyDictionary dict, string id) =>
+ public static Datum? TryGet(this IReadOnlyDictionary dict, string id) =>
dict.GetValueOrDefault(id);
/// Try to get the solution assigned to the given variable
- public static T? TryGet(this IReadOnlyDictionary dict, string id)
- where T : DataNode
+ public static T? TryGet(this IReadOnlyDictionary dict, string id)
+ where T : Datum
{
if (!dict.TryGetValue(id, out var data))
return null;
diff --git a/src/MiniZinc.Parser/Token.cs b/src/MiniZinc.Parser/Token.cs
index 8a0d5b3..058d64f 100644
--- a/src/MiniZinc.Parser/Token.cs
+++ b/src/MiniZinc.Parser/Token.cs
@@ -12,8 +12,7 @@ public readonly struct Token
public readonly object? Data;
public int IntValue => (int)Data!;
public string StringValue => (string)Data!;
- public decimal DecimalValue => (decimal)Data!;
- public bool BoolValue => Kind is TokenKind.KEYWORD_TRUE;
+ public decimal FloatValue => (decimal)Data!;
public int End => Start + Length;
public Token(TokenKind kind, int line, int col, int start, int length, object? data = null)
@@ -121,7 +120,7 @@ public override string ToString() =>
TokenKind.PIPE => "|",
TokenKind.EMPTY => "<>",
TokenKind.INT_LITERAL => IntValue.ToString(),
- TokenKind.FLOAT_LITERAL => DecimalValue.ToString(CultureInfo.InvariantCulture),
+ TokenKind.FLOAT_LITERAL => FloatValue.ToString(CultureInfo.InvariantCulture),
TokenKind.STRING_LITERAL => $"\"{Data}\"",
TokenKind.KEYWORD_ANONENUM => "anon_enum",
TokenKind.NOT_EQUAL => "!=",
diff --git a/src/MiniZinc.Parser/Writer.cs b/src/MiniZinc.Parser/Writer.cs
index 0726546..a2f7df8 100644
--- a/src/MiniZinc.Parser/Writer.cs
+++ b/src/MiniZinc.Parser/Writer.cs
@@ -457,39 +457,39 @@ public void WriteExpr(ExpressionSyntax? expr, int? prec = null)
}
}
- internal void WriteValue(DataNode dataSyntax)
+ internal void WriteValue(Datum dataSyntax)
{
switch (dataSyntax)
{
- case IntArrayData x:
+ case IntArray x:
WriteValues(x, WriteInt);
break;
- case BoolArrayData x:
+ case BoolArray x:
WriteValues(x, WriteBool);
break;
- case FloatArrayData x:
+ case FloatArray x:
WriteValues(x, WriteDecimal);
break;
- case StringArrayData x:
+ case StringArray x:
WriteValues(x, WriteString);
break;
- case ArrayData x:
+ case DatumArray x:
WriteValues(x, WriteValue);
break;
- case BoolData x:
+ case BoolDatum x:
WriteBool(x);
break;
- case EmptyData x:
+ case EmptyDatum x:
WriteChar(OPEN_CHEVRON);
WriteChar(CLOSE_CHEVRON);
break;
- case IntData x:
+ case IntDatum x:
WriteInt(x);
break;
- case FloatData x:
+ case FloatDatum x:
WriteDecimal(x);
break;
- case RecordData x:
+ case RecordDatum x:
WriteValues(
x,
pair =>
@@ -502,24 +502,24 @@ internal void WriteValue(DataNode dataSyntax)
after: CLOSE_PAREN
);
break;
- case IntSetData x:
+ case IntSet x:
WriteValues(x, WriteInt, before: OPEN_BRACE, after: CLOSE_BRACE);
break;
- case FloatSetData x:
+ case FloatSet x:
WriteValues(x, WriteDecimal, before: OPEN_BRACE, after: CLOSE_BRACE);
break;
- case BoolSetData x:
+ case BoolSet x:
WriteValues(x, WriteBool, before: OPEN_BRACE, after: CLOSE_BRACE);
break;
- case SetData x:
+ case SetDatum x:
WriteValues(x, WriteValue, before: OPEN_BRACE, after: CLOSE_BRACE);
break;
- case StringData x:
+ case StringDatum x:
WriteChar(DOUBLE_QUOTE);
WriteString(x.Value);
WriteChar(DOUBLE_QUOTE);
break;
- case TupleData x:
+ case DatumTuple x:
WriteChar(OPEN_PAREN);
foreach (var item in x)
{
@@ -528,13 +528,13 @@ internal void WriteValue(DataNode dataSyntax)
}
WriteChar(CLOSE_PAREN);
break;
- case FloatRangeData x:
+ case FloatRange x:
WriteDecimal(x.Lower);
WriteChar(DOT);
WriteChar(DOT);
WriteDecimal(x.Upper);
break;
- case IntRangeData x:
+ case IntRange x:
WriteInt(x.Lower);
WriteChar(DOT);
WriteChar(DOT);
diff --git a/test/ClientTests/ClientTest.cs b/test/ClientTests/ClientTest.cs
index 8caaa43..e7a1cc2 100644
--- a/test/ClientTests/ClientTest.cs
+++ b/test/ClientTests/ClientTest.cs
@@ -147,7 +147,7 @@ public bool Check(decimal a, decimal b)
return ra == rb;
}
- public bool Check(IntLiteralSyntax value, IntRangeData rangeData)
+ public bool Check(IntLiteralSyntax value, IntRange rangeData)
{
if (!Check(value.Value, rangeData.Lower))
return false;
@@ -156,7 +156,7 @@ public bool Check(IntLiteralSyntax value, IntRangeData rangeData)
return true;
}
- public bool Check(FloatLiteralSyntax value, FloatRangeData range)
+ public bool Check(FloatLiteralSyntax value, FloatRange range)
{
if (!Check(value.Value, range.Lower))
return false;
@@ -165,7 +165,7 @@ public bool Check(FloatLiteralSyntax value, FloatRangeData range)
return true;
}
- public bool Check(IntSetData set, IntRangeData rangeData)
+ public bool Check(IntSet set, IntRange rangeData)
{
foreach (var value in set)
{
@@ -178,7 +178,7 @@ public bool Check(IntSetData set, IntRangeData rangeData)
return true;
}
- public bool Check(FloatSetData set, FloatRangeData range)
+ public bool Check(FloatSet set, FloatRange range)
{
foreach (var value in set)
{
@@ -194,52 +194,52 @@ public bool Check(FloatSetData set, FloatRangeData range)
///
/// Compare the solution against the json node
///
- public bool Check(DataNode expected, DataNode actual)
+ public bool Check(Datum expected, Datum actual)
{
int i = 0;
switch (expected, actual)
{
- case (IntData value, IntRangeData range):
+ case (IntDatum value, IntRange range):
if (!Check(value, range))
return false;
break;
- case (IntRangeData range, IntData value):
+ case (IntRange range, IntDatum value):
if (!Check(value, range))
return false;
break;
- case (FloatData value, FloatRangeData range):
+ case (FloatDatum value, FloatRange range):
if (!Check(value, range))
return false;
break;
- case (FloatRangeData range, FloatData value):
+ case (FloatRange range, FloatDatum value):
if (!Check(value, range))
return false;
break;
- case (FloatRangeData range, SetData set):
+ case (FloatRange range, SetDatum set):
if (!Check(set, range))
return false;
break;
- case (SetData set, FloatRangeData range):
+ case (SetDatum set, FloatRange range):
if (!Check(set, range))
return false;
break;
- case (IntRangeData range, IntSetData set):
+ case (IntRange range, IntSet set):
if (!Check(set, range))
return false;
break;
- case (IntSetData set, IntRangeData range):
+ case (IntSet set, IntRange range):
if (!Check(set, range))
return false;
break;
- case (ArrayData array, TupleData tuple):
+ case (DatumArray array, DatumTuple tuple):
for (i = 0; i < array.Count; i++)
{
var e = array[i];
diff --git a/test/ClientTests/ClientUnitTests.cs b/test/ClientTests/ClientUnitTests.cs
index d718c73..037a76c 100644
--- a/test/ClientTests/ClientUnitTests.cs
+++ b/test/ClientTests/ClientUnitTests.cs
@@ -35,8 +35,8 @@ async void test_solve_satisfy_result()
var b = model.AddInt("b", 10, 20);
model.AddConstraint(a < b);
var result = await Client.Solve(model);
- int aval = result.Data.Get(a);
- int bval = result.Data.Get(b);
+ int aval = result.Data.Get(a);
+ int bval = result.Data.Get(b);
aval.Should().BeLessThan(bval);
result.Status.Should().Be(SolveStatus.Satisfied);
}
@@ -58,8 +58,8 @@ async void test_solve_maximize_result()
model.Maximize("a + b");
var result = await Client.Solve(model);
result.Status.Should().Be(SolveStatus.Optimal);
- int a = result.Data.Get("a");
- int b = result.Data.Get("b");
+ int a = result.Data.Get("a");
+ int b = result.Data.Get("b");
a.Should().Be(20);
b.Should().Be(20);
result.Objective.Should().Be(40);
@@ -70,7 +70,7 @@ async void test_solve_return_array()
{
var model = MiniZincModel.FromString("array[1..10] of var 0..100: xd;");
var result = await Client.Solve(model);
- var arr = result.Data.Get("xd");
+ var arr = result.Data.Get("xd");
}
[Fact]
@@ -81,8 +81,8 @@ async void test_solve_satisfy_foreach()
model.AddVariable("b", "10..20");
await foreach (var result in Client.Solve(model))
{
- int a = result.Data.Get("a");
- int b = result.Data.Get("b");
+ int a = result.Data.Get("a");
+ int b = result.Data.Get("b");
result.Status.Should().Be(SolveStatus.Satisfied);
}
}
diff --git a/test/ParserTests/DataUnitTests.cs b/test/ParserTests/DataUnitTests.cs
index a2c9dd9..ba66fab 100644
--- a/test/ParserTests/DataUnitTests.cs
+++ b/test/ParserTests/DataUnitTests.cs
@@ -1,6 +1,7 @@
namespace MiniZinc.Tests;
using Parser;
+using static Parser.Parser;
public class DataUnitTests
{
@@ -9,9 +10,9 @@ public class DataUnitTests
[InlineData("{1}", "{1}")]
void test_data_eq(string mznA, string mznB)
{
- Parser.ParseDataString(mznA, out var a).Ok.Should().BeTrue();
- Parser.ParseDataString(mznB, out var b).Ok.Should().BeTrue();
- a.Should().Equal(b);
+ ParseDatum(mznA, out var a).Should().BeTrue();
+ ParseDatum(mznB, out var b).Should().BeTrue();
+ a.Should().Be(b);
}
[Theory]
@@ -20,9 +21,30 @@ void test_data_eq(string mznA, string mznB)
[InlineData("{1.5}", "1.5..1.5")]
void test_data_set_eq(string mznA, string mznB)
{
- Parser.ParseDataString(mznA, out var a);
- Parser.ParseDataString(mznB, out var b);
+ ParseDataString(mznA, out var a);
+ ParseDataString(mznB, out var b);
a.Should().Equal(b);
b.Should().Equal(a);
}
+
+ [Fact]
+ void test_empty_datum()
+ {
+ ParseDatum("<>", out var datum);
+ datum.Should().Be(Datum.Empty);
+ }
+
+ [Fact]
+ void test_array_datum()
+ {
+ ParseDatum("[1,2,3,2,1]", out var array);
+ array.Should().Equal(1, 2, 3, 2, 1);
+ }
+
+ [Fact]
+ void test_mixed_array()
+ {
+ var ok = ParseDatum("[1,2.0, <>, 1]", out var array);
+ ok.Should().BeFalse();
+ }
}