private static ASTNode ParseSingleStatement() { ASTNode ret = null; if (currentTokens[currentToken] is StringToken) { ret = new ASTString { String = currentTokens[currentToken].Token }; currentToken++; } else if (currentTokens[currentToken] is NumberToken) { double dResult; if (double.TryParse(currentTokens[currentToken].Token, NumberStyles.Any, CultureInfo.GetCultureInfo("en"), out dResult)) { ret = new ASTNumber { Number = dResult }; } else { throw new ParserException(string.Format("Number {0} is not valid.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber); } currentToken++; } else if (currentTokens[currentToken] is ReservedWordToken) { if (currentTokens[currentToken].Token == "this" || currentTokens[currentToken].Token == "VM") { string scope = currentTokens[currentToken].Token; currentToken++; if (currentTokens[currentToken] is SpecialToken && currentTokens[currentToken].Token == ".") { currentToken++; ret = ParseFunctionCallOrParameterAccess(scope); } else { throw new ParserException(string.Format("Expected '.' instead of '{0}'.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber); } } else if (currentTokens[currentToken].Token == "object" || currentTokens[currentToken].Token == "string" || currentTokens[currentToken].Token == "number") { VMType type = currentTokens[currentToken].Token == "number" ? VMType.Number : (currentTokens[currentToken].Token == "string" ? VMType.String : VMType.Object); currentToken++; if (currentTokens[currentToken] is IdentifierToken) { ret = new ASTLocalVariable() { Type = type, Name = currentTokens[currentToken].Token }; } else { throw new ParserException("Expected Identifier.", currentTokens[currentToken].LineNumber); } currentToken++; } else if (currentTokens[currentToken].Token == "new") { currentToken++; ASTNode createClass = ParseFunctionCallOrParameterAccess("constructor"); if (createClass is ASTFunctionCall) { ASTFunctionCall fc = (ASTFunctionCall)createClass; ret = new ASTCreateClass() { Scope = fc.FunctionName, FunctionName = fc.FunctionName, Parameter = fc.Parameter }; } else { throw new ParserException("Error with new.", currentTokens[currentToken].LineNumber); } } else if (currentTokens[currentToken].Token == "return") { currentToken++; ret = new ASTReturn() { Return = ParseStatement() }; // Point to ';' again!!! --currentToken; } else { throw new ParserException(string.Format("Reserved Word {0} is not legal in Statement.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber); } } else if (currentTokens[currentToken] is IdentifierToken) { string identifierOrScope = currentTokens[currentToken].Token; currentToken++; if (currentTokens[currentToken] is SpecialToken) { if (currentTokens[currentToken].Token == ".") { currentToken++; TokenBase isFunction = currentTokens[currentToken + 1]; ret = ParseFunctionCallOrParameterAccess(identifierOrScope); } else if (currentTokens[currentToken].Token == "(") { // Set focus again to the function name --currentToken; ret = ParseFunctionCallOrParameterAccess("this"); } else if (currentTokens[currentToken].Token == "[") { currentToken++; ASTStatement statement = ParseStatement(); if (statement == null) { throw new ParserException("Expected Statement for Parameter Access.", currentTokens[currentToken].LineNumber); } ret = new ASTClassParameter() { Scope = identifierOrScope, Parameter = statement }; } else { ret = new ASTIdentifier() { Identifier = identifierOrScope }; } } else { ret = new ASTIdentifier() { Identifier = identifierOrScope }; } } if (ret == null) { throw new ParserException(String.Format("Problems parsing the Identifier/Function Call/String/Number {0}.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber); } return(ret); }
public static List <ASTClass> Parse(this Compiler compiler, List <TokenBase> tokens) { currentTokens = tokens; currentToken = 0; List <ASTClass> classes = new List <ASTClass>(); while (currentToken < currentTokens.Count) { if (currentTokens[currentToken].Token == "class") { currentToken++; currentClassName = currentTokens[currentToken].Token; currentToken++; if (currentTokens[currentToken].Token != "{") { throw new ParserException("Expected '{'.", currentTokens[currentToken].LineNumber); } currentToken++; List <ASTConstructor> constructors = new List <ASTConstructor>(); List <ASTFunction> functions = new List <ASTFunction>(); List <ASTClassAttribute> attributes = new List <ASTClassAttribute>(); while (currentToken < currentTokens.Count) { if (currentTokens[currentToken].Token == "function") { currentToken++; ASTFunction func = ParseFunction(); if (func is ASTConstructor) { constructors.Add((ASTConstructor)func); } else { functions.Add(func); } } else if (currentTokens[currentToken].Token == "number" || currentTokens[currentToken].Token == "string" || currentTokens[currentToken].Token == "object") { ASTNode node = ParseSingleStatement(); if (node is ASTLocalVariable) { ASTLocalVariable lv = (ASTLocalVariable)node; attributes.Add(new ASTClassAttribute() { Type = lv.Type, Name = lv.Name }); if (currentTokens[currentToken].Token == ";") { currentToken++; } else { throw new ParserException("Expected ';'.", currentTokens[currentToken].LineNumber); } } else { throw new ParserException("Expected '}' or attribute or function.", currentTokens[currentToken].LineNumber); } } else if (currentTokens[currentToken].Token == "}") { currentToken++; classes.Add(new ASTClass() { Name = currentClassName, Constructors = constructors, Functions = functions, Attributes = attributes }); break; } else { throw new ParserException("Expected '}' or attribute or function.", currentTokens[currentToken].LineNumber); } } } else { throw new ParserException("Expected class.", currentTokens[currentToken].LineNumber); } } return(classes); }
private static void PrintNode(ASTNode node, int incident) { if (node == null) { return; } for (int i = 0; i < incident; i++) { sw.Write("\t"); } if (node is ASTString) { sw.WriteLine("ASTString: " + ((ASTString)node).String.Replace("\n", "\\n")); } else if (node is ASTNumber) { sw.WriteLine("ASTNumber: " + ((ASTNumber)node).Number); } else if (node is ASTIdentifier) { sw.WriteLine("ASTIdentifier: " + ((ASTIdentifier)node).Identifier); } else if (node is ASTOperator) { ASTOperator op = (ASTOperator)node; sw.WriteLine("ASTOperator: " + op.Operator); PrintNode(op.Left, incident + 1); PrintNode(op.Right, incident + 1); } else if (node is ASTStatement) { ASTStatement stm = (ASTStatement)node; sw.WriteLine("ASTStatement: "); PrintNode(stm.Statement, incident + 1); } else if (node is ASTFunctionCall) { ASTFunctionCall call = (ASTFunctionCall)node; sw.WriteLine("ASTFunctionCall: " + call.Scope + "." + call.FunctionName); foreach (ASTNode param in call.Parameter) { PrintNode(param, incident + 1); } } else if (node is ASTClassParameter) { ASTClassParameter classP = (ASTClassParameter)node; sw.WriteLine("ASTClassParameter: " + classP.Scope); PrintNode(classP.Parameter, incident + 1); } else if (node is ASTIf) { ASTIf ifNode = (ASTIf)node; sw.WriteLine("ASTIf:"); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCondition:"); PrintNode(ifNode.Condition, incident + 2); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCodeBlock:"); foreach (ASTNode codeBlock in ifNode.CodeBlock) { PrintNode(codeBlock, incident + 2); } if (ifNode.ElseCodeBlock != null) { for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tElse:"); foreach (ASTNode codeBlock in ifNode.ElseCodeBlock) { PrintNode(codeBlock, incident + 2); } } } else if (node is ASTFor) { ASTFor forNode = (ASTFor)node; sw.WriteLine("ASTFor:"); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tInit:"); PrintNode(forNode.Initialise, incident + 2); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCondition:"); PrintNode(forNode.Condition, incident + 2); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCounter:"); PrintNode(forNode.Count, incident + 2); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCodeBlock:"); foreach (ASTNode codeBlock in forNode.CodeBlock) { PrintNode(codeBlock, incident + 2); } } else if (node is ASTWhile) { ASTWhile wNode = (ASTWhile)node; sw.WriteLine("ASTWhile:"); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCondition:"); PrintNode(wNode.Condition, incident + 2); for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCodeBlock:"); foreach (ASTNode codeBlock in wNode.CodeBlock) { PrintNode(codeBlock, incident + 2); } } else if (node is ASTFunction) { ASTFunction func = (ASTFunction)node; if (node is ASTConstructor) { sw.WriteLine("ASTConstructor:"); } else { sw.WriteLine("ASTFunction: " + func.ReturnValue.ToString() + " " + func.Name); } for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tParameter:"); foreach (ASTNode n in func.Parameter) { PrintNode(n, incident + 2); } for (int i = 0; i < incident; i++) { sw.Write("\t"); } sw.WriteLine("\tCodeBlock:"); foreach (ASTNode codeBlock in func.CodeBlock) { PrintNode(codeBlock, incident + 2); } } else if (node is ASTFunctionParameter) { ASTFunctionParameter param = (ASTFunctionParameter)node; switch (param.Type) { case VMType.Object: sw.WriteLine("Object: " + param.Name); break; case VMType.String: sw.WriteLine("String: " + param.Name); break; case VMType.Number: sw.WriteLine("Number: " + param.Name); break; } } else if (node is ASTLocalVariable) { ASTLocalVariable param = (ASTLocalVariable)node; switch (param.Type) { case VMType.Object: sw.WriteLine("var Object: " + param.Name); break; case VMType.String: sw.WriteLine("var String: " + param.Name); break; case VMType.Number: sw.WriteLine("var Number: " + param.Name); break; } } else if (node is ASTReturn) { sw.WriteLine("ASTReturn:"); PrintNode(((ASTReturn)node).Return, incident + 1); } else if (node is ASTClass) { ASTClass cNode = (ASTClass)node; sw.WriteLine("ASTClass: " + cNode.Name); sw.WriteLine("\tAttributes:"); foreach (ASTNode n in cNode.Attributes) { PrintNode(n, incident + 2); } sw.WriteLine("\tConstructors:"); foreach (ASTNode n in cNode.Constructors) { PrintNode(n, incident + 2); } sw.WriteLine("\tFunctions:"); foreach (ASTNode n in cNode.Functions) { PrintNode(n, incident + 2); } } }