// Given a bunch of raw text, load all nodes that were inside it. // You can call this multiple times to append to the collection of nodes, // but note that new nodes will replace older ones with the same name. // Returns the number of nodes that were loaded. public Program Load(string text, Library library, string fileName, Program includeProgram, bool showTokens, bool showParseTree, string onlyConsiderNode, NodeFormat format, bool experimentalMode = false) { if (format == NodeFormat.Unknown) { format = GetFormatFromFileName(fileName); } // currently experimental node can only be used on yarn.txt yarn files and single nodes if (experimentalMode && (format == NodeFormat.Text || format == NodeFormat.SingleNodeText)) { // this isn't the greatest... if (format == NodeFormat.SingleNodeText) { // it is just the body // need to add a dummy header and body delimiters StringBuilder builder = new StringBuilder(); builder.Append("title:Start\n"); builder.Append("---\n"); builder.Append(text); builder.Append("\n===\n"); text = builder.ToString(); } string inputString = preprocessor(text); ICharStream input = CharStreams.fromstring(inputString); YarnSpinnerLexer lexer = new YarnSpinnerLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); YarnSpinnerParser parser = new YarnSpinnerParser(tokens); // turning off the normal error listener and using ours parser.RemoveErrorListeners(); parser.AddErrorListener(ErrorListener.Instance); IParseTree tree = parser.dialogue(); AntlrCompiler antlrcompiler = new AntlrCompiler(library); antlrcompiler.Compile(tree); // merging in the other program if requested if (includeProgram != null) { antlrcompiler.program.Include(includeProgram); } return(antlrcompiler.program); } else { // The final parsed nodes that were in the file we were given Dictionary <string, Yarn.Parser.Node> nodes = new Dictionary <string, Parser.Node>(); // Load the raw data and get the array of node title-text pairs var nodeInfos = GetNodesFromText(text, format); int nodesLoaded = 0; foreach (NodeInfo nodeInfo in nodeInfos) { if (onlyConsiderNode != null && nodeInfo.title != onlyConsiderNode) { continue; } // Attempt to parse every node; log if we encounter any errors #if CATCH_EXCEPTIONS try { #endif if (nodes.ContainsKey(nodeInfo.title)) { throw new InvalidOperationException("Attempted to load a node called " + nodeInfo.title + ", but a node with that name has already been loaded!"); } var lexer = new Lexer(); var tokens = lexer.Tokenise(nodeInfo.title, nodeInfo.body); if (showTokens) { PrintTokenList(tokens); } var node = new Parser(tokens, library).Parse(); // If this node is tagged "rawText", then preserve its source if (string.IsNullOrEmpty(nodeInfo.tags) == false && nodeInfo.tags.Contains("rawText")) { node.source = nodeInfo.body; } node.name = nodeInfo.title; node.nodeTags = nodeInfo.tagsList; if (showParseTree) { PrintParseTree(node); } nodes[nodeInfo.title] = node; nodesLoaded++; #if CATCH_EXCEPTIONS } catch (Yarn.TokeniserException t) { // Add file information var message = string.Format("In file {0}: Error reading node {1}: {2}", fileName, nodeInfo.title, t.Message); throw new Yarn.TokeniserException(message); } catch (Yarn.ParseException p) { var message = string.Format("In file {0}: Error parsing node {1}: {2}", fileName, nodeInfo.title, p.Message); throw new Yarn.ParseException(message); } catch (InvalidOperationException e) { var message = string.Format("In file {0}: Error reading node {1}: {2}", fileName, nodeInfo.title, e.Message); throw new InvalidOperationException(message); } #endif } var compiler = new Yarn.Compiler(fileName); foreach (var node in nodes) { compiler.CompileNode(node.Value); } if (includeProgram != null) { compiler.program.Include(includeProgram); } return(compiler.program); } }