Initial Commit

This commit is contained in:
Michael Nolan 2022-09-07 11:10:42 -05:00
commit af59ea75ca
8 changed files with 1179 additions and 0 deletions

133
.gitignore vendored Normal file
View File

@ -0,0 +1,133 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.svclog
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
*.azurePubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
packages/
## TODO: If the tool you use requires repositories.config, also uncomment the next line
!packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
![Ss]tyle[Cc]op.targets
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac desktop service store files
.DS_Store
_NCrunch*

26
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net6.0/dumbcompiler.dll",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}

41
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/dumbcompiler.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/dumbcompiler.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/dumbcompiler.csproj"
],
"problemMatcher": "$msCompile"
}
]
}

756
AST.cs Normal file
View File

@ -0,0 +1,756 @@
using System.Linq;
using System.Collections.Generic;
using System.Text;
namespace TLang
{
public class Parser
{
private static bool _checkForArrayType(ref int i,List<LexToken> tokens)
{
if(i+2 < tokens.Count && tokens[i+1].Type == LexSymbol.Symbol && tokens[i+2].Type == LexSymbol.Symbol && tokens[i+1].TokenText == "[" && tokens[i+2].TokenText == "]")
{
//we are getting somewhere
//type normal parse
//type [ ] normal parse
i+=2;
return true;
}
return false;
}
public static ProgramNode Parse(List<LexToken> tokens)
{
ProgramNode node=new ProgramNode();
//function pointers are
//funcptr func identifer (arg_type arg_name, ...);
//funcptr
// a function can be
// func identifier (arg_type arg_name,...)
// return_type identifier (arg_type arg_name, ...)
// func identifier (arg_type arg_name)
// return_type identifier (arg_type arg_name)
// func identifier ()
// return_type identifier ()
//a const variable can be (also in func)
//variable_type identifier;
//variable_type identifier = expression;
int i = 0;
for(;i<tokens.Count;i++)
{
//we need a type or null
LexToken type_token = tokens[i];
if(type_token.Type == LexSymbol.Keyword || type_token.Type == LexSymbol.Identifier)
{
string type;
//we only allow keywords for variable types for now eg no data types other than system ones
if(_checkForArrayType(ref i,tokens))
{
type=$"{type_token.TokenText}[]";
//it is an array
}else{
type=type_token.TokenText;
//not a bloddy array
}
i++;
if(i<tokens.Count)
{
LexToken name_token = tokens[i];
if(name_token.Type == LexSymbol.Identifier)
{
//this must be an identifier
//now we will check if it is a function or a variable
//is next char ( or = or ;
i++;
if(i<tokens.Count)
{
LexToken del=tokens[i];
if(del.Type == LexSymbol.Symbol)
{
if(del.TokenText == "(")
{
FunctionNode fnode=ParseArguments(ref i,tokens);
ParseFunction(ref i,tokens,fnode);
fnode.Column = type_token.ColumnNumber;
fnode.FilePosition = type_token.OffsetInFile;
fnode.Line = type_token.LineNumber;
fnode.ReturnType = type_token.TokenText;
fnode.Name = name_token.TokenText;
node.Functions.Add(fnode);
//must be function
}else if(del.TokenText == "=")
{
i++;
if(i<tokens.Count){
//must be creation of global variable
var res=ParseExpression(ref i,tokens);
VariableDeclarationNode decl=new VariableDeclarationNode();
decl.Column = type_token.ColumnNumber;
decl.FilePosition = type_token.OffsetInFile;
decl.Line = type_token.LineNumber;
decl.VariableType = type_token.TokenText;
decl.Name = name_token.TokenText;
decl.InitialValue = res;
node.Variables.Add(decl);
}
}else if(del.TokenText == ";")
{
//null global variable
VariableDeclarationNode decl=new VariableDeclarationNode();
decl.Column = type_token.ColumnNumber;
decl.FilePosition = type_token.OffsetInFile;
decl.Line = type_token.LineNumber;
decl.VariableType = type_token.TokenText;
decl.Name = name_token.TokenText;
decl.InitialValue=new UninitNode();
node.Variables.Add(decl);
}
}
}
}
}
}
}
return node;
}
private static FunctionNode ParseArguments(ref int i, List<LexToken> tokens)
{
i++;
List<ArgumentNode> argumentNodes = new List<ArgumentNode>();
//type arg,type arg
for(;i<tokens.Count;i++)
{
LexToken type = tokens[i];
if(type.Type ==LexSymbol.Symbol && type.TokenText == ")")
{
break;
}
if(type.Type == LexSymbol.Keyword || type.Type == LexSymbol.Identifier)
{
//we got a type
ArgumentNode node = new ArgumentNode();
string typestr;
//we only allow keywords for variable types for now eg no data types other than system ones
if(_checkForArrayType(ref i,tokens))
{
typestr=$"{type.TokenText}[]";
//it is an array
}else{
typestr=type.TokenText;
//not a bloddy array
}
node.ArgType=typestr;
i++;
if(i<tokens.Count)
{
LexToken name = tokens[i];
if(name.Type == LexSymbol.Identifier)
{
node.Name = name.TokenText;
argumentNodes.Add(node);
i++;
if(i<tokens.Count)
{
LexToken sep= tokens[i];
if(sep.Type == LexSymbol.Symbol)
{
i++;
if(sep.TokenText == ")")
{
break;
}else if(sep.TokenText == ",")
{
continue;
}
}
}
}
}else{
throw new Exception("argument name expected");
}
}
}
return new FunctionNode(){Arguments=argumentNodes};
}
private static Node ParseStatement(ref int i,List<LexToken> tokens)
{
//if(EXPRESSION) {} else {}
//if(EXPRESSION) {}
//while {}
//break;
//return EXPRESSION;
//TYPE VARNAME = EXPRESSION;
//VARNAME = EXPRESSION;
//FUNCNAME(EXPRESSION,...)
LexToken type_token_keyword_token = tokens[i];
if(type_token_keyword_token.Type == LexSymbol.Symbol && type_token_keyword_token.TokenText == "{")
{
ScopeNode node=new ScopeNode();
i++;
for(;i<tokens.Count;i++)
{
if(tokens[i].TokenText == "}")
{
//i++;
break;
}
node.Nodes.Add(ParseStatement(ref i,tokens));
}
return node;
}else
if(type_token_keyword_token.Type == LexSymbol.Keyword)
{
//its if, while, break or return
if(type_token_keyword_token.TokenText == "break")
{
BreakNode node=new BreakNode();
i++;
return node;
//break
}
else if(type_token_keyword_token.TokenText=="while")
{
i++;
WhileNode node=new WhileNode();
node.Body = ParseStatement(ref i,tokens);
return node;
//while
}
else if(type_token_keyword_token.TokenText == "if")
{
//if
if(i+2<tokens.Count)
{
LexToken lparn = tokens[i+1];
i+=2;
if(lparn.TokenText == "(" && lparn.Type == LexSymbol.Symbol)
{
Expression ifCondition=ParseExpression(ref i,tokens);
LexToken rparn = tokens[i];
if(rparn.TokenText == ")" && rparn.Type == LexSymbol.Symbol)
{
i++;
var truth=ParseStatement(ref i,tokens);
//we need to parse body
}else{
throw new Exception("missing )");
}
}else{
throw new Exception("missing (");
}
}
}
else if(type_token_keyword_token.TokenText == "return")
{
//return
}
else
{
//variable
var type_token=type_token_keyword_token;
string type;
if(_checkForArrayType(ref i,tokens))
{
type=$"{type_token_keyword_token.TokenText}[]";
//it is an array
}else{
type=type_token_keyword_token.TokenText;
//not a bloddy array
}
i++;
if(i<tokens.Count)
{
LexToken name_token = tokens[i];
if(name_token.Type == LexSymbol.Identifier)
{
//this must be an identifier
//now we will check if it is a function or a variable
//is next char ( or = or ;
i++;
if(i<tokens.Count)
{
LexToken del=tokens[i];
if(del.Type == LexSymbol.Symbol)
{
if(del.TokenText == "=")
{
i++;
if(i<tokens.Count){
//must be creation of global variable
var res=ParseExpression(ref i,tokens);
VariableDeclarationNode decl=new VariableDeclarationNode();
decl.Column = type_token.ColumnNumber;
decl.FilePosition = type_token.OffsetInFile;
decl.Line = type_token.LineNumber;
decl.VariableType = type_token.TokenText;
decl.Name = name_token.TokenText;
decl.InitialValue = res;
return decl;
}
}else if(del.TokenText == ";")
{
//null global variable
VariableDeclarationNode decl=new VariableDeclarationNode();
decl.Column = type_token.ColumnNumber;
decl.FilePosition = type_token.OffsetInFile;
decl.Line = type_token.LineNumber;
decl.VariableType = type_token.TokenText;
decl.Name = name_token.TokenText;
decl.InitialValue=new UninitNode();
return decl;
}
}
}
}
}
}
}
throw new Exception("Thrown");
}
private static void ParseFunction(ref int i, List<LexToken> tokens,FunctionNode node)
{
node.Body=ParseStatement(ref i,tokens);
}
private static Expression ParseExpression(ref int i, List<LexToken> tokens)
{
//Console.WriteLine(tokens[i].TokenText);
//an expression can be
//number
//char
//string
//function_call
//bool
//variable
//function call
//method_name(expression ...)
LexToken identifer = tokens[i];
if(identifer.Type == LexSymbol.Integer)
{
i++;
return new ConstInt(identifer.TokenText);
}
if(identifer.Type == LexSymbol.Float)
{
i++;
return new ConstFloat(identifer.TokenText);
}
if(identifer.Type == LexSymbol.Char)
{
i++;
return new ConstChar(identifer.TokenText);
}
if(identifer.Type == LexSymbol.String)
{
i++;
return new ConstString(identifer.TokenText);
}
//either function call or identifer
if(identifer.Type == LexSymbol.Identifier)
{
if(i+1<tokens.Count)
{
var parenToken = tokens[i+1];
if(parenToken.Type == LexSymbol.Symbol)
{
if(parenToken.TokenText == "(")
{
//function_call
List<Expression> args=new List<Expression>();
Console.WriteLine(tokens[i].TokenText);
i+=2;
for(;i<tokens.Count;i++)
{
var exp=ParseExpression(ref i,tokens);
Console.WriteLine(exp);
args.Add(exp);
if(i<tokens.Count)
{
var t = tokens[i];
if(t.Type == LexSymbol.Symbol)
{
if(t.TokenText == ",")
{
continue;
}
if(t.TokenText == ")") {break;}
}
}else{
//error
}
}
i++;
return new FunctionCallNode(identifer.TokenText,args);
}
if(parenToken.TokenText == "[")
{
Expression e=ParseExpression(ref i,tokens);
if(parenToken.Type == LexSymbol.Symbol && parenToken.TokenText == "]")
{
//we got array index
i++;
return new GetArrayValueNode(identifer.TokenText,e);
}
throw new Exception();
//array index;
}
else{
i++;
return new GetVariableValueNode(identifer.TokenText);
}
}else
{
//it is actually a variable
i++;
return new GetVariableValueNode(identifer.TokenText);
}
}else{
//eof
throw new Exception();
}
}
throw new Exception("Error");
}
}
public class WhileNode : Node
{
public override string ToString()
{
return $"While Loop:\n{TabOver(Body.ToString())}";
}
public override NodeType Type {get {return NodeType.While;}}
public Node Body { get; set; }
}
public class BreakNode : Node
{
public override string ToString()
{
return "break loop";
}
public override NodeType Type {get{return NodeType.Break;}}
}
internal class GetVariableValueNode : Expression
{
public string Name {get;set;}
public override NodeType Type {get{return NodeType.GetVariableValue;}}
public override string ToString()
{
return $"Get value from {Name}";
}
public GetVariableValueNode(string tokenText)
{
Name= tokenText;
}
}
public class GetArrayValueNode : Expression
{
public override string ToString()
{
return $"GetArrayValue:\nName: {Name}\nIndex:\n{TabOver(Index.ToString())}";
}
public GetArrayValueNode(string name,Expression expression)
{
Name=name;
Index=expression;
}
public Expression Index {get;set;}
public string Name {get;set;}
public override NodeType Type {get{return NodeType.GetArrayValue;}}
}
public class ConstString : Expression
{
public override string ToString()
{
return $"Const String: {Text}";
}
public ConstString(string tokenText)
{
Text = tokenText;
}
public string Text {get;set;}
public override NodeType Type {get{return NodeType.ConstString;}}
}
public class ConstChar : Expression
{
public override string ToString()
{
return $"Const Char: {Text}";
}
public string Text {get;set;}
public override NodeType Type {get{return NodeType.ConstChar;}}
public ConstChar(string tokenText)
{
Text = tokenText;
}
}
public class FunctionCallNode : Expression
{
public override string ToString()
{
StringBuilder b=new StringBuilder();
int i=0;
foreach(var args in Arguments)
{
b.Append($"args[{i}]: {args}\n");
i++;
}
return $"Function Call: {Name}\n{TabOver(b.ToString())}";
}
public string Name {get;set;}
public List<Expression> Arguments {get;set;}
public override NodeType Type {get{return NodeType.CallMethod;}}
public FunctionCallNode(string tokenText, List<Expression> args)
{
Name = tokenText;
Arguments = args;
}
}
public class ConstFloat : Expression
{
public override string ToString()
{
return $"Const Float: {Text}";
}
public override NodeType Type {get{return NodeType.ConstFloat;}}
public string Text {get;set;}
public ConstFloat(string tokenText)
{
Text = tokenText;
}
}
public class ConstInt : Expression
{
public override string ToString()
{
return $"Const Int: {Text}";
}
public string Text {get;set;}
public ConstInt(string tokenText)
{
Text = tokenText;
}
public override NodeType Type {get{return NodeType.ConstInt;}}
}
public class ProgramNode : Node
{
public override NodeType Type {get {return NodeType.Program;}}
public ProgramNode()
{
Functions=new List<FunctionNode>();
Variables=new List<VariableDeclarationNode>();
}
public List<FunctionNode> Functions {get;set;}
public List<VariableDeclarationNode> Variables {get;set;}
public override string ToString()
{
StringBuilder funcs=new StringBuilder();
foreach(var args in Functions)
{
funcs.Append($"{args}\n");
}
StringBuilder vars = new StringBuilder();
foreach(var args in Variables)
{
vars.Append($"{args}\n");
}
return $"Program:\nFunctions:\n{TabOver(funcs.ToString())}\nGlobal Variables:\n{TabOver(vars.ToString())}";
}
}
public class VariableDeclarationNode : Node
{
public string Name {get;set;}="";
public string VariableType {get;set;}="";
public Expression InitialValue {get;set;}=new UninitNode();
public override NodeType Type {get{return NodeType.VariableCreate;}}
public override string ToString()
{
return $"Variable declared with name: {Name}\nType: {VariableType}\nInitial Value:\n{TabOver(InitialValue.ToString())}";
}
}
public class ArgumentNode : Node
{
public override NodeType Type {get {return NodeType.Arguments;}}
public string ArgType {get;set;}="";
public string Name {get;set;}="";
public override string ToString()
{
return $"ArgType: {ArgType}\nName: {Name}";
}
}
public class ScopeNode : Node
{
public List<Node> Nodes {get;set;}=new List<Node>();
public override NodeType Type {get{return NodeType.Scope;}}
public override string ToString()
{
StringBuilder b=new StringBuilder();
foreach(var node in Nodes)
{
b.Append(node.ToString()+"\n");
}
return $"Scope:\n{TabOver(b.ToString())}";
}
}
public class FunctionNode : Node
{
public override string ToString()
{
StringBuilder b=new StringBuilder();
int i=0;
foreach(var args in Arguments)
{
b.Append($"args[{i}]: {args}\n");
i++;
}
return $"Function: {Name}\nReturn Type: {ReturnType}\nArguments:\n{TabOver(b.ToString())}\nBody:{TabOver(Body.ToString())}";
}
public string ReturnType {get;set;}="";
public override NodeType Type {get {return NodeType.Function;}}
public string Name {get;set;}="";
public Node Body {get;set;}
public List<ArgumentNode> Arguments {get;set;}=new List<ArgumentNode>();
}
public enum NodeType
{
ConstInt=0,
ConstFloat=1,
ConstString=2,
ConstChar=3,
VariableCreate=4,
GetVariableValue=5,
SetVariableValue=6,
CallMethod=7,
Return=8,
Function=9,
Program=10,
Arguments=11,
Uninit=12,
GetArrayValue=13,
Scope=14,
If=15,
Else=16,
While=17,
Break=18,
}
public abstract class Expression : Node
{
public override string ToString()
{
return $"Expression {base.ToString()}";
}
}
public class UninitNode : Expression
{
public override string ToString()
{
return $"Uninitilized {base.ToString()}";
}
public override NodeType Type {get {return NodeType.Uninit;}}
}
public abstract class Node
{
public override string ToString()
{
return $"Node:\nFilePosition: {FilePosition}\nColumn: {Column}\nLine: {Line}";
}
protected string TabOver(string text)
{
StringBuilder b=new StringBuilder();
foreach(var txt in text.Split('\n'))
{
b.Append($"\t{txt}\n");
}
return b.ToString();
}
public abstract NodeType Type {get;}
public int FilePosition {get;set;}
public int Column {get;set;}
public int Line {get;set;}
}
}

