Skip to content

Commit

Permalink
🔀 Merge pull request #1 from Coding-Cactus/declare_variables
Browse files Browse the repository at this point in the history
✨ Add declaration of variables
  • Loading branch information
Coding-Cactus authored Jul 26, 2022
2 parents d93aecc + 656f024 commit 5b12851
Show file tree
Hide file tree
Showing 19 changed files with 728 additions and 22 deletions.
29 changes: 24 additions & 5 deletions Bow/Bow/Bow.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
using Errors;
using Parse;
using Parse.Statements;
using Parse.Environment;

using Interpret;

using Errors;
using Tokenise;

public class Bow
{
private readonly string _code;
private readonly bool _debug;

public Bow(string fileName)
public Bow(string fileName, bool debug=false)
{
_code = String.Join("\n", File.ReadAllLines(fileName));
_debug = debug;
}

public void Run()
{
try
{
List<Token> tokens = new Lexer(_code).ScanTokens();
foreach (var token in tokens)
if (_debug)
{
foreach (var token in tokens)
{
Console.WriteLine(token.Inspect());
}
}

List<Statement> statements = new Parser(tokens).Parse();
new Interpreter(statements).Interpret();

if (_debug)
{
Console.WriteLine(token.Inspect());
Env.OutputVariables();
}
}
catch (BowSyntaxError ex)
{
Console.WriteLine(ex);
Console.WriteLine($"\x1B[91m{(_debug ? ex : ex.Message)}\x1B[0m");
}
}
}
12 changes: 12 additions & 0 deletions Bow/Bow/Errors/BowNameError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Errors;

