2023-07-27 03:31:32 +00:00
|
|
|
|
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<ctx.Length;i++)
|
|
|
|
|
{
|
|
|
|
|
ctx2 += ctx[i];
|
|
|
|
|
}
|
|
|
|
|
Parse p=new Parse(ctx2);
|
|
|
|
|
p.ParseNodeRoot();
|
|
|
|
|
return p.Node;
|
|
|
|
|
}
|
|
|
|
|
return new Node();
|
|
|
|
|
}
|
|
|
|
|
public static Node ParseFromTextReader(TextReader reader,string filename="memory.tlang")
|
|
|
|
|
{
|
|
|
|
|
var lexed = Lex.GetTokens(reader,filename);
|
|
|
|
|
return ParseFromLexContext(lexed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Node ParseFromFiles(params string[] filenames)
|
|
|
|
|
{
|
|
|
|
|
return ParseFromLexContext(filenames.Select<string,LexContext>(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<string> args=new List<string>();
|
|
|
|
|
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<string> args=new List<string>();
|
|
|
|
|
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);
|
2023-07-27 03:33:22 +00:00
|
|
|
|
if(Context.MoreTokens && Context.)
|
2023-07-27 03:31:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new CompilerError("End of ParseValue func",new Node(){LineInfo = token.Position});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|