Skip to content

Commit

Permalink
Fixed numerous bugs in parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Calendis committed Sep 28, 2024
1 parent ff96b52 commit f1921fe
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 47 deletions.
63 changes: 47 additions & 16 deletions magician/algebra/Notate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static Oper Parse(string s)
{
List<Token> tokens = Tokenize(s);
Oper o = ParseExpression(tokens.ToArray());
return o;
return o.Copy();
}

internal class Token
Expand All @@ -54,7 +54,7 @@ internal Token(TokenKind tk, string s)
}
public override string ToString()
{
return $"{kind}\"{name}\"";
return $"{kind.GetType().Name}\"{name}\"";
}
}

Expand Down Expand Up @@ -166,7 +166,8 @@ internal static Oper ParseExpression(Token[] tokens)
Stack<OperBuilder> branches = new();
bool primed = false; // Primed to create an Oper object
Token? arg = null;
Token? op = null;
Token? op = new(Token.TokenKind.PLUS, "+"); // The implicit plus sign
Token? lastOp = null;
for (int i = 0; i < tokens.Length; i++)
{
bool climb = false;
Expand All @@ -187,46 +188,50 @@ internal static Oper ParseExpression(Token[] tokens)
throw Scribe.Issue($"null operator in parser");

OperBuilder newOp = new(OperBuilder.FromToken(op.kind, op.name), op.kind);
//OperBuilder? lastOp = branches.Count > 0 ? branches.Peek() : null;

// If this is the first operator, just push it
if (branches.Count == 0)
{
if (arg == null) { throw Scribe.Issue($"Null argument in initial op"); }
branches.Push(newOp);
branches.Peek().AddArg(OperBuilder.FromToken(arg.kind, arg.name));
op = null;
lastOp = op == null ? lastOp : op;; op = null;
}
// Precedence drop, eat the argument and become the current branch
else if (kindToPrecedence[branches.Peek().Kind] > kindToPrecedence[op.kind])
{
if (arg == null) { throw Scribe.Issue($"Null argument in drop"); }
branches.Peek().AddArg(OperBuilder.FromToken(arg.kind, arg.name));
List<OperBuilder> brl = branches.ToList();
newOp.AddArg(brl[brl.Count - 1].Current);
newOp.AddArg(brl[brl.Count - 1].Current, true);
newOp.AddArg(OperBuilder.FromToken(arg.kind, arg.name));
branches.Clear();
branches.Push(newOp);
op = null;

lastOp = op == null ? lastOp : op;; op = null;
}
// Precedece climb, append and push
// Precedence climb: steal the last argument, append and push
else if (kindToPrecedence[branches.Peek().Kind] < kindToPrecedence[op.kind])
{
if (arg == null) { throw Scribe.Issue($"Null argument in climb"); }
Oper stolen = branches.Peek().PopArg();
newOp.AddArg(stolen);
newOp.AddArg(OperBuilder.FromToken(arg.kind, arg.name));
branches.Peek().AddArg(newOp.Current);
branches.Push(newOp);
op = null;

lastOp = op == null ? lastOp : op;; op = null;
climb = true;
}
else
{
if (arg == null)
{
throw Scribe.Issue($"Null argument in climb");
throw Scribe.Issue($"Null argument in similar");
}
newOp.AddArg(OperBuilder.FromToken(arg.kind, arg.name));
branches.Peek().AddArg(newOp.Current);
op = null;

lastOp = op == null ? lastOp : op;; op = null;
}

if (kindToPrecedence[t.kind] == 0)
Expand All @@ -235,15 +240,16 @@ internal static Oper ParseExpression(Token[] tokens)
}
else
{
op = t;

lastOp = op == null ? lastOp : op;; op = t;
arg = null;
}
}
else
{
if (kindToPrecedence[t.kind] > 0)
{
op = t;
lastOp = op == null ? lastOp : op;; op = t;
}
else if (arg == null && !climb)
{
Expand All @@ -254,8 +260,8 @@ internal static Oper ParseExpression(Token[] tokens)
throw Scribe.Issue($"Unsupported operation");
}
}

primed = op != null && arg != null;

