init
This commit is contained in:
4
Nub.Lang/.idea/.idea.Nub.Lang/.idea/encodings.xml
generated
Normal file
4
Nub.Lang/.idea/.idea.Nub.Lang/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
8
Nub.Lang/.idea/.idea.Nub.Lang/.idea/indexLayout.xml
generated
Normal file
8
Nub.Lang/.idea/.idea.Nub.Lang/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
Nub.Lang/.idea/.idea.Nub.Lang/.idea/vcs.xml
generated
Normal file
6
Nub.Lang/.idea/.idea.Nub.Lang/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
16
Nub.Lang/Nub.Lang.sln
Normal file
16
Nub.Lang/Nub.Lang.sln
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nub.Lang", "Nub.Lang\Nub.Lang.csproj", "{5047E21F-590D-4CB3-AFF3-064316485009}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{5047E21F-590D-4CB3-AFF3-064316485009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5047E21F-590D-4CB3-AFF3-064316485009}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5047E21F-590D-4CB3-AFF3-064316485009}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5047E21F-590D-4CB3-AFF3-064316485009}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
14
Nub.Lang/Nub.Lang/Input/program.nub
Normal file
14
Nub.Lang/Nub.Lang/Input/program.nub
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
let SYS_WRITE = 1;
|
||||||
|
let STD_IN = 0;
|
||||||
|
let STD_OUT = 1;
|
||||||
|
let STD_ERR = 2;
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
write("test");
|
||||||
|
syscall(SYS_WRITE, STD_OUT, msg);
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(msg: void) {
|
||||||
|
syscall(SYS_WRITE, STD_OUT, msg);
|
||||||
|
}
|
||||||
6
Nub.Lang/Nub.Lang/Lexing/IdentifierToken.cs
Normal file
6
Nub.Lang/Nub.Lang/Lexing/IdentifierToken.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Nub.Lang.Lexing;
|
||||||
|
|
||||||
|
public class IdentifierToken(string value) : Token
|
||||||
|
{
|
||||||
|
public string Value { get; } = value;
|
||||||
|
}
|
||||||
131
Nub.Lang/Nub.Lang/Lexing/Lexer.cs
Normal file
131
Nub.Lang/Nub.Lang/Lexing/Lexer.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using Nub.Lib;
|
||||||
|
|
||||||
|
namespace Nub.Lang.Lexing;
|
||||||
|
|
||||||
|
public class Lexer
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<string, Symbol> Keywords = new()
|
||||||
|
{
|
||||||
|
["func"] = Symbol.Func,
|
||||||
|
["return"] = Symbol.Return,
|
||||||
|
["let"] = Symbol.Let,
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly Dictionary<char, Symbol> Chars = new()
|
||||||
|
{
|
||||||
|
[';'] = Symbol.Semicolon,
|
||||||
|
[':'] = Symbol.Colon,
|
||||||
|
['('] = Symbol.OpenParen,
|
||||||
|
[')'] = Symbol.CloseParen,
|
||||||
|
['{'] = Symbol.OpenBrace,
|
||||||
|
['}'] = Symbol.CloseBrace,
|
||||||
|
['['] = Symbol.OpenBracket,
|
||||||
|
[']'] = Symbol.CloseBracket,
|
||||||
|
[','] = Symbol.Comma,
|
||||||
|
['.'] = Symbol.Period,
|
||||||
|
['='] = Symbol.Assign,
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly string _src;
|
||||||
|
private int _index;
|
||||||
|
|
||||||
|
public Lexer(string src)
|
||||||
|
{
|
||||||
|
_src = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Token> Lex()
|
||||||
|
{
|
||||||
|
_index = 0;
|
||||||
|
List<Token> tokens = [];
|
||||||
|
while (Peek().HasValue)
|
||||||
|
{
|
||||||
|
tokens.Add(ParseToken());
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Token ParseToken()
|
||||||
|
{
|
||||||
|
var current = Peek();
|
||||||
|
|
||||||
|
if (char.IsLetter(current.Value) || current.Value == '_')
|
||||||
|
{
|
||||||
|
var buffer = string.Empty;
|
||||||
|
|
||||||
|
while (current.HasValue && (char.IsLetterOrDigit(current.Value) || current.Value == '_'))
|
||||||
|
{
|
||||||
|
buffer += current.Value;
|
||||||
|
Next();
|
||||||
|
current = Peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Keywords.TryGetValue(buffer, out var keywordSymbol))
|
||||||
|
{
|
||||||
|
return new SymbolToken(keywordSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IdentifierToken(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (char.IsDigit(current.Value))
|
||||||
|
{
|
||||||
|
var buffer = string.Empty;
|
||||||
|
|
||||||
|
while (current.HasValue && char.IsDigit(current.Value))
|
||||||
|
{
|
||||||
|
buffer += current.Value;
|
||||||
|
Next();
|
||||||
|
current = Peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LiteralToken(Type.Int32, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Chars.TryGetValue(current.Value, out var charSymbol))
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
return new SymbolToken(charSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current.Value == '"')
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
var buffer = string.Empty;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
current = Peek();
|
||||||
|
Next();
|
||||||
|
if (!current.HasValue) throw new Exception("Unclosed string literal");
|
||||||
|
if (current.Value == '"') break;
|
||||||
|
buffer += current.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LiteralToken(Type.Pointer, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (char.IsWhiteSpace(current.Value))
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
return new SymbolToken(Symbol.Whitespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Unknown character {current.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<char> Peek()
|
||||||
|
{
|
||||||
|
if (_index < _src.Length)
|
||||||
|
{
|
||||||
|
return _src[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional<char>.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Next()
|
||||||
|
{
|
||||||
|
_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Nub.Lang/Nub.Lang/Lexing/LiteralToken.cs
Normal file
7
Nub.Lang/Nub.Lang/Lexing/LiteralToken.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Lexing;
|
||||||
|
|
||||||
|
public class LiteralToken(Type type, string value) : Token
|
||||||
|
{
|
||||||
|
public Type Type { get; } = type;
|
||||||
|
public string Value { get; } = value;
|
||||||
|
}
|
||||||
25
Nub.Lang/Nub.Lang/Lexing/SymbolToken.cs
Normal file
25
Nub.Lang/Nub.Lang/Lexing/SymbolToken.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
namespace Nub.Lang.Lexing;
|
||||||
|
|
||||||
|
public class SymbolToken(Symbol symbol) : Token
|
||||||
|
{
|
||||||
|
public Symbol Symbol { get; } = symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Symbol
|
||||||
|
{
|
||||||
|
Whitespace,
|
||||||
|
Func,
|
||||||
|
Return,
|
||||||
|
Let,
|
||||||
|
Semicolon,
|
||||||
|
Colon,
|
||||||
|
OpenParen,
|
||||||
|
CloseParen,
|
||||||
|
OpenBrace,
|
||||||
|
CloseBrace,
|
||||||
|
OpenBracket,
|
||||||
|
CloseBracket,
|
||||||
|
Comma,
|
||||||
|
Period,
|
||||||
|
Assign
|
||||||
|
}
|
||||||
3
Nub.Lang/Nub.Lang/Lexing/Token.cs
Normal file
3
Nub.Lang/Nub.Lang/Lexing/Token.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Nub.Lang.Lexing;
|
||||||
|
|
||||||
|
public abstract class Token;
|
||||||
14
Nub.Lang/Nub.Lang/Nub.Lang.csproj
Normal file
14
Nub.Lang/Nub.Lang/Nub.Lang.csproj
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Nub.Lib" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
6
Nub.Lang/Nub.Lang/Parsing/BlockNode.cs
Normal file
6
Nub.Lang/Nub.Lang/Parsing/BlockNode.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class BlockNode(IEnumerable<StatementNode> statements) : StatementNode
|
||||||
|
{
|
||||||
|
public IEnumerable<StatementNode> Statements { get; } = statements;
|
||||||
|
}
|
||||||
3
Nub.Lang/Nub.Lang/Parsing/DefinitionNode.cs
Normal file
3
Nub.Lang/Nub.Lang/Parsing/DefinitionNode.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public abstract class DefinitionNode : Node;
|
||||||
11
Nub.Lang/Nub.Lang/Parsing/ExpressionNode.cs
Normal file
11
Nub.Lang/Nub.Lang/Parsing/ExpressionNode.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public abstract class ExpressionNode : Node
|
||||||
|
{
|
||||||
|
private Type? _type;
|
||||||
|
public Type Type
|
||||||
|
{
|
||||||
|
get => _type ?? throw new Exception("Tried to access expression type before type was populated");
|
||||||
|
set => _type = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Nub.Lang/Nub.Lang/Parsing/FuncDefinitionNode.cs
Normal file
7
Nub.Lang/Nub.Lang/Parsing/FuncDefinitionNode.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class FuncDefinitionNode(string name, IEnumerable<FuncParameter> parameters) : DefinitionNode
|
||||||
|
{
|
||||||
|
public string Name { get; } = name;
|
||||||
|
public IEnumerable<FuncParameter> Parameters { get; } = parameters;
|
||||||
|
}
|
||||||
7
Nub.Lang/Nub.Lang/Parsing/FuncParameter.cs
Normal file
7
Nub.Lang/Nub.Lang/Parsing/FuncParameter.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class FuncParameter(string name, Type type)
|
||||||
|
{
|
||||||
|
public string Name { get; } = name;
|
||||||
|
public Type Type { get; } = type;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class GlobalVariableDefinitionNode(string name, ExpressionNode value) : DefinitionNode
|
||||||
|
{
|
||||||
|
public string Name { get; } = name;
|
||||||
|
public ExpressionNode Value { get; } = value;
|
||||||
|
}
|
||||||
3
Nub.Lang/Nub.Lang/Parsing/Node.cs
Normal file
3
Nub.Lang/Nub.Lang/Parsing/Node.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public abstract class Node;
|
||||||
95
Nub.Lang/Nub.Lang/Parsing/Parser.cs
Normal file
95
Nub.Lang/Nub.Lang/Parsing/Parser.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
using Nub.Lang.Lexing;
|
||||||
|
using Nub.Lib;
|
||||||
|
|
||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class Parser
|
||||||
|
{
|
||||||
|
private readonly Token[] _tokens;
|
||||||
|
private int _index;
|
||||||
|
|
||||||
|
public Parser(IEnumerable<Token> tokens)
|
||||||
|
{
|
||||||
|
_tokens = tokens.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<DefinitionNode> Parse()
|
||||||
|
{
|
||||||
|
List<DefinitionNode> definitions = [];
|
||||||
|
while (Peek().HasValue)
|
||||||
|
{
|
||||||
|
definitions.Add(ParseDefinition());
|
||||||
|
}
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefinitionNode ParseDefinition()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Token ExpectToken()
|
||||||
|
{
|
||||||
|
var token = Peek();
|
||||||
|
if (!token.HasValue)
|
||||||
|
{
|
||||||
|
throw new Exception("Reached end of tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
return token.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SymbolToken ExpectSymbol()
|
||||||
|
{
|
||||||
|
var token = ExpectToken();
|
||||||
|
if (token is not SymbolToken symbol)
|
||||||
|
{
|
||||||
|
throw new Exception($"Expected {nameof(SymbolToken)} but got {token.GetType().Name}");
|
||||||
|
}
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExpectSymbol(Symbol symbol)
|
||||||
|
{
|
||||||
|
var token = ExpectSymbol();
|
||||||
|
if (token.Symbol != symbol)
|
||||||
|
{
|
||||||
|
throw new Exception($"Expected symbol {symbol} but got {token.Symbol}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IdentifierToken ExpectIdentifier()
|
||||||
|
{
|
||||||
|
var token = ExpectToken();
|
||||||
|
if (token is not IdentifierToken identifier)
|
||||||
|
{
|
||||||
|
throw new Exception($"Expected {nameof(IdentifierToken)} but got {token.GetType().Name}");
|
||||||
|
}
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LiteralToken ExpectLiteral()
|
||||||
|
{
|
||||||
|
var token = ExpectToken();
|
||||||
|
if (token is not LiteralToken literal)
|
||||||
|
{
|
||||||
|
throw new Exception($"Expected {nameof(LiteralToken)} but got {token.GetType().Name}");
|
||||||
|
}
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Token> Peek()
|
||||||
|
{
|
||||||
|
if (_index < _tokens.Length)
|
||||||
|
{
|
||||||
|
return _tokens[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional<Token>.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Next()
|
||||||
|
{
|
||||||
|
_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Nub.Lang/Nub.Lang/Parsing/StatementNode.cs
Normal file
3
Nub.Lang/Nub.Lang/Parsing/StatementNode.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public abstract class StatementNode : Node;
|
||||||
11
Nub.Lang/Nub.Lang/Parsing/SyscallNode.cs
Normal file
11
Nub.Lang/Nub.Lang/Parsing/SyscallNode.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class ESyscallNode(IEnumerable<FuncParameter> parameters) : ExpressionNode
|
||||||
|
{
|
||||||
|
public IEnumerable<FuncParameter> Parameters { get; } = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SSyscallNode(IEnumerable<FuncParameter> parameters) : StatementNode
|
||||||
|
{
|
||||||
|
public IEnumerable<FuncParameter> Parameters { get; } = parameters;
|
||||||
|
}
|
||||||
7
Nub.Lang/Nub.Lang/Parsing/VariableAssignmentNode.cs
Normal file
7
Nub.Lang/Nub.Lang/Parsing/VariableAssignmentNode.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Parsing;
|
||||||
|
|
||||||
|
public class VariableAssignmentNode(string name, ExpressionNode value) : StatementNode
|
||||||
|
{
|
||||||
|
public string Name { get; } = name;
|
||||||
|
public ExpressionNode Value { get; } = value;
|
||||||
|
}
|
||||||
6
Nub.Lang/Nub.Lang/Program.cs
Normal file
6
Nub.Lang/Nub.Lang/Program.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
using Nub.Lang.Lexing;
|
||||||
|
|
||||||
|
var src = File.ReadAllText(args[0]);
|
||||||
|
|
||||||
|
var lexer = new Lexer(src);
|
||||||
|
var tokens = lexer.Lex();
|
||||||
26
Nub.Lang/Nub.Lang/Type.cs
Normal file
26
Nub.Lang/Nub.Lang/Type.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
namespace Nub.Lang;
|
||||||
|
|
||||||
|
public class Type(string name)
|
||||||
|
{
|
||||||
|
public static Type Bool => new("bool");
|
||||||
|
public static Type Char => new("char");
|
||||||
|
|
||||||
|
public static Type Int8 => new("int8");
|
||||||
|
public static Type UInt8 => new("uint8");
|
||||||
|
|
||||||
|
public static Type Int16 => new("int16");
|
||||||
|
public static Type UInt16 => new("uint16");
|
||||||
|
|
||||||
|
public static Type Int32 => new("int32");
|
||||||
|
public static Type UInt32 => new("uint32");
|
||||||
|
|
||||||
|
public static Type Int64 => new("int64");
|
||||||
|
public static Type UInt64 => new("uint64");
|
||||||
|
|
||||||
|
public static Type Float => new("char");
|
||||||
|
public static Type Double => new("double");
|
||||||
|
|
||||||
|
public static Type Pointer => new("pointer");
|
||||||
|
|
||||||
|
public string Name = name;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user