4
FunctionCallNode.cs Normal file
View File

@ -0,0 +1,4 @@
namespace TLang
{
}

201
Lexer.cs Normal file
View File

@ -0,0 +1,201 @@
using System.IO;
using System.Collections.Generic;
using System.Text;
using System;
namespace TLang
{
public enum LexSymbol
{
Identifier = 0,
String=1,
Char=2,
Integer=3,
Float=4,
Boolean=5,
Symbol=6,
Keyword=7,
Error=8
}
public class LexToken
{
public static string Symbols="{};(),[]=";
public static string[] Keywords=new string[]{"func","funcptr","string","int","uint","long","ulong","short","ushort","byte","sbyte","return","if","else","while","break"};
public LexToken(string text,int offsetInFile,int lineNumber,int columnNumber)
{
Func<bool> has_any_non_number=()=>
{
if(TokenText.Length <= 0)
return false;
bool hasDot=false;
foreach(var c in TokenText)
{
if(c == '.')
{
if(hasDot) return true;
hasDot=true;
}
if(c < '0' && c > '9')
return true;
}
return false;
};
TokenText=text;
OffsetInFile=offsetInFile;
LineNumber = lineNumber;
ColumnNumber = columnNumber;
string _lower=TokenText.ToLower();
if(TokenText.Length == 0){Type=LexSymbol.Error;return;}
if(_lower == "true" || _lower=="false")
{
Type = LexSymbol.Boolean;
}
else if(TokenText[0] == '_' || (TokenText[0] >= 'a' && TokenText[0] <= 'z') || (TokenText[0] >= 'A' && TokenText[0] <= 'Z'))
{
Type= Keywords.Contains(TokenText) ? LexSymbol.Keyword : LexSymbol.Identifier;
}else if(Symbols.Contains(TokenText[0]))
{
Type = LexSymbol.Symbol;
}else if(!has_any_non_number())
{
Type = TokenText.Contains('.') ? LexSymbol.Float : LexSymbol.Integer;
}else{
Type = LexSymbol.Error;
}
}
public string TokenText {get;set;}
public int OffsetInFile {get;set;}
public int LineNumber {get;set;}
public int ColumnNumber {get;set;}
public LexSymbol Type {get;set;}
}
public class Lexer
{
public static IEnumerable<LexToken> GetTokens(TextReader reader)
{
LexToken value = new LexToken("",0,0,0);
int read=0;
int i=0;
int col=0;
int ln=0;
StringBuilder b=new StringBuilder();
Func<bool> pop_off = ()=>{
//we need to pop off what ever is in array
if(b.Length <= 0)
return false;
value=new LexToken(b.ToString(),i,ln,col);
b.Clear();
return true;
};
while((read=reader.Read()) != -1)
{
//neq(T,T)
//lte(T,T)
//gte(T,T)
//gt(T,T)
//lt(T,T)
//eq(T,T)
//add(T,T)
//concat(T,T)
//tostr(T)
//toint(T)
//touint(T)
//tolong(T)
//toulong(T)
//toshort(T)
//toushort(T)
//tobool(T)
//tobyte(T)
//tosbyte(T)
//hasvalue(T)
//sub(T,T)
//times(T,T)
//div(T,T)
//mod(T,T)
//split(s,symbol,expected_num)
//split(s,symbol)
//trimend(s,sym)
//trimstart(s,sym)
//len(T[])
//add(T[],T)
//remove(T[],T)
//removeat(T[],i)
//insert(T[],T,i)
//create_stream(read_ptr,write_ptr,seek_ptr,close_ptr)
//read_stream(stream,byte[],int)
//write_stream(stream byte[],int)
switch(read)
{
case '{':
case '}':
case '(':
case ')':
case ',':
case '[':
case ']':
case '=':
case ';':
col++;
i++;
if(pop_off())
yield return value;
b.Append((char)read);
if(pop_off())
yield return value;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
b.Append((char)read);
col++;
i++;
break;
case ' ':
case '\t':
if(read == ' ') {i++;col++;}
if(read == '\t') {i++;col+=4;}
if(pop_off())
yield return value;
break;
default:
//needs to start with _ or letter
//can contain numbers
col++;
if(read == '\n') {col=0;ln++;}
i++;
if(read == '_' || (read >= 'a' && read <= 'z') || (read >= 'A' && read <= 'Z'))
{
b.Append((char)read);
}
break;
}
}if(pop_off())
yield return value;
}
}
}

8
Program.cs Normal file
View File

@ -0,0 +1,8 @@
using System.IO;
using System;
using TLang;
//string code = "func main(string[] args) { int i = times(4,8); print(i);}";
string code = "func main(string[] args) { int i = 0; int j = 42; int k=demi(1,1); while { int f=0; } int j=0; } int j=42; func sub(int i){int j=0;}";
var parsed=Parser.Parse(Lexer.GetTokens(new StringReader(code)).ToList());
Console.WriteLine(parsed);

10
dumbcompiler.csproj Normal file
View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>