247 lines
8.6 KiB
C#
247 lines
8.6 KiB
C#
|
namespace tlang
|
||
|
{
|
||
|
internal class Parser
|
||
|
{
|
||
|
|
||
|
public Parser()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
public Node ParseExpression(List<LexToken> tokens,ref int i,bool isFirst=false)
|
||
|
{
|
||
|
if(tokens[i].Text == "{" || isFirst)
|
||
|
{
|
||
|
if(!isFirst)
|
||
|
i++;
|
||
|
ScopeNode scopeNode = new ScopeNode();
|
||
|
while(i<tokens.Count && tokens[i].Text != "}")
|
||
|
{
|
||
|
scopeNode.Body.Add(ParseExpression(tokens,ref i));
|
||
|
if(i<tokens.Count && tokens[i].Text == ";")
|
||
|
{
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
i++;
|
||
|
return scopeNode;
|
||
|
}else{
|
||
|
return ParseAssignable(tokens,ref i);
|
||
|
}
|
||
|
}
|
||
|
private Node ParseAssignable(List<LexToken> tokens,ref int i)
|
||
|
{
|
||
|
Node myExpression = ParseSum(tokens,ref i);
|
||
|
while(i<tokens.Count && (tokens[i].Text == "="))
|
||
|
{
|
||
|
if(i<tokens.Count && tokens[i].Text == "=")
|
||
|
{
|
||
|
i++;
|
||
|
GetVariableValue? gvar = myExpression as GetVariableValue;
|
||
|
if(gvar != null)
|
||
|
{
|
||
|
myExpression= new SetVariableNode(gvar.Name,ParseSum(tokens,ref i));
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return myExpression;
|
||
|
}
|
||
|
private Node ParseSum(List<LexToken> tokens,ref int i)
|
||
|
{
|
||
|
Node myExpression = ParseFactor(tokens,ref i);
|
||
|
while(i<tokens.Count && (tokens[i].Text == "+" || tokens[i].Text == "-"))
|
||
|
{
|
||
|
|
||
|
if(i<tokens.Count && tokens[i].Text == "+"){
|
||
|
i++;
|
||
|
myExpression = new AddNode(myExpression,ParseFactor(tokens,ref i));
|
||
|
}
|
||
|
|
||
|
|
||
|
if(i<tokens.Count && tokens[i].Text == "-")
|
||
|
{
|
||
|
i++;
|
||
|
myExpression = new SubtractNode(myExpression,ParseFactor(tokens,ref i));
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
return myExpression;
|
||
|
}
|
||
|
private Node ParseValue(List<LexToken> tokens,ref int i)
|
||
|
{
|
||
|
var token=tokens[i++];
|
||
|
if(token.IsString) return new ConstNode(new TString(token.Text));
|
||
|
if(token.IsChar)
|
||
|
{
|
||
|
return new ConstNode(new TNumber(token.Text.SingleOrDefault()));
|
||
|
}
|
||
|
|
||
|
long val;
|
||
|
if(long.TryParse(token.Text,out val))
|
||
|
{
|
||
|
if(i<tokens.Count && tokens[i].Text == "." && !tokens[i].IsChar && !tokens[i].IsString)
|
||
|
{
|
||
|
i++;
|
||
|
if(i<tokens.Count)
|
||
|
{
|
||
|
var token2=tokens[i++];
|
||
|
double dblR;
|
||
|
if(double.TryParse($"{val}.{token2.Text}",out dblR))
|
||
|
{
|
||
|
return new ConstNode(new TNumber(dblR));
|
||
|
}
|
||
|
}
|
||
|
}else{
|
||
|
return new ConstNode(new TNumber( val ));
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if(i<tokens.Count && tokens[i].Text=="(")
|
||
|
{
|
||
|
if(token.Text == "func")
|
||
|
{
|
||
|
List<string> args = new List<string>();
|
||
|
i++;
|
||
|
while(i<tokens.Count && tokens[i].Text != ")")
|
||
|
{
|
||
|
|
||
|
if(tokens[i].Text == ",") {i++;continue;}
|
||
|
|
||
|
if(i<tokens.Count)
|
||
|
{
|
||
|
var exp = ParseExpression(tokens,ref i);
|
||
|
var gvExp = exp as GetVariableValue;
|
||
|
if(gvExp != null)
|
||
|
{
|
||
|
args.Add(gvExp.Name);
|
||
|
}else{
|
||
|
throw new Exception("not a getvariablenode");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
i++;
|
||
|
return new ClosureNode(args,ParseExpression(tokens,ref i));
|
||
|
} else if(token.Text == "if")
|
||
|
{
|
||
|
i++;
|
||
|
var condition=ParseExpression(tokens,ref i);
|
||
|
i++;
|
||
|
Node yes = new ConstNode(new TUninit());
|
||
|
Node no = new ConstNode(new TUninit());
|
||
|
if(i<tokens.Count && tokens[i].Text != "else")
|
||
|
yes=ParseExpression(tokens,ref i);
|
||
|
|
||
|
if(i<tokens.Count && tokens[i].Text == "else")
|
||
|
{
|
||
|
i++;
|
||
|
no = ParseExpression(tokens,ref i);
|
||
|
}
|
||
|
|
||
|
return new IfNode(condition,yes,no);
|
||
|
}
|
||
|
else{
|
||
|
i++;
|
||
|
List<Node> args = new List<Node>();
|
||
|
//function call baby
|
||
|
while(i<tokens.Count && tokens[i].Text != ")")
|
||
|
{
|
||
|
|
||
|
if(tokens[i].Text == ",") {i++;continue;}
|
||
|
|
||
|
if(i<tokens.Count)
|
||
|
{
|
||
|
args.Add(ParseExpression(tokens,ref i));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
i++;
|
||
|
var ret = new FunctionCallNode(token.Text,args);
|
||
|
while(i<tokens.Count && tokens[i].Text == ".")
|
||
|
{
|
||
|
i++;
|
||
|
|
||
|
var token2 = tokens[i++];
|
||
|
|
||
|
if(i<tokens.Count && tokens[i].Text == "(")
|
||
|
{
|
||
|
i++;
|
||
|
args = new List<Node>();
|
||
|
//function call baby
|
||
|
while(i<tokens.Count && tokens[i].Text != ")")
|
||
|
{
|
||
|
|
||
|
if(tokens[i].Text == ",") {i++;continue;}
|
||
|
|
||
|
if(i<tokens.Count)
|
||
|
{
|
||
|
args.Add(ParseExpression(tokens,ref i));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
i++;
|
||
|
ret = new MemberFunctionCallNode(ret,token2.Text,args);
|
||
|
}
|
||
|
else if(i<tokens.Count && tokens[i].Text == "[")
|
||
|
{
|
||
|
|
||
|
}
|
||
|
else{
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
}else{
|
||
|
switch(token.Text)
|
||
|
{
|
||
|
case "null":
|
||
|
return new ConstNode(TObject.Null);
|
||
|
case "undefined":
|
||
|
return new ConstNode(TObject.Uninit);
|
||
|
case "true":
|
||
|
return new ConstNode(new TNumber(1));
|
||
|
case "false":
|
||
|
return new ConstNode(new TNumber(0));
|
||
|
default:
|
||
|
return new GetVariableValue(token.Text);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
throw new Exception();
|
||
|
}
|
||
|
|
||
|
private Node ParseFactor(List<LexToken> tokens,ref int i)
|
||
|
{
|
||
|
Node myExpression = ParseValue(tokens,ref i);
|
||
|
while(i<tokens.Count && (tokens[i].Text == "*" || tokens[i].Text == "/" || tokens[i].Text == "%"))
|
||
|
{
|
||
|
|
||
|
if(i<tokens.Count && tokens[i].Text == "*"){
|
||
|
i++;
|
||
|
myExpression = new MultiplyNode(myExpression,ParseValue(tokens,ref i));
|
||
|
}
|
||
|
if(i<tokens.Count && tokens[i].Text == "/")
|
||
|
{
|
||
|
i++;
|
||
|
myExpression = new DivideNode(myExpression,ParseValue(tokens,ref i));
|
||
|
}
|
||
|
if(i<tokens.Count && tokens[i].Text == "%")
|
||
|
{
|
||
|
i++;
|
||
|
myExpression = new ModuloNode(myExpression,ParseValue(tokens,ref i));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return myExpression;
|
||
|
}
|
||
|
}
|
||
|
}
|