Skip to content

Commit

Permalink
0.1.10
Browse files Browse the repository at this point in the history
  • Loading branch information
eccs0103 committed Dec 3, 2023
1 parent f168fb9 commit 3daf43c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 44 deletions.
116 changes: 77 additions & 39 deletions Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace AdaptiveCore
{
namespace ANL
{
public class Interpreter
public partial class Interpreter
{
#region Tokenizer
public class Token
Expand Down Expand Up @@ -43,7 +43,9 @@ public override string ToString()
{
{ new Regex(@"^\s+", RegexOptions.Compiled), null },
{ new Regex(@"^\d+(\.\d+)?", RegexOptions.Compiled), Token.Types.Number },
{ new Regex(@"^[+\-*/:]", RegexOptions.Compiled), Token.Types.Operator },
//{ new Regex(@"^(\+\+|--)", RegexOptions.Compiled), Token.Types.Operator },
{ new Regex(@"^(\+:|-:|\*:|/:)", RegexOptions.Compiled), Token.Types.Operator },
{ new Regex(@"^(\+|-|\*|/|:)", RegexOptions.Compiled), Token.Types.Operator },
{ new Regex(@"^[A-z]\w*", RegexOptions.Compiled), Token.Types.Identifier },
{ new Regex(@"^[()]", RegexOptions.Compiled), Token.Types.Brackets },
{ new Regex(@"^;", RegexOptions.Compiled), Token.Types.Semicolon },
Expand Down Expand Up @@ -89,13 +91,16 @@ public Token[] Tokenize(in string code)
break;
}
}
if (!hasChanges) throw new FormatException($"Invalid '{text[0]}' term");
if (!hasChanges) throw new FormatException($"Invalid {text[0]} term");
}
return tokens.ToArray();
}
#endregion
#region Parser
public abstract class Node { }
public abstract class Node
{

}
private class DataNode: Node
{
public static readonly DataNode Null = new(null);
Expand All @@ -106,9 +111,9 @@ public DataNode(double? value) : base()
public double? Value { get; }
public override string ToString() => $"{this.Value}";
}
private class ReferenceNode: Node
private class IdentifierNode: Node
{
public ReferenceNode(string path) : base()
public IdentifierNode(string path) : base()
{
this.Name = path;
}
Expand Down Expand Up @@ -150,25 +155,34 @@ public BinaryOperatorNode(string @operator, Node left, Node right) : base(@opera
};
public Node[] Parse(in Token[] tokens)
{
List<Node> trees = new();

Node Parse0(in Token[] tokens, ref int begin, int end)
static Node Parse0(in Token[] tokens, ref int begin, int end)
{
Node left = Parse1(tokens, ref begin, end);
while (begin < Min(tokens.Length, end))
{
Token token = tokens[begin];
if (token.Type == Token.Types.Operator && token.Value == ":")
if (token.Type == Token.Types.Operator)
{
begin++;
Node right = Parse1(tokens, ref begin, end);
left = new BinaryOperatorNode(token.Value, left, right);
switch (token.Value)
{
case ":":
case "+:":
case "-:":
case "*:":
case "/:":
{
begin++;
Node right = Parse1(tokens, ref begin, end);
left = new BinaryOperatorNode(token.Value, left, right);
}
break;
}
}
else break;
}
return left;
}
Node Parse1(in Token[] tokens, ref int begin, int end)
static Node Parse1(in Token[] tokens, ref int begin, int end)
{
Node left = Parse2(tokens, ref begin, end);
while (begin < Min(tokens.Length, end))
Expand All @@ -184,7 +198,7 @@ Node Parse1(in Token[] tokens, ref int begin, int end)
}
return left;
}
Node Parse2(in Token[] tokens, ref int begin, int end)
static Node Parse2(in Token[] tokens, ref int begin, int end)
{
Node left = Parse3(tokens, ref begin, end);
while (begin < Min(tokens.Length, end))
Expand All @@ -200,22 +214,20 @@ Node Parse2(in Token[] tokens, ref int begin, int end)
}
return left;
}
Node Parse3(in Token[] tokens, ref int begin, int end)
static Node Parse3(in Token[] tokens, ref int begin, int end)
{
if (begin < Min(tokens.Length, end))
{
Token token = tokens[begin];
if (token.Type == Token.Types.Number)
{
double value = Convert.ToDouble(token.Value, CultureInfo.GetCultureInfo("en-US"));
Node node = new DataNode(value);
Node node = new DataNode(Convert.ToDouble(token.Value, CultureInfo.GetCultureInfo("en-US")));
begin++;
return node;
}
else if (token.Type == Token.Types.Identifier)
{
string value = token.Value;
Node node = new ReferenceNode(value);
Node node = new IdentifierNode(token.Value);
begin++;
return node;
}
Expand Down Expand Up @@ -276,6 +288,7 @@ Node Parse3(in Token[] tokens, ref int begin, int end)
else throw new NullReferenceException($"Expected expression");
}

List<Node> trees = new();
for (int index = 0; index < tokens.Length;)
{
Node tree = Parse0(tokens, ref index, tokens.Length);
Expand All @@ -292,12 +305,24 @@ Node Parse3(in Token[] tokens, ref int begin, int end)
#region Evalutor
private class Data
{
public Data(double? value)
public Data(double? value, string type = "Number")
{
this.Value = value;
this.Type = type;
}
public double? Value { get; set; }
public readonly string Type;
public bool Writeable { get; set; } = true;
private double? value;
public double? Value
{
get => this.value;
set
{
this.value = this.Writeable
? value
: throw new InvalidOperationException($"Data is non-writeable");
}
}
}
private readonly Dictionary<string, Data> memory = new()
{
Expand All @@ -312,11 +337,11 @@ DataNode ToDataNode(in Node node)
{
return nodeData;
}
else if (node is ReferenceNode nodeReference)
else if (node is IdentifierNode nodeIdentifier)
{
return this.memory.TryGetValue(nodeReference.Name, out Data? data)
return this.memory.TryGetValue(nodeIdentifier.Name, out Data? data)
? new DataNode(data.Value)
: throw new Exception($"Identifier '{nodeReference.Name}' does not exist");
: throw new Exception($"Identifier '{nodeIdentifier.Name}' does not exist");
}
else if (node is UnaryOperatorNode nodeUnaryOperator)
{
Expand All @@ -329,7 +354,7 @@ DataNode ToDataNode(in Node node)
}
case "data":
{
return ToDataNode(ToReferenceNode(nodeUnaryOperator));
return ToDataNode(ToIdentifierNode(nodeUnaryOperator));
}
case "print":
{
Expand Down Expand Up @@ -361,35 +386,39 @@ DataNode ToDataNode(in Node node)
};
}
case ":":
case "+:":
case "-:":
case "*:":
case "/:":
{
return ToDataNode(ToReferenceNode(nodeBinaryOperator));
return ToDataNode(ToIdentifierNode(nodeBinaryOperator));
}
default: throw new ArgumentException($"Invalid {nodeBinaryOperator.Operator} operator");
}
}
else throw new ArgumentException($"Invalid expression {node}");
}
ReferenceNode ToReferenceNode(in Node node)
IdentifierNode ToIdentifierNode(in Node node)
{
if (node is ReferenceNode nodeReference)
if (node is IdentifierNode nodeIdentifier)
{
return nodeReference;
return nodeIdentifier;
}
else if (node is UnaryOperatorNode nodeUnaryOperator)
{
switch (nodeUnaryOperator.Operator)
{
case "data":
{
if (nodeUnaryOperator.Target is ReferenceNode nodeReferenceTarget)
if (nodeUnaryOperator.Target is IdentifierNode nodeIdentifierTarget)
{
if (!this.memory.TryAdd(nodeReferenceTarget.Name, new Data(null)))
if (!this.memory.TryAdd(nodeIdentifierTarget.Name, new Data(null)))
{
throw new ArgumentException($"Identifier '{nodeReferenceTarget.Name}' already exists");
throw new ArgumentException($"Identifier '{nodeIdentifierTarget.Name}' already exists");
}
}
else throw new ArgumentException($"Identifier expected");
return nodeReferenceTarget;
return nodeIdentifierTarget;
}
default: throw new ArgumentException($"Invalid {nodeUnaryOperator.Operator} keyword");
}
Expand All @@ -401,13 +430,22 @@ ReferenceNode ToReferenceNode(in Node node)
case ":":
{
DataNode nodeDataRight = ToDataNode(nodeBinaryOperator.Right);
ReferenceNode nodeReferenceLeft = ToReferenceNode(nodeBinaryOperator.Left);
if (!this.memory.ContainsKey(nodeReferenceLeft.Name)) throw new Exception($"Identifier '{nodeReferenceLeft.Name}' does not exist");
Data data = this.memory[nodeReferenceLeft.Name];
IdentifierNode nodeIdentifierLeft = ToIdentifierNode(nodeBinaryOperator.Left);
if (!this.memory.ContainsKey(nodeIdentifierLeft.Name)) throw new Exception($"Identifier '{nodeIdentifierLeft.Name}' does not exist");
Data data = this.memory[nodeIdentifierLeft.Name];
data.Value = data.Writeable
? nodeDataRight.Value
: throw new InvalidOperationException($"Identifier '{nodeReferenceLeft.Name}' is non-writeable");
return nodeReferenceLeft;
: throw new InvalidOperationException($"Identifier '{nodeIdentifierLeft.Name}' is non-writeable");
return nodeIdentifierLeft;
}
case "+:":
case "-:":
case "*:":
case "/:":
{
DataNode nodeDataRight = ToDataNode(nodeBinaryOperator.Right);
IdentifierNode nodeIdentifierLeft = ToIdentifierNode(nodeBinaryOperator.Left);
return ToIdentifierNode(new BinaryOperatorNode(":", nodeIdentifierLeft, new BinaryOperatorNode(nodeBinaryOperator.Operator[0..1], nodeIdentifierLeft, nodeDataRight)));
}
default: throw new ArgumentException($"Invalid {nodeBinaryOperator.Operator} operator");
}
Expand Down
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,34 @@

## Feed

### Update 0.1.10 (04.12.2023)
- Added operators `+:`, `-:`, `*:`, `/:`.
```anl
data A;
A +: 3;
A : A + 3;
```
- Optimized token parsing.

### Update 0.1.9 (29.11.2023)
- Added the keyword `null`. To use a missing value, it's necessary to explicitly use `null`. The absence of a value is no longer automatically considered as `null`.
```anl
data A: null;
data A : null;
```
- Improved recognition of semicolons.
- Now the initial variables `E` and `Pi` are considered non-writable. Their values cannot be changed.
- Improved adaptability and interpretation of variables.
```anl
print(data A: 5);
print(data A : 5);
```
- Fixed a bug where it was possible to initialize a variable with itself.


### Update 0.1.7 (28.11.2023)
- Now you can execute code with multiple instructions.
```anl
data A: 1;
data B: 2;
data A : 1;
data B : 2;
print(A);
print(B);
```
Expand All @@ -30,7 +39,7 @@ print(7 + -4);
```
- Improved language adaptability. Now, the absence of a value anywhere will be interpreted as `null`;
```anl
data A: ();
data A : ();
print(A);
```
- Changed syntax. Now it's mandatory to put a semicolon after each instruction.
Expand Down

0 comments on commit 3daf43c

Please sign in to comment.