internal static IList <Executable> ParseBlock(Parser parser, TokenStream tokens, bool bracketsRequired, Executable owner) { List <Executable> output = new List <Executable>(); if (tokens.PopIfPresent("{")) { while (!tokens.PopIfPresent("}")) { output.Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner)); } } else { if (bracketsRequired) { tokens.PopExpected("{"); // throws with reasonable exception message. } if (tokens.PopIfPresent(";")) { return(output); } output.Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner)); } return(output); }
public Executable[] ParseInterpretedCode(string filename, string code, string libraryName) { int fileId = this.GetNextFileId(); this.RegisterFileUsed(filename, code, fileId); Token[] tokenList = Tokenizer.Tokenize(filename, code, fileId, true); TokenStream tokens = new TokenStream(tokenList); List <Executable> executables = new List <Executable>(); List <string> namespaceImportsBuilder = new List <string>(); tokens.InsertTokens(implicitCoreImport); while (tokens.HasMore && tokens.IsNext("import")) { ImportStatement importStatement = ExecutableParser.Parse(this, tokens, false, true, true, null) as ImportStatement; if (importStatement == null) { throw new Exception(); } namespaceImportsBuilder.Add(importStatement.ImportPath); Executable[] libraryEmbeddedCode = this.SystemLibraryManager.ImportLibrary(this, importStatement.FirstToken, importStatement.ImportPath); executables.AddRange(libraryEmbeddedCode); } string[] namespaceImports = namespaceImportsBuilder.ToArray(); while (tokens.HasMore) { Executable executable; try { executable = ExecutableParser.Parse(this, tokens, false, true, true, null); } catch (EofException) { throw new ParserException(null, "Unexpected EOF encountered while parsing " + filename + ". Did you forget a closing curly brace?"); } if (executable is ImportStatement) { throw new ParserException(executable.FirstToken, "All imports must occur at the beginning of the file."); } executable.NamespacePrefixSearch = namespaceImports; executable.LibraryName = libraryName; if (executable is Namespace) { ((Namespace)executable).GetFlattenedCode(executables, namespaceImports, libraryName); } else { executables.Add(executable); } } return(executables.ToArray()); }
public Executable[] ParseInterpreterCode(string filename, string contents) { TokenStream tokens = new TokenStream(Tokenizer.Tokenize(filename, contents, 0, true)); List <Executable> output = new List <Executable>(); while (tokens.HasMore) { output.Add(ExecutableParser.Parse(this, tokens, false, true, true, null)); } return(new Resolver(this, output).ResolveTranslatedCode()); }
private static Executable ParseNamespace(Parser parser, TokenStream tokens, Executable owner) { Token namespaceToken = tokens.PopExpected("namespace"); Token first = tokens.Pop(); Parser.VerifyIdentifier(first); List <Token> namespacePieces = new List <Token>() { first }; while (tokens.PopIfPresent(".")) { Token nsToken = tokens.Pop(); Parser.VerifyIdentifier(nsToken); namespacePieces.Add(nsToken); } string name = string.Join(".", namespacePieces.Select <Token, string>(t => t.Value)); parser.PushNamespacePrefix(name); Namespace namespaceInstance = new Namespace(namespaceToken, name, owner); tokens.PopExpected("{"); List <Executable> namespaceMembers = new List <Executable>(); while (!tokens.PopIfPresent("}")) { Executable executable = ExecutableParser.Parse(parser, tokens, false, false, true, namespaceInstance); if (executable is FunctionDefinition || executable is ClassDefinition || executable is EnumDefinition || executable is ConstStatement || executable is Namespace) { namespaceMembers.Add(executable); } else { throw new ParserException(executable.FirstToken, "Only function, class, and nested namespace declarations may exist as direct members of a namespace."); } } namespaceInstance.Code = namespaceMembers.ToArray(); parser.PopNamespacePrefix(); return(namespaceInstance); }
private static Executable ParseSwitch(Parser parser, TokenStream tokens, Executable owner) { Token switchToken = tokens.PopExpected("switch"); Expression explicitMax = null; Token explicitMaxToken = null; if (tokens.IsNext("{")) { explicitMaxToken = tokens.Pop(); explicitMax = ExpressionParser.Parse(tokens, owner); tokens.PopExpected("}"); } tokens.PopExpected("("); Expression condition = ExpressionParser.Parse(tokens, owner); tokens.PopExpected(")"); tokens.PopExpected("{"); List <List <Expression> > cases = new List <List <Expression> >(); List <Token> firstTokens = new List <Token>(); List <List <Executable> > code = new List <List <Executable> >(); char state = '?'; // ? - first, O - code, A - case bool defaultEncountered = false; while (!tokens.PopIfPresent("}")) { if (tokens.IsNext("case")) { if (defaultEncountered) { throw new ParserException(tokens.Peek(), "default condition in a switch statement must be the last condition."); } Token caseToken = tokens.PopExpected("case"); if (state != 'A') { cases.Add(new List <Expression>()); firstTokens.Add(caseToken); code.Add(null); state = 'A'; } cases[cases.Count - 1].Add(ExpressionParser.Parse(tokens, owner)); tokens.PopExpected(":"); } else if (tokens.IsNext("default")) { Token defaultToken = tokens.PopExpected("default"); if (state != 'A') { cases.Add(new List <Expression>()); firstTokens.Add(defaultToken); code.Add(null); state = 'A'; } cases[cases.Count - 1].Add(null); tokens.PopExpected(":"); defaultEncountered = true; } else { if (state != 'O') { cases.Add(null); firstTokens.Add(null); code.Add(new List <Executable>()); state = 'O'; } code[code.Count - 1].Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner)); } } return(new SwitchStatement(switchToken, condition, firstTokens, cases, code, explicitMax, explicitMaxToken, owner)); }
public static Executable Parse(Parser parser, TokenStream tokens, bool simpleOnly, bool semicolonPresent, bool isRoot, Executable owner) { string value = tokens.PeekValue(); if (!simpleOnly) { Token staticToken = null; Token finalToken = null; while (value == "static" || value == "final") { if (value == "static" && staticToken == null) { staticToken = tokens.Pop(); value = tokens.PeekValue(); } if (value == "final" && finalToken == null) { finalToken = tokens.Pop(); value = tokens.PeekValue(); } } if (staticToken != null || finalToken != null) { if (value != "class") { if (staticToken != null) { throw new ParserException(staticToken, "Only classes, methods, and fields may be marked as static"); } else { throw new ParserException(finalToken, "Only classes may be marked as final."); } } if (staticToken != null && finalToken != null) { throw new ParserException(staticToken, "Classes cannot be both static and final."); } } if (!isRoot && (value == "function" || value == "class")) { throw new ParserException(tokens.Peek(), (value == "function" ? "Function" : "Class") + " definition cannot be nested in another construct."); } if (parser.IsTranslateMode && value == "struct") { if (!isRoot) { throw new ParserException(tokens.Peek(), "structs cannot be nested into any other construct."); } return(ParseStruct(tokens, owner)); } if (value == "import") { Token importToken = tokens.PopExpected("import"); bool inline = parser.IsTranslateMode && tokens.PopIfPresent("inline"); if (inline) { Token fileToken = tokens.Pop(); char c = fileToken.Value[0]; if (c != '\'' && c != '"') { throw new ParserException(fileToken, "Inline imports are supposed to be strings."); } tokens.PopExpected(";"); string inlineImportFileName = fileToken.Value.Substring(1, fileToken.Value.Length - 2); string inlineImportFileContents; if (inlineImportFileName.StartsWith("LIB:")) { string[] parts = inlineImportFileName.Split(':'); string libraryName = parts[1]; string filename = FileUtil.JoinPath(parts[2].Split('/')); Library library = parser.SystemLibraryManager.GetLibraryFromKey(libraryName.ToLower()); inlineImportFileContents = library.ReadFile(filename, false); } else { inlineImportFileContents = Util.ReadInterpreterFileInternally(inlineImportFileName); } // TODO: Anti-pattern alert. Clean this up. if (inlineImportFileContents.Contains("%%%")) { Dictionary <string, string> replacements = parser.NullablePlatform.InterpreterCompiler.BuildReplacementsDictionary(); inlineImportFileContents = Constants.DoReplacements(inlineImportFileContents, replacements); } Token[] inlineTokens = Tokenizer.Tokenize(inlineImportFileName, inlineImportFileContents, 0, true); tokens.InsertTokens(inlineTokens); return(ExecutableParser.Parse(parser, tokens, simpleOnly, semicolonPresent, isRoot, owner)); // start exectuable parser anew. } if (!isRoot) { throw new ParserException(tokens.Peek(), "Imports can only be made from the root of a file and cannot be nested inside other constructs."); } List <string> importPathBuilder = new List <string>(); while (!tokens.PopIfPresent(";")) { if (importPathBuilder.Count > 0) { tokens.PopExpected("."); } Token pathToken = tokens.Pop(); Parser.VerifyIdentifier(pathToken); importPathBuilder.Add(pathToken.Value); } string importPath = string.Join(".", importPathBuilder); return(new ImportStatement(importToken, importPath)); } if (value == "enum") { if (!isRoot) { throw new ParserException(tokens.Peek(), "Enums can only be defined from the root of a file and cannot be nested inside functions/loops/etc."); } return(ParseEnumDefinition(parser, tokens, owner)); } if (value == "namespace") { if (!isRoot) { throw new ParserException(tokens.Peek(), "Namespace declarations cannot be nested in other constructs."); } } switch (value) { case "namespace": return(ParseNamespace(parser, tokens, owner)); case "function": return(ParseFunction(parser, tokens, owner)); case "class": return(ParseClassDefinition(parser, tokens, owner, staticToken, finalToken)); case "enum": return(ParseEnumDefinition(parser, tokens, owner)); case "for": return(ParseFor(parser, tokens, owner)); case "while": return(ParseWhile(parser, tokens, owner)); case "do": return(ParseDoWhile(parser, tokens, owner)); case "switch": return(ParseSwitch(parser, tokens, owner)); case "if": return(ParseIf(parser, tokens, owner)); case "try": return(ParseTry(parser, tokens, owner)); case "return": return(ParseReturn(tokens, owner)); case "break": return(ParseBreak(tokens, owner)); case "continue": return(ParseContinue(tokens, owner)); case "const": return(ParseConst(parser, tokens, owner)); case "constructor": return(ParseConstructor(parser, tokens, owner)); default: break; } } Expression expr = ExpressionParser.Parse(tokens, owner); value = tokens.PeekValue(); if (ASSIGNMENT_OPS.Contains(value)) { Token assignment = tokens.Pop(); Expression assignmentValue = ExpressionParser.Parse(tokens, owner); if (semicolonPresent) { tokens.PopExpected(";"); } return(new Assignment(expr, assignment, assignment.Value, assignmentValue, owner)); } if (semicolonPresent) { tokens.PopExpected(";"); } return(new ExpressionAsExecutable(expr, owner)); }