[Serializable]
public class BowNameError : Exception
{
public BowNameError() : base() { }
public BowNameError(string message) : base(message) { }
public BowNameError(string message, Exception inner) : base(message, inner) { }

protected BowNameError(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
12 changes: 12 additions & 0 deletions Bow/Bow/Errors/BowRuntimeError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Errors;

[Serializable]
public class BowRuntimeError : Exception
{
public BowRuntimeError() : base() { }
public BowRuntimeError(string message) : base(message) { }
public BowRuntimeError(string message, Exception inner) : base(message, inner) { }

protected BowRuntimeError(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
21 changes: 21 additions & 0 deletions Bow/Bow/Interpret/Interpreter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Parse.Statements;

namespace Interpret;

public class Interpreter
{
private readonly List<Statement> _statements;

public Interpreter(List<Statement> statements)
{
_statements = statements;
}

public void Interpret()
{
foreach (var statement in _statements)
{
statement.Interpret();
}
}
}
80 changes: 80 additions & 0 deletions Bow/Bow/Parse/Environment/Env.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using Errors;
using Tokenise;

namespace Parse.Environment;

public class Env
{
private static readonly List<Env> Scopes = new() { new Env() };
private readonly Dictionary<string, Symbol> _variables;

public Env()
{
_variables = new Dictionary<string, Symbol>();
}

public static void PushScope(Env env)
{
Scopes.Insert(0, env);
}

public static void PopScope()
{
Scopes.RemoveAt(0);
}

public static void AddVariable(Symbol symbol)
{
Env scope = Scopes[0];

if (!scope._variables.ContainsKey(symbol.Name))
{
scope._variables.Add(symbol.Name, symbol);
}
}

public static Symbol GetVariable(string name)
{
foreach (Env scope in Scopes)
{
if (scope._variables.ContainsKey(name))
{
return scope._variables[name];
}
}

throw new BowNameError($"Variable '{name}' not found");
}

public static bool IsVariableDefined(string name)
{
try
{
GetVariable(name);
return true;
}
catch (BowNameError)
{
return false;
}
}

public static void OutputVariables()
{
Console.WriteLine("\nVariables:");
foreach (Env scope in Scopes)
{
foreach (KeyValuePair<string, Symbol> pair in scope._variables)
{
string value = pair.Value.Value;

if (pair.Value.Type == TokenType.Str)
{
value = $"\"{value}\"";
}

Console.WriteLine($"{pair.Key} = {value}");
}
}
}
}
21 changes: 21 additions & 0 deletions Bow/Bow/Parse/Environment/Symbol.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Errors;

namespace Parse.Environment;

public class Symbol
{
public string Name { get; }
public string Type { get; }
public string Value { get; }
public int Line { get; }
public bool IsConstant { get; set; }

public Symbol(string name, string type, string value, int line, bool isConstant)
{
Name = name;
Type = type;
Value = value;
Line = line;
IsConstant = isConstant;
}
}
66 changes: 66 additions & 0 deletions Bow/Bow/Parse/Expressions/BinaryExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Globalization;
using Errors;
using Tokenise;

using Parse.Expressions.Literals;

namespace Parse.Expressions;

public class BinaryExpression : Expression
{
private readonly Expression _left;
private readonly Expression _right;
private readonly Token _operator;
private readonly int _line;

public BinaryExpression(Expression left, Token op, Expression right, int line)
{
_left = left;
_right = right;
_operator = op;
_line = line;
}

public override Literal Evaluate()
{
Literal left = _left.Evaluate();
Literal right = _right.Evaluate();

if (left.Type != right.Type)
{
throw new BowSyntaxError($"Cannot perform operation on two different types on line {_line}");
}

switch (left.Type)
{
case TokenType.BooLiteral:
throw new BowSyntaxError($"Can't perform operations on booleans on line {_line}");
case TokenType.StrLiteral:
return _operator.Type switch
{
TokenType.Plus => new Literal(left.Value + right.Value, TokenType.StrLiteral),
_ => throw new BowSyntaxError(
$"Can't perform {_operator.Type} operation on strings on line {_line}")
};
case TokenType.DecLiteral:
double leftDec = double.Parse(left.Value);
double rightDec = double.Parse(right.Value);

return _operator.Type switch
{
TokenType.Plus => new Literal((leftDec + rightDec).ToString(CultureInfo.CurrentCulture),
TokenType.DecLiteral),
TokenType.Minus => new Literal((leftDec - rightDec).ToString(CultureInfo.CurrentCulture),
TokenType.DecLiteral),
TokenType.Star => new Literal((leftDec * rightDec).ToString(CultureInfo.CurrentCulture),
TokenType.DecLiteral),
TokenType.Slash => new Literal((leftDec / rightDec).ToString(CultureInfo.CurrentCulture),
TokenType.DecLiteral),
_ => throw new BowSyntaxError(
$"Can't perform `{_operator.Type} operation on decimals on line {_line}")
};
default:
throw new BowSyntaxError($"Can't perform operations on {left.Type} on line {_line}");
}
}
}
11 changes: 11 additions & 0 deletions Bow/Bow/Parse/Expressions/Expression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Parse.Expressions.Literals;

namespace Parse.Expressions;

public class Expression
{
public virtual Literal Evaluate()
{
throw new NotImplementedException();
}
}
20 changes: 20 additions & 0 deletions Bow/Bow/Parse/Expressions/LiteralExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Parse.Expressions.Literals;

namespace Parse.Expressions;

public class LiteralExpression : Expression
{
private Literal _value;
private int _line;

public LiteralExpression(Literal value, int line)
{
_value = value;
_line = line;
}

public override Literal Evaluate()
{
return _value;
}
}
13 changes: 13 additions & 0 deletions Bow/Bow/Parse/Expressions/Literals/Literal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Parse.Expressions.Literals;

public class Literal
{
public string Value { get; }
public string Type { get; }

public Literal(string value, string type)
{
Value = value;
Type = type;
}
}
37 changes: 37 additions & 0 deletions Bow/Bow/Parse/Expressions/UnaryExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Globalization;
using Errors;
using Tokenise;
using Parse.Expressions.Literals;

namespace Parse.Expressions;

public class UnaryExpression : Expression
{
private readonly Expression _right;
private readonly Token _operator;
private readonly int _line;

public UnaryExpression(Token op, Expression right, int line)
{
_right = right;
_operator = op;
_line = line;
}

public override Literal Evaluate()
{
Literal right = _right.Evaluate();

switch (_operator.Type)
{
case TokenType.Minus:
if (right.Type != TokenType.DecLiteral)
{
throw new BowSyntaxError($"Can't negate non-decimal value on line {_line}");
}
return new Literal((-double.Parse(right.Value)).ToString(CultureInfo.CurrentCulture), TokenType.DecLiteral);
default:
throw new BowSyntaxError($"Can't perform `{_operator.Type} operation {right.Type} on line {_line}");
}
}
}
23 changes: 23 additions & 0 deletions Bow/Bow/Parse/Expressions/VariableExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Parse.Environment;
using Parse.Expressions.Literals;

namespace Parse.Expressions;

public class VariableExpression : Expression
{
private readonly string _name;
private readonly int _line;

public VariableExpression(string name, int line)
{
_name = name;
_line = line;
}

public override Literal Evaluate()
{
Symbol var = Env.GetVariable(_name);

return new Literal(var.Value, var.Type);
}
}
Loading

0 comments on commit 5b12851

Please sign in to comment.