Implement collapse instruction. Update docs.

This commit is contained in:
2022-10-29 16:22:35 +08:00
parent c0d6b89edc
commit 4101ee8c8e
3 changed files with 84 additions and 26 deletions

View File

@@ -77,15 +77,42 @@ namespace Cryville.Common.Pdt {
return string.Format("op {0}({1})", Name, ParamCount);
}
}
public class Collapse : PdtInstruction {
private string m_name;
public string Name { get { return m_name; } }
public LinkedListNode<PdtInstruction> Target { get; private set; }
public Collapse(string name, LinkedListNode<PdtInstruction> target) {
m_name = name;
Target = target;
}
internal override void Execute(PdtEvaluatorBase etor) {
etor.Collapse(ref m_name, Target);
}
public override string ToString() {
return string.Format("col {0}{{{1}}}", Name, Target.Value);
}
}
}
public partial class PdtInterpreter<T> {
readonly static Dictionary<char, int> pri = new Dictionary<char, int> {
{ '*', 5 }, { '/', 5 }, { '%', 5 },
{ '+', 4 }, { '-', 4 },
{ '=', 3 }, { '<', 3 }, { '>', 3 },
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
{ '*', 6 }, { '/', 6 }, { '%', 6 },
{ '+', 5 }, { '-', 5 },
{ '=', 4 }, { '<', 4 }, { '>', 4 },
{ '!', 3 },
{ '&', 2 },
{ '|', 1 }, { '!', 1 },
{ '|', 1 },
{ ',', 0 },
{ '$', -1 },
};
readonly static Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
{ '*', 0 }, { '/', 0 }, { '%', 0 },
{ '+', 0 }, { '-', 0 },
{ '=', 0 }, { '<', 0 }, { '>', 0 },
{ '!', 0 },
{ '&', 1 },
{ '|', 1 },
{ ',', -2 },
{ '$', -1 },
};
readonly static PdtExpression _emptyexp;
@@ -118,7 +145,7 @@ namespace Cryville.Common.Pdt {
}
public readonly static PdtExpToken EmptyOperator = new PdtExpToken {
Type = 0x0080,
Value = "",
Value = "$",
};
}
@@ -131,7 +158,7 @@ namespace Cryville.Common.Pdt {
/// <list type="bullet">
/// <item><term><c>-2</c></term><description>The expression is in a root scope which ends at a semicolon.</description></item>
/// <item><term><c>-1</c></term><description>The expression is in a bracketed scope which ends at a closing parenthesis.</description></item>
/// <item><term>Any non-negative values</term><description>The expression is in an auxiliary scope which ends before a closing parenthesis or an operator whose priority is lower (less) than the value of this parameter.</description></item>
/// <item><term>Any non-negative values</term><description>The expression is in an auxiliary scope which ends before a closing parenthesis or an operator whose priority is lower (less) than or equal to the value of this parameter.</description></item>
/// </list>
/// </param>
/// <param name="pc">The parameter count in this (sub)expression.</param>
@@ -140,25 +167,33 @@ namespace Cryville.Common.Pdt {
PdtExpToken InterpretExp(LinkedList<PdtInstruction> ins, int enc, out int pc, PdtExpToken? token = null) {
PdtExpToken t1, t2;
int insc0 = ins.Count;
Dictionary<LinkedListNode<PdtInstruction>, string> colp = null;
pc = 1;
if (token == null) t1 = PdtExpToken.EmptyOperator;
else t1 = token.Value;
else {
t1 = token.Value;
if (OP_TYPE[t1.Value[0]] == 1)
colp = new Dictionary<LinkedListNode<PdtInstruction>, string> { { ins.Last, token.Value.Value } };
}
while (true) {
t2 = InterpretExpBlock(ins);
panic:
switch (t2.Type) {
case 0x0080:
if (t1.Value != "") {
int p1 = pri[t1.Value[0]];
int p2 = pri[t2.Value[0]];
if (OP_TYPE[t1.Value[0]] != -1) {
int p1 = OP_PRIORITY[t1.Value[0]];
int p2 = OP_PRIORITY[t2.Value[0]];
if (p2 <= enc) goto exit;
if (p2 > p1) {
int _;
t2 = InterpretExp(ins, p1, out _, t2);
goto panic;
}
if (t1.Value != ",") ins.AddLast(new PdtInstruction.Operate(t1.Value, 2));
else pc++;
switch (OP_TYPE[t1.Value[0]]) {
case 0: ins.AddLast(new PdtInstruction.Operate(t1.Value, 2)); break;
case 1: colp.Add(ins.Last, t2.Value); break;
default: pc++; break;
}
}
t1 = t2;
break;
@@ -171,8 +206,14 @@ namespace Cryville.Common.Pdt {
}
}
exit:
if (t1.Value != "," && t1.Value != "") ins.AddLast(new PdtInstruction.Operate(t1.Value, 2));
else if (t1.Value == ",") pc++;
switch (OP_TYPE[t1.Value[0]]) {
case 0: ins.AddLast(new PdtInstruction.Operate(t1.Value, 2)); break;
case 1:
foreach (var p in colp)
ins.AddAfter(p.Key, new PdtInstruction.Collapse(p.Value, ins.Last));
break;
case -2: pc++; break;
}
return t2;
}