From c3afc99003814d083f73a6a859043e5cd4a64d55 Mon Sep 17 00:00:00 2001 From: Michael Nolan Date: Wed, 26 Jul 2023 22:31:32 -0500 Subject: [PATCH] First Commit --- .gitignore | 398 ++++++++++++++++ TLang.Lexer/Class1.cs | 415 ++++++++++++++++ TLang.Lexer/LexContext.cs | 139 ++++++ TLang.Lexer/LexEntryContext.cs | 19 + TLang.Lexer/LexLineInfo.cs | 64 +++ TLang.Lexer/LexToken.cs | 78 +++ TLang.Lexer/TLang.Lexer.csproj | 7 + TLang.Parser/AddNode.cs | 14 + TLang.Parser/BAndNode.cs | 14 + TLang.Parser/BOrNode.cs | 14 + TLang.Parser/BitwiseNotNode.cs | 16 + TLang.Parser/BreakNode.cs | 6 + TLang.Parser/CallNode.cs | 9 + TLang.Parser/CaseNode.cs | 18 + TLang.Parser/CharNode.cs | 16 + TLang.Parser/Class1.cs | 653 ++++++++++++++++++++++++++ TLang.Parser/ClassEntryNode.cs | 12 + TLang.Parser/ClassNode.cs | 13 + TLang.Parser/ClosureNode.cs | 16 + TLang.Parser/CompilerError.cs | 39 ++ TLang.Parser/ConstNumberNode.cs | 12 + TLang.Parser/ContinueNode.cs | 6 + TLang.Parser/DefaultNode.cs | 16 + TLang.Parser/DivideNode.cs | 14 + TLang.Parser/EachLoopNode.cs | 16 + TLang.Parser/EqualsNode.cs | 14 + TLang.Parser/ForLoopNode.cs | 18 + TLang.Parser/FunctionCallNode.cs | 12 + TLang.Parser/GetArrayNode.cs | 15 + TLang.Parser/GetMemberNode.cs | 17 + TLang.Parser/GetVariableNode.cs | 12 + TLang.Parser/GreaterThanEqualsNode.cs | 14 + TLang.Parser/GreaterThanNode.cs | 14 + TLang.Parser/IfNode.cs | 16 + TLang.Parser/LAndNode.cs | 14 + TLang.Parser/LOrNode.cs | 14 + TLang.Parser/LeftShiftNode.cs | 14 + TLang.Parser/LessThanEqualsNode.cs | 14 + TLang.Parser/LessThanNode.cs | 14 + TLang.Parser/MethodCallNode.cs | 19 + TLang.Parser/ModuloNode.cs | 14 + TLang.Parser/MultiplyNode.cs | 14 + TLang.Parser/NegativeNode.cs | 16 + TLang.Parser/Node.cs | 10 + TLang.Parser/NotEqualsNode.cs | 14 + TLang.Parser/NotNode.cs | 16 + TLang.Parser/PostFixDecrementNode.cs | 15 + TLang.Parser/PostFixIncrementNode.cs | 15 + TLang.Parser/PowNode.cs | 14 + TLang.Parser/ReturnNode.cs | 12 + TLang.Parser/RightShiftNode.cs | 14 + TLang.Parser/ScopeNode.cs | 16 + TLang.Parser/SetVariableNode.cs | 14 + TLang.Parser/StringNode.cs | 12 + TLang.Parser/SubtractNode.cs | 14 + TLang.Parser/SymbolNode.cs | 7 + TLang.Parser/TLang.Parser.csproj | 11 + TLang.Parser/WhileLoop.cs | 17 + TLang.Parser/XOrNode.cs | 14 + 59 files changed, 2504 insertions(+) create mode 100644 .gitignore create mode 100644 TLang.Lexer/Class1.cs create mode 100644 TLang.Lexer/LexContext.cs create mode 100644 TLang.Lexer/LexEntryContext.cs create mode 100644 TLang.Lexer/LexLineInfo.cs create mode 100644 TLang.Lexer/LexToken.cs create mode 100644 TLang.Lexer/TLang.Lexer.csproj create mode 100644 TLang.Parser/AddNode.cs create mode 100644 TLang.Parser/BAndNode.cs create mode 100644 TLang.Parser/BOrNode.cs create mode 100644 TLang.Parser/BitwiseNotNode.cs create mode 100644 TLang.Parser/BreakNode.cs create mode 100644 TLang.Parser/CallNode.cs create mode 100644 TLang.Parser/CaseNode.cs create mode 100644 TLang.Parser/CharNode.cs create mode 100644 TLang.Parser/Class1.cs create mode 100644 TLang.Parser/ClassEntryNode.cs create mode 100644 TLang.Parser/ClassNode.cs create mode 100644 TLang.Parser/ClosureNode.cs create mode 100644 TLang.Parser/CompilerError.cs create mode 100644 TLang.Parser/ConstNumberNode.cs create mode 100644 TLang.Parser/ContinueNode.cs create mode 100644 TLang.Parser/DefaultNode.cs create mode 100644 TLang.Parser/DivideNode.cs create mode 100644 TLang.Parser/EachLoopNode.cs create mode 100644 TLang.Parser/EqualsNode.cs create mode 100644 TLang.Parser/ForLoopNode.cs create mode 100644 TLang.Parser/FunctionCallNode.cs create mode 100644 TLang.Parser/GetArrayNode.cs create mode 100644 TLang.Parser/GetMemberNode.cs create mode 100644 TLang.Parser/GetVariableNode.cs create mode 100644 TLang.Parser/GreaterThanEqualsNode.cs create mode 100644 TLang.Parser/GreaterThanNode.cs create mode 100644 TLang.Parser/IfNode.cs create mode 100644 TLang.Parser/LAndNode.cs create mode 100644 TLang.Parser/LOrNode.cs create mode 100644 TLang.Parser/LeftShiftNode.cs create mode 100644 TLang.Parser/LessThanEqualsNode.cs create mode 100644 TLang.Parser/LessThanNode.cs create mode 100644 TLang.Parser/MethodCallNode.cs create mode 100644 TLang.Parser/ModuloNode.cs create mode 100644 TLang.Parser/MultiplyNode.cs create mode 100644 TLang.Parser/NegativeNode.cs create mode 100644 TLang.Parser/Node.cs create mode 100644 TLang.Parser/NotEqualsNode.cs create mode 100644 TLang.Parser/NotNode.cs create mode 100644 TLang.Parser/PostFixDecrementNode.cs create mode 100644 TLang.Parser/PostFixIncrementNode.cs create mode 100644 TLang.Parser/PowNode.cs create mode 100644 TLang.Parser/ReturnNode.cs create mode 100644 TLang.Parser/RightShiftNode.cs create mode 100644 TLang.Parser/ScopeNode.cs create mode 100644 TLang.Parser/SetVariableNode.cs create mode 100644 TLang.Parser/StringNode.cs create mode 100644 TLang.Parser/SubtractNode.cs create mode 100644 TLang.Parser/SymbolNode.cs create mode 100644 TLang.Parser/TLang.Parser.csproj create mode 100644 TLang.Parser/WhileLoop.cs create mode 100644 TLang.Parser/XOrNode.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a30d25 --- /dev/null +++ b/.gitignore @@ -0,0 +1,398 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# 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 +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml diff --git a/TLang.Lexer/Class1.cs b/TLang.Lexer/Class1.cs new file mode 100644 index 0000000..39f4162 --- /dev/null +++ b/TLang.Lexer/Class1.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace TLang.Lexer +{ + public class Lex + { + TextReader reader; + private Lex(TextReader reader) + { + this.reader = reader; + } + private LexLineInfo lineInfo = new LexLineInfo(); + private LexLineInfo beginLInfo = new LexLineInfo(); + private List tokens = new List(); + private StringBuilder builder = new StringBuilder(); + private void Flush() + { + if(builder.Length > 0) + { + tokens.Add(LexToken.Token(builder.ToString()).WithLineInfo(beginLInfo)); + builder.Clear(); + } + } + private void Append(int c) + { + if(c == -1) return; + if(builder.Length == 0) + beginLInfo = lineInfo.Clone(); + + builder.Append((char)c); + + } + public static LexContext GetTokens(TextReader reader,string filename="memory.tlang") + { + Lex lex = new Lex(reader); + lex.StartLexing(); + return new LexContext(lex.tokens); + } + private void ParseChar() + { + var lineInfo = this.lineInfo.Clone(); + //'c' + var (mChar,Escaped,EOF) = ReadChar(); + + tokens.Add(LexToken.Char(mChar.ToString()).WithLineInfo(lineInfo)); + _ = Next; + } + private void ParseString(bool interoplated) + { + var lineInfo = this.lineInfo.Clone(); + //$"Demi Lovato is { variable + 5 } years Old"; -> String.Join("Demi Lovato is ",( variable + 5)," years Old"); + + StringBuilder b = new StringBuilder(); + var (mChar,Escaped,EOF) = ReadChar(); + + while((mChar != '\"' || Escaped) && !EOF) + { + b.Append(mChar); + (mChar,Escaped,EOF) = ReadChar(); + } + if(interoplated) + { + + tokens.Add(LexToken.Token("String").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token(".").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token("Concat").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); + int e = 0; + int escapeI = 0; + + StringBuilder b2 = new StringBuilder(); + for(int i = 0;i< b.Length;i++) + { + if(b[i] == '{' ) + { + if((i+1 < b.Length && b[i+1] != '{') || escapeI >= 1) + { + if(b2.Length > 0 && escapeI < 1) + { + if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + tokens.Add(LexToken.String(b2.ToString()).WithLineInfo(lineInfo)); + b2.Clear(); + e++; + } + escapeI++; + if(escapeI > 1) + { + b2.Append('{'); + } + } + else + { + b2.Append('{'); + i++; + } + } + else if(b[i] == '}') + { + if(escapeI >= 1) + { + escapeI--; + if(b2.Length > 0 && escapeI == 0) + { + if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + + + tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); + tokens.AddRange(Lex.GetTokensFromString(b2.ToString(),"compilerGenerated.tlang").Tokens); + tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + b2.Clear(); + e++; + } + if(escapeI >= 1) + { + b2.Append("}"); + } + } + } + else { + b2.Append(b[i]); + } + } + + if(b2.Length > 0) + { + if(escapeI > 0) + { + if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + + + tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); + tokens.AddRange(Lex.GetTokensFromString(b2.ToString(),"compilerGenerated.tlang").Tokens); + tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + b2.Clear(); + e++; + } + else + { + if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + tokens.Add(LexToken.String(b2.ToString()).WithLineInfo(lineInfo)); + b2.Clear(); + e++; + } + } + + + tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + + } + else + { + tokens.Add(LexToken.String(b.ToString()).WithLineInfo(lineInfo)); + } + } + private (char Char, bool Escaped,bool EOF) ReadChar() + { + + int next = Next; + if(next == -1) return (' ',false,true); + if(next == '\\') + { + next = Next; + if(next == 'n') + { + return ('\n',true,false); + } + else if(next == 'r') + { + return ('\r',true,false); + } + else if(next == 't') + { + return ('\t',true,false); + } + else if(next == 'x') + { + string hexCode = new string(new char[]{(char)Next,(char)Next}); + int val= int.Parse(hexCode,System.Globalization.NumberStyles.HexNumber); + return ((char)val,true,false); + } + else + { + return ((char)next,true,false); + } + } + return ((char)next,false,false); + } + private void StartLexing() + { + int c; + while((c=Next) != -1) + { + var peek = Peek; + var lineInfo = this.lineInfo.Clone(); + switch(c) + { + case '/': + if(peek == '/') + { + _ = Next; + //single line comment + Flush(); + while(Next != '\n'); + } + else if(peek == '*') + { + var next = Next; + + while((next = Next) != -1) + { + if(next == '*') + { + if(Peek == '/') + { + _ = Next; + break; + } + } + } + } + else if(peek == '^') + { + var next = Next; + StringBuilder b = new StringBuilder(); + + while((next = Next) != -1) + { + if(next == '^') + { + if(Peek == '/') + { + _ = Next; + break; + } + } + b.Append((char)next); + } + tokens.Add(LexToken.Documentation(b.ToString()).WithLineInfo(lineInfo)); + } + else if(peek == '=') + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}=").WithLineInfo(lineInfo)); + } + else + { + tokens.Add(LexToken.Token($"{(char)c}").WithLineInfo(lineInfo)); + } + break; + case '\"': + Flush(); + ParseString(false); + break; + case '\'': + Flush(); + ParseChar(); + break; + case '$': + Flush(); + if(peek == '\"') + { + _ = Next; + ParseString(true); + } + break; + case '^': + { + Flush(); + if(peek == c) + { + _ = Next; + peek=Peek; + if(peek == '=') + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}{(char)c}=").WithLineInfo(lineInfo)); + + } + else + { + tokens.Add(LexToken.Token($"{(char)c}{(char)c}").WithLineInfo(lineInfo)); + } + + } + else if(peek == '=') + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}=").WithLineInfo(lineInfo)); + } + else { + tokens.Add(LexToken.Token($"{(char)c}").WithLineInfo(lineInfo)); + } + } + break; + case '+': + case '-': + case '<': + case '>': + case '|': + case '&': + { + Flush(); + if(peek == c) + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}{(char)c}").WithLineInfo(lineInfo)); + } + else if(peek == '=') + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}=").WithLineInfo(lineInfo)); + } + else { + tokens.Add(LexToken.Token($"{(char)c}").WithLineInfo(lineInfo)); + } + } + break; + case '*': + case '%': + case '!': + { + Flush(); + if(peek == '=') + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}=").WithLineInfo(lineInfo)); + } + else { + tokens.Add(LexToken.Token($"{(char)c}").WithLineInfo(lineInfo)); + } + } + break; + case '[': + case ']': + case '(': + case ')': + case ':': + case '{': + case '}': + case ';': + case '?': + case '.': + case ',': + { + Flush(); + tokens.Add(LexToken.Token($"{(char)c}").WithLineInfo(lineInfo)); + break; + } + case '=': + { + Flush(); + if(peek == c) + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}{(char)c}").WithLineInfo(lineInfo)); + } + else if(peek == '>') + { + _ = Next; + tokens.Add(LexToken.Token($"{(char)c}>").WithLineInfo(lineInfo)); + } + else { + tokens.Add(LexToken.Token($"{(char)c}").WithLineInfo(lineInfo)); + } + } + break; + case '\t': + case '\n': + case '\r': + case ' ': + Flush(); + SetSpacesBetweenTrue(); + break; + default: + Append(c); + break; + } + } + Flush(); + } + + private void SetSpacesBetweenTrue() + { + if(tokens.Count > 0) + { + tokens[tokens.Count-1].SpacesBetweenThisAndNext = true; + } + } + + private int Next { + get{ + int read= reader.Read(); + if(read != -1) + lineInfo.AppendChar((char)read); + return read; + } + } + private int Peek => reader.Peek(); + + public static LexContext GetTokensFromFile(string str) + { + using(var f = File.OpenText(str)) + { + return GetTokens(f,str); + } + } + public static LexContext GetTokensFromString(string str,string filename="memory.tlang") + { + return GetTokens(new StringReader(str)); + } + } +} diff --git a/TLang.Lexer/LexContext.cs b/TLang.Lexer/LexContext.cs new file mode 100644 index 0000000..7f5141d --- /dev/null +++ b/TLang.Lexer/LexContext.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; + +namespace TLang.Lexer +{ + public class LexContext + { + public static LexContext operator+(LexContext left,LexContext right) + { + List tokens=new List(); + tokens.AddRange(left.Tokens); + tokens.AddRange(right.Tokens); + + LexContext ctx=new LexContext(tokens); + ctx.Offset = left.Offset; + return ctx; + } + public LexContext(IReadOnlyList tokens) + { + Tokens = tokens; + } + public IReadOnlyList Tokens {get;} + public int Offset {get;set;} = 0; + + + public LexContext FromOffset(int offset) + { + return new LexContext(Tokens){Offset = offset}; + } + public LexContext FromOffset() + { + return FromOffset(Offset); + } + + public LexToken Next(int i = 0) + { + if(Offset + i < Tokens.Count) return Tokens[Offset + i]; + return new LexToken(); + } + + public void Add(int i=1) + { + Offset++; + } + public LexEntryContext NextEntriesNoSpaces(bool consumeIfTrue,params string[] tokenText) + { + List tokens = new List(); + int offset = Offset; + if(Offset + tokenText.Length >= Tokens.Count) return new LexEntryContext(tokens,offset,false); + for(int i = 0; i tokens = new List(); + int offset = Offset; + if(Offset + tokenText.Length >= Tokens.Count) return new LexEntryContext(tokens,offset,false); + for(int i = 0; i= Tokens.Count) return false; + + foreach(var item in tokenText) + { + if(Tokens[Offset].IsDocumentation || Tokens[Offset].IsChar || Tokens[Offset].IsString || Tokens[Offset].Text == item) + { + token = Tokens[Offset]; + if(consumeIfTrue) Offset++; + return true; + } + + } + + return false; + } + + public LexToken NextEntry + { + get { + if(Offset < Tokens.Count) + { + return Tokens[Offset++]; + } + return LexToken.Empty; + } + } + public LexToken PeekEntry + { + get + { + if(Offset < Tokens.Count) + { + return Tokens[Offset]; + } + return LexToken.Empty; + } + } + + public LexLineInfo CurrentLineInfo => PeekEntry.Position; + + public bool MoreTokens => Offset < Tokens.Count; + + public string PopDocumentation() + { + if(Offset >= Tokens.Count || !Tokens[Offset].IsDocumentation) return ""; + return Tokens[Offset++].Text; + } + + public LexEntryContext NextEntries(bool consumeIfTrue,params LexToken[] tokens) + { + List _tokens = new List(); + int offset = Offset; + if(Offset + tokens.Length >= Tokens.Count) return new LexEntryContext(_tokens,offset,false); + for(int i = 0; i tokens,int offset,bool success) + { + Tokens = tokens; + Offset = offset; + Success = success; + } + public IReadOnlyList Tokens {get;} + + public int Offset {get;} + + public bool Success {get;} + } +} \ No newline at end of file diff --git a/TLang.Lexer/LexLineInfo.cs b/TLang.Lexer/LexLineInfo.cs new file mode 100644 index 0000000..d894941 --- /dev/null +++ b/TLang.Lexer/LexLineInfo.cs @@ -0,0 +1,64 @@ +using System; +namespace TLang.Lexer +{ + public class LexLineInfo : IEquatable + { + + public LexLineInfo() + { + Line = 1; + Position = 0; + Column = 1; + FileName="memory.tlang"; + } + public string FileName {get;set;} + + public int Line {get;set;} + + public int Column {get;set;} + + public int Position {get;set;} + + + + public void AppendChar(char c) + { + Position++; + if(c == '\t') + { + Column += 4; + } + else if(c == '\r') + { + Column = 1; + } + else if(c == '\n') + { + Column = 1; + Line += 1; + } + else { + Column++; + } + } + + public LexLineInfo Clone() + { + LexLineInfo lineInfo=new LexLineInfo(); + lineInfo.Column = Column; + lineInfo.FileName = FileName; + lineInfo.Line = Line; + lineInfo.Position = Position; + return lineInfo; + } + + public bool Equals(LexLineInfo other) + { + return Line == other.Line && Column == other.Column && FileName == other.FileName && Position == other.Position; + } + public override string ToString() + { + return $"in file: {FileName}:{Line} offset: {Position}, col: {Column}"; + } + } +} \ No newline at end of file diff --git a/TLang.Lexer/LexToken.cs b/TLang.Lexer/LexToken.cs new file mode 100644 index 0000000..2434e72 --- /dev/null +++ b/TLang.Lexer/LexToken.cs @@ -0,0 +1,78 @@ +using System; +namespace TLang.Lexer +{ + public class LexToken : IEquatable + { + public static LexToken Empty => new LexToken(); + public bool IsEmpty => Text.Length == 0 && !IsDocumentation && !IsChar && !IsString; + public static LexToken Documentation(string text) + { + LexToken token = new LexToken(); + token.IsDocumentation =true; + token.IsChar = false; + token.IsString = false; + token.Text = text; + return token; + } + public static LexToken Token(string text) + { + LexToken token = new LexToken(); + token.IsDocumentation=false; + token.IsChar = false; + token.IsString = false; + token.Text = text; + return token; + } + public static LexToken String(string text) + { + LexToken token = new LexToken(); + token.IsDocumentation=false; + token.IsChar = false; + token.IsString = true; + token.Text = text; + return token; + } + public static LexToken Char(string text) + { + LexToken token = new LexToken(); + token.IsDocumentation=false; + token.IsChar = true; + token.IsString = false; + token.Text = text; + return token; + } + public bool SpacesBetweenThisAndNext {get;set;} = false; + public LexToken WithLineInfo(LexLineInfo lineInfo) + { + Position = lineInfo.Clone(); + return this; + } + public LexToken WithLineInfo(int line,int col,int offset,string filename="memory.tlang") + { + Position = new LexLineInfo(){Line = line,Column = col,Position = offset,FileName = filename}; + return this; + } + public LexLineInfo Position {get;set;} = new LexLineInfo(); + public string Text {get;set;}=""; + + public bool IsString {get;set;}=false; + + public bool IsChar {get;set;}=false; + + public bool IsDocumentation {get;set;}=false; + + public bool SameToken(LexToken token) + { + return Text == token.Text && IsChar == token.IsChar && IsString == token.IsString && IsDocumentation == token.IsDocumentation; + } + public bool Equals(LexToken token) + { + return Text == token.Text && IsChar == token.IsChar && IsString == token.IsString && IsDocumentation == token.IsDocumentation && SpacesBetweenThisAndNext == token.SpacesBetweenThisAndNext && Position.Equals(token.Position); + } + + public bool IsTokenWith(string text) + { + return !IsChar && !IsDocumentation && !IsString && Text == text; + } + } +} \ No newline at end of file diff --git a/TLang.Lexer/TLang.Lexer.csproj b/TLang.Lexer/TLang.Lexer.csproj new file mode 100644 index 0000000..9f5c4f4 --- /dev/null +++ b/TLang.Lexer/TLang.Lexer.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/TLang.Parser/AddNode.cs b/TLang.Parser/AddNode.cs new file mode 100644 index 0000000..816f0f3 --- /dev/null +++ b/TLang.Parser/AddNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class AddNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public AddNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/BAndNode.cs b/TLang.Parser/BAndNode.cs new file mode 100644 index 0000000..8338b3f --- /dev/null +++ b/TLang.Parser/BAndNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class BAndNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public BAndNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/BOrNode.cs b/TLang.Parser/BOrNode.cs new file mode 100644 index 0000000..5f571c9 --- /dev/null +++ b/TLang.Parser/BOrNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class BOrNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public BOrNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/BitwiseNotNode.cs b/TLang.Parser/BitwiseNotNode.cs new file mode 100644 index 0000000..e3d0c0e --- /dev/null +++ b/TLang.Parser/BitwiseNotNode.cs @@ -0,0 +1,16 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + public class BitwiseNotNode : Node + { + public Node Node {get;set;} + + public BitwiseNotNode(Node node) + { + Node = node; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/BreakNode.cs b/TLang.Parser/BreakNode.cs new file mode 100644 index 0000000..254f459 --- /dev/null +++ b/TLang.Parser/BreakNode.cs @@ -0,0 +1,6 @@ +namespace TLang.Parser +{ + public class BreakNode : Node + { + } +} \ No newline at end of file diff --git a/TLang.Parser/CallNode.cs b/TLang.Parser/CallNode.cs new file mode 100644 index 0000000..5533819 --- /dev/null +++ b/TLang.Parser/CallNode.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace TLang.Parser +{ + public class CallNode : SymbolNode + { + public List Arguments {get;set;} + } +} \ No newline at end of file diff --git a/TLang.Parser/CaseNode.cs b/TLang.Parser/CaseNode.cs new file mode 100644 index 0000000..3f017a8 --- /dev/null +++ b/TLang.Parser/CaseNode.cs @@ -0,0 +1,18 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + public class CaseNode : Node + { + public Node Variable {get;set;} + public Node Body {get;set;} + + public CaseNode(Node expr, Node node) + { + Variable = expr; + Body = node; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/CharNode.cs b/TLang.Parser/CharNode.cs new file mode 100644 index 0000000..d1adb69 --- /dev/null +++ b/TLang.Parser/CharNode.cs @@ -0,0 +1,16 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + public class CharNode : Node + { + public string Text {get;set;} + + public CharNode(string text) + { + Text = text; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/Class1.cs b/TLang.Parser/Class1.cs new file mode 100644 index 0000000..392fb50 --- /dev/null +++ b/TLang.Parser/Class1.cs @@ -0,0 +1,653 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using TLang.Lexer; +namespace TLang.Parser +{ + public class Parse + { + private Parse(LexContext ctx) + { + Context = ctx; + } + private LexContext Context {get;set;} + private Node Node {get;set;} + private void ParseNodeRoot() + { + Node = ParseNode(true); + } + public static Node ParseFromLexContext(params LexContext[] ctx) + { + if(ctx.Length > 0) + { + var ctx2 = ctx[0]; + for(int i = 1;i(e=>Lex.GetTokensFromFile(e)).ToArray()); + } + public static Node ParseFromString(string str,string filename="memory.tlang") + { + var lexed=Lex.GetTokensFromString(str,filename); + return ParseFromLexContext(lexed); + } + + private Node ParseNode(bool isRoot=false,bool inCase=false) + { + + ScopeNode node = new ScopeNode(); + node.LineInfo = Context.CurrentLineInfo; + + + while(Context.Offset < Context.Tokens.Count && (isRoot || !Context.NextEntries(true,"}").Success)) + { + if(Context.NextEntries(true,"{").Success) + { + node.Add(ParseNode()); + } + node.Add(ParseAssigable()); + } + + return node; + } + + private Node ParseAssigable() + { + Node expr = ParseLOr(); + while(Context.NextEntryIsAnyOf(true,out var token,"=","+=","-=","*=","/=","%=","|=","&=","^=","^^=")) + { + if(token.Text == "=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,ParseLOr()){LineInfo=token.Position}; + } + if(token.Text == "+=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new AddNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "-=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new SubtractNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "*=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new MultiplyNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "/=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new DivideNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "%=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new ModuloNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "|=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new BOrNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "&=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new BAndNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "^=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new XOrNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + if(token.Text == "^^=") + { + var symbolNode = expr as SymbolNode; + if(symbolNode == null) throw new CompilerError("Assigning variable to something that is not a symbol",expr); + + expr = new SetVariableNode(symbolNode.Name,new PowNode(new GetVariableNode(symbolNode.Name),ParseLOr())){LineInfo=token.Position}; + } + } + return expr; + } + + private Node ParseLOr() + { + Node expr = ParseLAnd(); + while(Context.NextEntryIsAnyOf(true,out var token,"||")) + { + + + expr = new LOrNode(expr,ParseLAnd()){LineInfo=token.Position}; + + } + return expr; + } + + private Node ParseLAnd() + { + Node expr = ParseBOr(); + while(Context.NextEntryIsAnyOf(true,out var token,"&&")) + { + + + expr = new LAndNode(expr,ParseBOr()){LineInfo=token.Position}; + + } + return expr; + } + + private Node ParseBOr() + { + Node expr = ParseXOr(); + while(Context.NextEntryIsAnyOf(true,out var token,"|")) + { + + + expr = new BOrNode(expr,ParseXOr()){LineInfo=token.Position}; + + } + return expr; + } + + private Node ParseXOr() + { + Node expr = ParseBAnd(); + while(Context.NextEntryIsAnyOf(true,out var token,"^")) + { + + + expr = new XOrNode(expr,ParseBAnd()){LineInfo=token.Position}; + + } + return expr; + } + + private Node ParseBAnd() + { + Node expr = ParseEq(); + while(Context.NextEntryIsAnyOf(true,out var token,"&")) + { + + + expr = new BAndNode(expr,ParseEq()){LineInfo=token.Position}; + + } + return expr; + } + + private Node ParseEq() + { + Node expr = ParseRo(); + while(Context.NextEntryIsAnyOf(true,out var token,"==","!=")) + { + + if(token.Text == "==") + { + expr = new EqualsNode(expr,ParseRo()){LineInfo=token.Position}; + } + if(token.Text == "!=") + { + expr = new NotEqualsNode(expr,ParseRo()){LineInfo=token.Position}; + } + + + } + return expr; + } + + private Node ParseRo() + { + Node expr = ParseRo(); + while(Context.NextEntryIsAnyOf(true,out var token,"<","<=",">",">=")) + { + + if(token.Text == "<") + { + expr = new LessThanNode(expr,ParseShift()){LineInfo=token.Position}; + } + if(token.Text == "<=") + { + expr = new LessThanEqualsNode(expr,ParseShift()){LineInfo=token.Position}; + } + if(token.Text == ">") + { + expr = new GreaterThanNode(expr,ParseShift()){LineInfo=token.Position}; + } + if(token.Text == ">=") + { + expr = new GreaterThanEqualsNode(expr,ParseShift()){LineInfo=token.Position}; + } + + } + return expr; + } + private Node ParseShift() + { + Node expr = ParseSum(); + while(Context.NextEntryIsAnyOf(true,out var token,"<<",">>")) + { + + if(token.Text == "<<") + { + expr = new LeftShiftNode(expr,ParseSum()){LineInfo=token.Position}; + } + if(token.Text == ">>") + { + expr = new RightShiftNode(expr,ParseSum()){LineInfo=token.Position}; + } + + + } + return expr; + } + + private Node ParseSum() + { + Node expr = ParseFactor(); + while(Context.NextEntryIsAnyOf(true,out var token,"+","-")) + { + + if(token.Text == "+") + { + expr = new AddNode(expr,ParseFactor()){LineInfo=token.Position}; + } + if(token.Text == "-") + { + expr = new SubtractNode(expr,ParseFactor()){LineInfo=token.Position}; + } + + + } + return expr; + } + + private Node ParseFactor() + { + Node expr = ParseExpo(); + while(Context.NextEntryIsAnyOf(true,out var token,"*","/","%")) + { + + if(token.Text == "*") + { + expr = new MultiplyNode(expr,ParseExpo()){LineInfo=token.Position}; + } + if(token.Text == "/") + { + expr = new DivideNode(expr,ParseExpo()){LineInfo=token.Position}; + } + if(token.Text == "%") + { + expr = new ModuloNode(expr,ParseExpo()){LineInfo=token.Position}; + } + + } + return expr; + } + private Node ParseExpo() + { + Node expr = ParseValue(); + while(Context.NextEntryIsAnyOf(true,out var token,"^^")) + { + expr = new PowNode(expr,ParseValue()); + } + return expr; + } + + private Node ParseValue() + { + var doc = Context.PopDocumentation(); + var token = Context.NextEntry; + if(token.IsString) return new StringNode(token.Text){LineInfo = token.Position}; + if(token.IsChar) return new CharNode(token.Text){LineInfo = token.Position}; + if(token.Text == "(") + { + var assignable = ParseAssigable(); + assignable.LineInfo = token.Position; + if(!Context.NextEntries(true,")").Success) throw new CompilerError("symbol must be a ')'",assignable); + return assignable; + } + if(token.Text == "class") + { + ClassNode classInstance = new ClassNode(); + classInstance.Name = Context.NextEntry.Text; + classInstance.Documentation = doc; + + + if(Context.NextEntries(true,":").Success) + { + + classInstance.InheritsFrom = Context.NextEntry.Text; + + } + Context.NextEntries(true,"{"); + while(Context.MoreTokens && !Context.NextEntries(true,"}").Success) + { + var doc2 = Context.PopDocumentation(); + var token2 = Context.NextEntry; + var modifier = token2.Text; + if(Context.NextEntryIsAnyOf(true,out var token3,"func","abst")) + { + var name = Context.NextEntry.Text; + if(Context.NextEntries(true,"(").Success) + { + var pos = Context.PeekEntry.Position; + List args=new List(); + while(!Context.NextEntries(true,")").Success) + { + if(Context.NextEntries(true,",").Success) continue; + + if(Context.Offset < Context.Tokens.Count) + { + var n0 = ParseNode(); + var n= n0 as GetVariableNode; + if(n != null) + { + args.Add(n.Name); + } + else + { + throw new CompilerError("Argument must be a GetVariableNode",n0); + } + } + } + ClassEntryNode nod=new ClassEntryNode(){LineInfo = token2.Position}; + nod.Abstract = token3.Text == "abst"; + nod.Documentation = doc2; + nod.Modifier = modifier; + nod.Name = name; + nod.InitialValue = new ClosureNode(args,ParseNode()){LineInfo = pos}; + classInstance.Entries.Add(nod); + } + } + else + { + ClassEntryNode nod = new ClassEntryNode(){LineInfo = token2.Position}; + nod.Documentation = doc2; + nod.Name = Context.NextEntry.Text; + if(!Context.NextEntries(true,"=").Success) throw new CompilerError("Invalid member",classInstance); + + nod.Modifier = modifier; + nod.InitialValue = ParseNode(); + classInstance.Entries.Add(nod); + } + + } + return classInstance; + } + if(token.Text == "brk" || token.Text == "break") + { + return new BreakNode(){LineInfo = token.Position}; + } + if(token.Text == "cont" || token.Text == "continue") + { + return new ContinueNode(){LineInfo = token.Position}; + } + if(token.Text == "ret" || token.Text == "return") + { + return new ReturnNode(ParseNode()){LineInfo = token.Position}; + } + if(token.Text == "case") + { + var expr = ParseNode(); + if(!Context.NextEntries(true,":").Success) throw new CompilerError("Missing :",expr); + return new CaseNode(expr,ParseNode(true,true)){LineInfo = token.Position}; + } + if(token.Text == "default") + { + var cur = Context.CurrentLineInfo; + var r=Context.NextEntries(true,":"); + if(!r.Success) throw new CompilerError("Missing :",new Node(){LineInfo = cur}); + return new DefaultNode(ParseNode(true,true)){LineInfo = token.Position}; + } + if(token.Text == "-") + { + return new NegativeNode(ParseNode()); + } + if(token.Text == "~") + { + return new BitwiseNotNode(ParseNode()); + } + if(token.Text == "!") + { + return new NotNode(ParseNode()); + } + if(long.TryParse(token.Text,out var number)) + { + if(Context.NextEntries(true,".").Success) + { + var entry=Context.NextEntry; + if(!entry.IsChar && !entry.IsDocumentation && !entry.IsEmpty && !entry.IsString && double.TryParse($"{number}.{entry.Text}",out var number2)) + { + return new ConstNumberNode(number2); + } + } + + //just a long + return new ConstNumberNode(number); + + } + else + { + if(Context.NextEntries(true,"(").Success) + { + if(token.Text == "func") + { + List args=new List(); + while(!Context.NextEntries(true,")").Success) + { + if(Context.NextEntries(true,",").Success) continue; + + if(Context.Offset < Context.Tokens.Count) + { + var n0 = ParseNode(); + var n= n0 as GetVariableNode; + if(n != null) + { + args.Add(n.Name); + } + else + { + throw new CompilerError("Argument must be a GetVariableNode",n0); + } + } + } + return new ClosureNode(args,ParseNode()); + } + else if(token.Text == "for") + { + Node init=new Node(); + Node condition = new Node(); + Node inc = new Node(); + Node body = new Node(); + if(Context.MoreTokens && (Context.PeekEntry.Text != ")" || Context.PeekEntry.Text != ";")) + { + init = ParseNode(); + } + Context.NextEntries(true,";"); + if(Context.MoreTokens && (Context.PeekEntry.Text != ")" || Context.PeekEntry.Text != ";")) + { + condition = ParseNode(); + } + Context.NextEntries(true,";"); + if(Context.MoreTokens && (Context.PeekEntry.Text != ")" || Context.PeekEntry.Text != ";")) + { + inc = ParseNode(); + } + Context.NextEntries(true,")"); + if(Context.MoreTokens) + body = ParseNode(); + + return new ForLoopNode(init,condition,inc,body); + } + else if(token.Text == "each") + { + SymbolNode varNode = new GetVariableNode("item"){LineInfo = token.Position}; + Node expr = ParseNode(); + + if(Context.NextEntries(true,":").Success) + { + var vNode = expr as SymbolNode; + if(vNode != null) + { + varNode = vNode; + } + expr = ParseNode(); + + } + Context.NextEntries(true,")"); + if(Context.MoreTokens) + { + return new EachLoopNode(varNode,expr,ParseNode()){LineInfo = token.Position}; + } + } + else if(token.Text == "switch") + { + Node cond = ParseNode(); + Context.NextEntries(true,")"); + Node body = new Node(); + if(!Context.NextEntries(true,";").Success) + { + body = ParseNode(); + } + var scopeBody = body as ScopeNode; + if(scopeBody != null) + { + scopeBody.IsSwitchScope=true; + scopeBody.SwitchCondition = cond; + } + return body; + } + else if(token.Text == "while" || token.Text == "do") + { + Node cond = ParseNode(); + Context.NextEntries(true,")"); + Node body = new Node(); + if(!Context.NextEntries(true,";").Success) + { + body = ParseNode(); + } + return new WhileLoop(cond,body,token.Text == "do"); + } + else if(token.Text == "if") + { + Node cond = ParseNode(); + Context.NextEntries(true,")"); + Node yes = new Node(); + Node no = new Node(); + if(Context.MoreTokens && !Context.NextEntries(false,"else").Success) + { + yes = ParseNode(); + } + if(Context.MoreTokens && Context.NextEntries(true,"else").Success) + { + no = ParseNode(); + } + return new IfNode(cond,yes,no); + } + else + { + var fcall = new FunctionCallNode(token.Text){LineInfo = token.Position}; + SymbolNode ret = fcall; + while(Context.MoreTokens && !Context.NextEntries(true,")").Success) + { + if(Context.NextEntries(true,",").Success) continue; + fcall.Arguments.Add(ParseNode()); + } + while(Context.MoreTokens && Context.NextEntries(true,"[").Success) + { + var p = ParseNode(); + ret = new GetArrayNode(ret,p){LineInfo = p.LineInfo}; + Context.NextEntries(true,"]"); + } + while(Context.MoreTokens && Context.NextEntries(true,".").Success) + { + var token2 = Context.NextEntry; + + if(Context.MoreTokens && Context.NextEntries(true,"(").Success) + { + var mCall = new MethodCallNode(ret,token2.Text){LineInfo=token2.Position}; + ret = mCall; + while(Context.MoreTokens && !Context.NextEntries(true,")").Success) + { + if(Context.NextEntries(true,",").Success) continue; + mCall.Arguments.Add(ParseNode()); + } + } + else if(Context.MoreTokens && Context.NextEntries(false,"[").Success) + { + while(Context.MoreTokens && Context.NextEntries(true,"[").Success) + { + var p = ParseNode(); + ret = new GetArrayNode(ret,p){LineInfo = p.LineInfo}; + Context.NextEntries(true,"]"); + } + } + else + { + ret = new GetMemberNode(ret,token2.Text){LineInfo = token2.Position}; + } + + } + if(Context.MoreTokens && Context.NextEntries(true,"++").Success) + { + var r = new PostFixIncrementNode(ret){LineInfo = ret.LineInfo}; + ret = r; + } + if(Context.MoreTokens && Context.NextEntries(true,"--").Success) + { + var r = new PostFixDecrementNode(ret){LineInfo = ret.LineInfo}; + ret = r; + } + return ret; + } + } + else{ + Node ret = new Node(); + if(token.Text == "func") + { + var res = new GetVariableNode(Context.NextEntry.Text); + } + } + } + + throw new CompilerError("End of ParseValue func",new Node(){LineInfo = token.Position}); + } + + } +} diff --git a/TLang.Parser/ClassEntryNode.cs b/TLang.Parser/ClassEntryNode.cs new file mode 100644 index 0000000..89e0a71 --- /dev/null +++ b/TLang.Parser/ClassEntryNode.cs @@ -0,0 +1,12 @@ +namespace TLang.Parser +{ + public class ClassEntryNode : Node + { + public string Name {get;set;}=""; + public string Modifier {get;set;}=""; + + public string Documentation {get;set;}=""; + public Node InitialValue {get;set;}=new Node(); + public bool Abstract { get; set; }=false; + } +} \ No newline at end of file diff --git a/TLang.Parser/ClassNode.cs b/TLang.Parser/ClassNode.cs new file mode 100644 index 0000000..fcb79db --- /dev/null +++ b/TLang.Parser/ClassNode.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace TLang.Parser +{ + public class ClassNode : Node + { + public string Documentation {get;set;} + public string Name {get;set;} + public string InheritsFrom {get;set;}="object"; + + public List Entries {get;set;}=new List(); + } +} \ No newline at end of file diff --git a/TLang.Parser/ClosureNode.cs b/TLang.Parser/ClosureNode.cs new file mode 100644 index 0000000..acf234d --- /dev/null +++ b/TLang.Parser/ClosureNode.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace TLang.Parser +{ + public class ClosureNode : Node + { + public List Arguments {get;set;} + public Node Node {get;set;} + + public ClosureNode(List args, Node node) + { + Arguments = args; + Node = node; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/CompilerError.cs b/TLang.Parser/CompilerError.cs new file mode 100644 index 0000000..8352d83 --- /dev/null +++ b/TLang.Parser/CompilerError.cs @@ -0,0 +1,39 @@ +using System; +using System.Runtime.Serialization; + +namespace TLang.Parser +{ + [Serializable] + public class CompilerError : Exception + { + private string ErrorMessage {get;set;} + private Node CurrentNode {get;set;} + + public CompilerError() + { + } + + public CompilerError(string message) : base(message) + { + } + + public CompilerError(string v, Node node) : base(GenerateMessage(v,node)) + { + this.ErrorMessage = v; + this.CurrentNode = node; + } + + private static string GenerateMessage(string v, Node node) + { + return $"Compiler Error {node.LineInfo}: {v}"; + } + + public CompilerError(string message, Exception innerException) : base(message, innerException) + { + } + + protected CompilerError(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/TLang.Parser/ConstNumberNode.cs b/TLang.Parser/ConstNumberNode.cs new file mode 100644 index 0000000..67e7b65 --- /dev/null +++ b/TLang.Parser/ConstNumberNode.cs @@ -0,0 +1,12 @@ +namespace TLang.Parser +{ + public class ConstNumberNode : Node + { + public double Value {get;set;} + + public ConstNumberNode(double number2) + { + this.Value = number2; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/ContinueNode.cs b/TLang.Parser/ContinueNode.cs new file mode 100644 index 0000000..cd752da --- /dev/null +++ b/TLang.Parser/ContinueNode.cs @@ -0,0 +1,6 @@ +namespace TLang.Parser +{ + public class ContinueNode : Node + { + } +} \ No newline at end of file diff --git a/TLang.Parser/DefaultNode.cs b/TLang.Parser/DefaultNode.cs new file mode 100644 index 0000000..fe451bd --- /dev/null +++ b/TLang.Parser/DefaultNode.cs @@ -0,0 +1,16 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + public class DefaultNode : Node + { + public Node Node {get;set;} + + public DefaultNode(Node node) + { + Node = node; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/DivideNode.cs b/TLang.Parser/DivideNode.cs new file mode 100644 index 0000000..9cda4e2 --- /dev/null +++ b/TLang.Parser/DivideNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class DivideNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public DivideNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/EachLoopNode.cs b/TLang.Parser/EachLoopNode.cs new file mode 100644 index 0000000..67739d0 --- /dev/null +++ b/TLang.Parser/EachLoopNode.cs @@ -0,0 +1,16 @@ +namespace TLang.Parser +{ + public class EachLoopNode : Node + { + public SymbolNode Name {get;set;} + public Node Itterator {get;set;} + public Node Body {get;set;} + + public EachLoopNode(SymbolNode varNode, Node expr, Node node) + { + Name = varNode; + Itterator = expr; + Body = node; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/EqualsNode.cs b/TLang.Parser/EqualsNode.cs new file mode 100644 index 0000000..7b095d7 --- /dev/null +++ b/TLang.Parser/EqualsNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class EqualsNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public EqualsNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/ForLoopNode.cs b/TLang.Parser/ForLoopNode.cs new file mode 100644 index 0000000..c4b2b32 --- /dev/null +++ b/TLang.Parser/ForLoopNode.cs @@ -0,0 +1,18 @@ +namespace TLang.Parser +{ + public class ForLoopNode : Node + { + public Node Init {get;set;} + public Node Condition {get;set;} + public Node Increment {get;set;} + public Node Body {get;set;} + + public ForLoopNode(Node init, Node condition, Node inc, Node body) + { + Init = init; + Condition = condition; + Increment = inc; + Body = body; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/FunctionCallNode.cs b/TLang.Parser/FunctionCallNode.cs new file mode 100644 index 0000000..4cc05c7 --- /dev/null +++ b/TLang.Parser/FunctionCallNode.cs @@ -0,0 +1,12 @@ +namespace TLang.Parser +{ + public class FunctionCallNode : CallNode + { + + + public FunctionCallNode(string text) + { + Name = text; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/GetArrayNode.cs b/TLang.Parser/GetArrayNode.cs new file mode 100644 index 0000000..c558f83 --- /dev/null +++ b/TLang.Parser/GetArrayNode.cs @@ -0,0 +1,15 @@ +namespace TLang.Parser +{ + public class GetArrayNode : SymbolNode + { + public SymbolNode Symbol {get;set;} + public Node Expression {get;set;} + + public GetArrayNode(SymbolNode sym, Node expr) + { + Symbol = sym; + this.Name = sym.Name; + Expression = expr; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/GetMemberNode.cs b/TLang.Parser/GetMemberNode.cs new file mode 100644 index 0000000..92f4547 --- /dev/null +++ b/TLang.Parser/GetMemberNode.cs @@ -0,0 +1,17 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + internal class GetMemberNode : SymbolNode + { + public SymbolNode Symbol {get;set;} + + public GetMemberNode(SymbolNode symbol, string name) + { + Symbol = symbol; + Name = name; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/GetVariableNode.cs b/TLang.Parser/GetVariableNode.cs new file mode 100644 index 0000000..d1118b1 --- /dev/null +++ b/TLang.Parser/GetVariableNode.cs @@ -0,0 +1,12 @@ +namespace TLang.Parser +{ + public class GetVariableNode : SymbolNode + { + + + public GetVariableNode(string name) + { + Name = name; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/GreaterThanEqualsNode.cs b/TLang.Parser/GreaterThanEqualsNode.cs new file mode 100644 index 0000000..b578cdd --- /dev/null +++ b/TLang.Parser/GreaterThanEqualsNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class GreaterThanEqualsNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public GreaterThanEqualsNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/GreaterThanNode.cs b/TLang.Parser/GreaterThanNode.cs new file mode 100644 index 0000000..10ff18a --- /dev/null +++ b/TLang.Parser/GreaterThanNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class GreaterThanNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public GreaterThanNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/IfNode.cs b/TLang.Parser/IfNode.cs new file mode 100644 index 0000000..8aa1100 --- /dev/null +++ b/TLang.Parser/IfNode.cs @@ -0,0 +1,16 @@ +namespace TLang.Parser +{ + internal class IfNode : Node + { + public Node Condition {get;set;} + public Node Yes {get;set;} + public Node No {get;set;} + + public IfNode(Node cond, Node yes, Node no) + { + Condition = cond; + Yes = yes; + No = no; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/LAndNode.cs b/TLang.Parser/LAndNode.cs new file mode 100644 index 0000000..21cc1e8 --- /dev/null +++ b/TLang.Parser/LAndNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class LAndNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public LAndNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/LOrNode.cs b/TLang.Parser/LOrNode.cs new file mode 100644 index 0000000..cc8a708 --- /dev/null +++ b/TLang.Parser/LOrNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class LOrNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public LOrNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/LeftShiftNode.cs b/TLang.Parser/LeftShiftNode.cs new file mode 100644 index 0000000..034f544 --- /dev/null +++ b/TLang.Parser/LeftShiftNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class LeftShiftNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public LeftShiftNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/LessThanEqualsNode.cs b/TLang.Parser/LessThanEqualsNode.cs new file mode 100644 index 0000000..31f5c6c --- /dev/null +++ b/TLang.Parser/LessThanEqualsNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class LessThanEqualsNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public LessThanEqualsNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/LessThanNode.cs b/TLang.Parser/LessThanNode.cs new file mode 100644 index 0000000..505b919 --- /dev/null +++ b/TLang.Parser/LessThanNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class LessThanNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public LessThanNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/MethodCallNode.cs b/TLang.Parser/MethodCallNode.cs new file mode 100644 index 0000000..a689c47 --- /dev/null +++ b/TLang.Parser/MethodCallNode.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using TLang.Lexer; + +namespace TLang.Parser +{ + public class MethodCallNode : SymbolNode + { + public SymbolNode Symbol {get;set;} + public List Arguments {get;set;}=new List(); + + public MethodCallNode(SymbolNode symbol, string name) + { + Symbol = symbol; + Name = name; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/ModuloNode.cs b/TLang.Parser/ModuloNode.cs new file mode 100644 index 0000000..faca061 --- /dev/null +++ b/TLang.Parser/ModuloNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class ModuloNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public ModuloNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/MultiplyNode.cs b/TLang.Parser/MultiplyNode.cs new file mode 100644 index 0000000..54a5cc9 --- /dev/null +++ b/TLang.Parser/MultiplyNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class MultiplyNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public MultiplyNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/NegativeNode.cs b/TLang.Parser/NegativeNode.cs new file mode 100644 index 0000000..8f05038 --- /dev/null +++ b/TLang.Parser/NegativeNode.cs @@ -0,0 +1,16 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + public class NegativeNode : Node + { + public Node Node {get;set;} + + public NegativeNode(Node node) + { + Node = node; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/Node.cs b/TLang.Parser/Node.cs new file mode 100644 index 0000000..509ad7f --- /dev/null +++ b/TLang.Parser/Node.cs @@ -0,0 +1,10 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + public class Node + { + public LexLineInfo LineInfo {get;set;} + + } +} \ No newline at end of file diff --git a/TLang.Parser/NotEqualsNode.cs b/TLang.Parser/NotEqualsNode.cs new file mode 100644 index 0000000..71901b9 --- /dev/null +++ b/TLang.Parser/NotEqualsNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class NotEqualsNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public NotEqualsNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/NotNode.cs b/TLang.Parser/NotNode.cs new file mode 100644 index 0000000..0fba76d --- /dev/null +++ b/TLang.Parser/NotNode.cs @@ -0,0 +1,16 @@ +using TLang.Lexer; + +namespace TLang.Parser +{ + public class NotNode : Node + { + public Node Node {get;set;} + + public NotNode(Node node) + { + Node = node; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/PostFixDecrementNode.cs b/TLang.Parser/PostFixDecrementNode.cs new file mode 100644 index 0000000..d274f7d --- /dev/null +++ b/TLang.Parser/PostFixDecrementNode.cs @@ -0,0 +1,15 @@ +namespace TLang.Parser +{ + public class PostFixDecrementNode : SymbolNode + { + public SymbolNode SymbolNode {get;set;} + + public PostFixDecrementNode(SymbolNode symbol) + { + SymbolNode = symbol; + Name = symbol.Name; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/PostFixIncrementNode.cs b/TLang.Parser/PostFixIncrementNode.cs new file mode 100644 index 0000000..7d75116 --- /dev/null +++ b/TLang.Parser/PostFixIncrementNode.cs @@ -0,0 +1,15 @@ +namespace TLang.Parser +{ + public class PostFixIncrementNode : SymbolNode + { + public SymbolNode SymbolNode {get;set;} + + public PostFixIncrementNode(SymbolNode symbol) + { + SymbolNode = symbol; + Name = symbol.Name; + } + + + } +} \ No newline at end of file diff --git a/TLang.Parser/PowNode.cs b/TLang.Parser/PowNode.cs new file mode 100644 index 0000000..a6b7568 --- /dev/null +++ b/TLang.Parser/PowNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class PowNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public PowNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/ReturnNode.cs b/TLang.Parser/ReturnNode.cs new file mode 100644 index 0000000..9d912ec --- /dev/null +++ b/TLang.Parser/ReturnNode.cs @@ -0,0 +1,12 @@ +namespace TLang.Parser +{ + public class ReturnNode : Node + { + public Node Expression {get;set;} + + public ReturnNode(Node node) + { + Expression = node; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/RightShiftNode.cs b/TLang.Parser/RightShiftNode.cs new file mode 100644 index 0000000..8420fba --- /dev/null +++ b/TLang.Parser/RightShiftNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class RightShiftNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public RightShiftNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/ScopeNode.cs b/TLang.Parser/ScopeNode.cs new file mode 100644 index 0000000..e719f9c --- /dev/null +++ b/TLang.Parser/ScopeNode.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace TLang.Parser +{ + public class ScopeNode : Node + { + public bool IsSwitchScope {get;set;} + public Node SwitchCondition {get;set;}=new Node(); + public List Nodes {get;set;}=new List(); + public void Add(Node node) + { + Nodes.Add(node); + } + } +} \ No newline at end of file diff --git a/TLang.Parser/SetVariableNode.cs b/TLang.Parser/SetVariableNode.cs new file mode 100644 index 0000000..95c9ce8 --- /dev/null +++ b/TLang.Parser/SetVariableNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class SetVariableNode : SymbolNode + { + + public Node Expression {get;set;} + + public SetVariableNode(string name, Node expr) + { + Name = name; + Expression = expr; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/StringNode.cs b/TLang.Parser/StringNode.cs new file mode 100644 index 0000000..6a8a3c1 --- /dev/null +++ b/TLang.Parser/StringNode.cs @@ -0,0 +1,12 @@ +namespace TLang.Parser +{ + public class StringNode : Node + { + public string Text {get;set;} + + public StringNode(string text) + { + Text = text; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/SubtractNode.cs b/TLang.Parser/SubtractNode.cs new file mode 100644 index 0000000..70b61e9 --- /dev/null +++ b/TLang.Parser/SubtractNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class SubtractNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public SubtractNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/SymbolNode.cs b/TLang.Parser/SymbolNode.cs new file mode 100644 index 0000000..f4576cc --- /dev/null +++ b/TLang.Parser/SymbolNode.cs @@ -0,0 +1,7 @@ +namespace TLang.Parser +{ + public class SymbolNode : Node + { + public string Name {get;set;} + } +} \ No newline at end of file diff --git a/TLang.Parser/TLang.Parser.csproj b/TLang.Parser/TLang.Parser.csproj new file mode 100644 index 0000000..3c13304 --- /dev/null +++ b/TLang.Parser/TLang.Parser.csproj @@ -0,0 +1,11 @@ + + + + + + + + netstandard2.0 + + + diff --git a/TLang.Parser/WhileLoop.cs b/TLang.Parser/WhileLoop.cs new file mode 100644 index 0000000..9a41046 --- /dev/null +++ b/TLang.Parser/WhileLoop.cs @@ -0,0 +1,17 @@ +namespace TLang.Parser +{ + public class WhileLoop : Node + { + public Node Condition {get;set;} + public Node Body {get;set;} + + public bool IsDo {get;set;} + + public WhileLoop(Node cond, Node body, bool v) + { + Condition = cond; + Body = body; + IsDo = v; + } + } +} \ No newline at end of file diff --git a/TLang.Parser/XOrNode.cs b/TLang.Parser/XOrNode.cs new file mode 100644 index 0000000..c36f24f --- /dev/null +++ b/TLang.Parser/XOrNode.cs @@ -0,0 +1,14 @@ +namespace TLang.Parser +{ + public class XOrNode : Node + { + private Node Left {get;set;} + private Node Right {get;set;} + + public XOrNode(Node left, Node right) + { + Left = left; + Right = right; + } + } +} \ No newline at end of file