Exemple #1
0
        // Given a bunch of raw text, load all nodes that were inside it.
        public static Status CompileString(string text, string fileName, out Program program, out IDictionary <string, StringInfo> stringTable)
        {
            string      inputString = PreprocessIndentationInSource(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();

            Compiler compiler = new Compiler(fileName);

            compiler.Compile(tree);

            program     = compiler.program;
            stringTable = compiler.StringTable;

            if (compiler.containsImplicitStringTags)
            {
                return(Status.SucceededUntaggedStrings);
            }
            else
            {
                return(Status.Succeeded);
            }
        }
Exemple #2
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)
        {
            if (format == NodeFormat.Unknown)
            {
                format = GetFormatFromFileName(fileName);
            }

            // currently experimental node can only be used on yarn.txt yarn files and single nodes
            if (format != NodeFormat.Text && format != NodeFormat.SingleNodeText)
            {
                throw new InvalidDataException($"Invalid node format {format}");
            }
            // 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();
            Compiler   compiler = new Compiler(library);

            compiler.Compile(tree);

            // merging in the other program if requested
            if (includeProgram != null)
            {
                compiler.program.Include(includeProgram);
            }

            return(compiler.program);
        }
Exemple #3
0
        /// <summary>
        /// Generates a program and a derived string table from the
        /// contents of a string.
        /// </summary>
        /// <param name="text">The source code of the program.</param>
        /// <param name="fileName">The file name to assign to the compiled
        /// results.</param>
        /// <param name="program">On return, contains the compiled
        /// program.</param>
        /// <param name="stringTable">On return, contains the string table
        /// generated from the source code.</param>
        /// <returns>The status of the compilation.</returns>
        /// <exception cref="ParseException">Thrown when a parse error
        /// occurs during compilation.</exception>
        public static Status CompileString(string text, string fileName, out Program program, out IDictionary <string, StringInfo> stringTable)
        {
            ICharStream input = CharStreams.fromstring(text);

            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(ParserErrorListener.Instance);

            lexer.RemoveErrorListeners();
            lexer.AddErrorListener(LexerErrorListener.Instance);

            IParseTree tree;

            try
            {
                tree = parser.dialogue();
            } catch (ParseException e)
            {
                var tokenStringList = new List <string>();
                tokens.Reset();
                foreach (var token in tokens.GetTokens())
                {
                    tokenStringList.Add($"{token.Line}:{token.Column} {YarnSpinnerLexer.DefaultVocabulary.GetDisplayName(token.Type)} \"{token.Text}\"");
                }
                throw new ParseException($"{e.Message}\n\nTokens:\n{string.Join("\n", tokenStringList)}");
            }

            Compiler compiler = new Compiler(fileName);

            compiler.Compile(tree);

            program     = compiler.Program;
            stringTable = compiler.StringTable;

            if (compiler.containsImplicitStringTags)
            {
                return(Status.SucceededUntaggedStrings);
            }
            else
            {
                return(Status.Succeeded);
            }
        }
Exemple #4
0
        private static IParseTree ParseSyntaxTree(CompilationJob.File file)
        {
            ICharStream input = CharStreams.fromstring(file.Source);

            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(ParserErrorListener.Instance);

            lexer.RemoveErrorListeners();
            lexer.AddErrorListener(LexerErrorListener.Instance);

            IParseTree tree;

            try
            {
                tree = parser.dialogue();
            }
            catch (ParseException e)
            {
#if DEBUG
                var tokenStringList = new List <string>();
                tokens.Reset();
                foreach (var token in tokens.GetTokens())
                {
                    tokenStringList.Add($"{token.Line}:{token.Column} {YarnSpinnerLexer.DefaultVocabulary.GetDisplayName(token.Type)} \"{token.Text}\"");
                }

                throw new ParseException(e.Context, $"{e.Message}\n\nTokens:\n{string.Join("\n", tokenStringList)}", file.FileName);
#else
                throw new ParseException(e.Context, e.Message, file.FileName);
#endif // DEBUG
            }

            return(tree);
        }
Exemple #5
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 (nodeInfo.title == null)
                    {
                        throw new InvalidOperationException("Tried to load a node with no title.");
                    }
                    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);
            }
        }