//last = t;
break;
case Token.TokenKind.LEFTPAREN:
Expand All @@ -271,10 +277,35 @@ internal static Oper ParseExpression(Token[] tokens)
{
throw Scribe.Issue($"Parser finished in unresolved state {branches.Count}");
}
lastOp = op == null ? lastOp : op;
// Absorb the final argument
if (arg != null)
branches.Peek().AddArg(OperBuilder.FromToken(arg.kind, arg.name));
{
if (lastOp == null)
throw Scribe.Issue("null last op");
OperBuilder finalOp = new(OperBuilder.FromToken(lastOp.kind, lastOp.name), lastOp.kind);

if (kindToPrecedence[branches.Peek().Kind] > kindToPrecedence[lastOp.kind])
{
List<OperBuilder> brl = branches.ToList();
finalOp.AddArg(brl[brl.Count-1].Current, true);
finalOp.AddArg(OperBuilder.FromToken(arg.kind, arg.name));
branches.Clear();
branches.Push(finalOp);
}
else if (kindToPrecedence[branches.Peek().Kind] < kindToPrecedence[lastOp.kind])
{
Oper stolen = branches.Peek().PopArg();
finalOp.AddArg(stolen);
finalOp.AddArg(OperBuilder.FromToken(arg.kind, arg.name));
branches.Peek().AddArg(finalOp.Current);
}
else
{
finalOp.AddArg(OperBuilder.FromToken(arg.kind, arg.name));
branches.Peek().AddArg(finalOp.Current);
}
}
List<OperBuilder> bl = branches.ToList();
return bl[bl.Count - 1].Current;
}
Expand Down
48 changes: 17 additions & 31 deletions magician/algebra/OperBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Magician.Alg;
using Magician.Alg.Symbols;
using Magician.Core;

internal struct OperBuilder
{
Expand All @@ -14,53 +15,38 @@ public OperBuilder(Oper o, Notate.Token.TokenKind tk)
k = tk;
}

public void AddArg(Oper o)
public void AddArg(Oper o, bool forcePositive=false)
{
if (o.GetType() == Current.GetType())
{
switch (k)
{
case Notate.Token.TokenKind.MINUS:
case Notate.Token.TokenKind.DIVIDEDBY:
Current.negArgs.AddRange(o.negArgs);
break;
default:
Current.posArgs.AddRange(o.posArgs);
break;
}
}
else
switch (k)
{
switch (k)
{
case Notate.Token.TokenKind.MINUS:
case Notate.Token.TokenKind.DIVIDEDBY:
case Notate.Token.TokenKind.MINUS:
case Notate.Token.TokenKind.DIVIDEDBY:
if (!forcePositive)
Current.negArgs.Add(o);
break;
default:
else
Current.posArgs.Add(o);
break;
}
break;
default:
Current.posArgs.Add(o);
break;
}
}

public Oper PopArg()
{
switch (k)
{
case Notate.Token.TokenKind.MINUS:
case Notate.Token.TokenKind.DIVIDEDBY:
Oper n = Current.negArgs[Current.negArgs.Count-1];
Current.negArgs.RemoveAt(Current.negArgs.Count-1);
return n;
Oper o = Current.negArgs[Current.negArgs.Count - 1];
Current.negArgs.RemoveAt(Current.negArgs.Count - 1);
return o;
default:
Oper p = Current.posArgs[Current.posArgs.Count-1];
Current.posArgs.RemoveAt(Current.posArgs.Count-1);
Oper p = Current.posArgs[Current.posArgs.Count - 1];
Current.posArgs.RemoveAt(Current.posArgs.Count - 1);
return p;
}
}


public override string ToString()
{
return $"({current},{k})";
Expand All @@ -71,7 +57,7 @@ public static Oper FromToken(Notate.Token.TokenKind tk, string data)
switch (tk)
{
case Notate.Token.TokenKind.SYMBOL:
return new Variable(data);
return Notate.Var(data);
case Notate.Token.TokenKind.NUMBER:
double num;
bool isInt = int.TryParse(data, out int n);
Expand Down

0 comments on commit f1921fe

Please sign in to comment.