Пример #1
0
        // 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);
            }
        }