Пример #1
0
        void GenerateCode(Node node, Parser.Statement parseNode, string line)
        {
            // Does this line have a "#line:LINENUM" tag? Use it
            string lineID = GetLineIDFromNodeTags(parseNode);

            var num = program.RegisterString(line, node.name, lineID, parseNode.lineNumber, true);

            Emit(node, ByteCode.RunLine, num);
        }
Пример #2
0
        public static CompileContext CompileGMLText(string input, CompileContext context, bool redoAssets = false)
        {
            context.Setup(redoAssets);                                    // Set up
            List <Lexer.Token> tokens = Lexer.LexString(context, input);  // Peform lexical analysis

            Parser.Statement block = Parser.ParseTokens(context, tokens); // Parse tokens, make syntax tree

            // Optimize and process syntax tree
            Parser.Statement optimizedBlock = null;
            if (Parser.ErrorMessages.Count == 0)
            {
                optimizedBlock = Parser.Optimize(context, block);
            }

            // Handle errors from either function
            if (Parser.ErrorMessages.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Error{0} parsing code:", Parser.ErrorMessages.Count == 1 ? "" : "s");
                sb.AppendLine();
                sb.AppendLine();
                foreach (string msg in Parser.ErrorMessages)
                {
                    sb.AppendLine(msg);
                }
                context.SetError(sb.ToString());
                return(context);
            }

            CodeWriter codeWriter = AssemblyWriter.AssembleStatement(context, optimizedBlock); // Write assembly code

            context.ResultAssembly = codeWriter.Finish();

            if (codeWriter.ErrorMessages.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Error{0} writing assembly code:", codeWriter.ErrorMessages.Count == 1 ? "" : "s");
                sb.AppendLine();
                sb.AppendLine();
                foreach (string msg in codeWriter.ErrorMessages)
                {
                    sb.AppendLine(msg);
                }
                sb.AppendLine();
                sb.Append(context.ResultAssembly);
                context.SetError(sb.ToString());
                return(context);
            }

            context.OnSuccessfulFinish();
            return(context);
        }
Пример #3
0
        // Statements
        void GenerateCode(Node node, Parser.Statement statement)
        {
            switch (statement.type)
            {
            case Parser.Statement.Type.CustomCommand:
                GenerateCode(node, statement.customCommand);
                break;

            case Parser.Statement.Type.ShortcutOptionGroup:
                GenerateCode(node, statement.shortcutOptionGroup);
                break;

            case Parser.Statement.Type.Block:

                // Blocks are just groups of statements
                foreach (var blockStatement in statement.block.statements)
                {
                    GenerateCode(node, blockStatement);
                }

                break;


            case Parser.Statement.Type.IfStatement:
                GenerateCode(node, statement.ifStatement);
                break;

            case Parser.Statement.Type.OptionStatement:
                GenerateCode(node, statement.optionStatement);
                break;

            case Parser.Statement.Type.AssignmentStatement:
                GenerateCode(node, statement.assignmentStatement);
                break;

            case Parser.Statement.Type.Line:
                GenerateCode(node, statement.line);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Пример #4
0
 private void EmitLinePart(Node node, Parser.Statement parseNode, String part, String lineID)
 {
     if (part[0] == '$')
     {
         node.instructions.Add(new Instruction
         {
             operation = ByteCode.PushVariable,
             operandA  = part,
             operandB  = null
         });
     }
     else
     {
         var num = program.RegisterString(part, node.name, lineID, parseNode.lineNumber, true);
         node.instructions.Add(new Instruction
         {
             operation = ByteCode.PushString,
             operandA  = num,
             operandB  = null
         });
     }
 }
Пример #5
0
        void GenerateCode(Node node, Parser.Statement parseNode, string line)
        {
            // Does this line have a "#line:LINENUM" tag? Use it
            string lineID = GetLineIDFromNodeTags(parseNode);

            var parts       = new List <String>();
            var currentPart = "";

            foreach (var c in line)
            {
                if (c == '$')
                {
                    if (currentPart.Length > 0)
                    {
                        parts.Add(currentPart);
                    }
                    currentPart = "$";
                }
                else
                {
                    if (currentPart.Length > 0 && currentPart[0] == '$' && ",.?!: ".Contains(new string(c, 1)))
                    {
                        parts.Add(currentPart);
                        currentPart = new string(c, 1);
                    }
                    else
                    {
                        currentPart += c;
                    }
                }
            }
            if (currentPart.Length > 0)
            {
                parts.Add(currentPart);
            }

            if (parts.Count == 1)
            {
                var num = program.RegisterString(line, node.name, lineID, parseNode.lineNumber, true);
                Emit(node, ByteCode.RunLine, num);
            }
            else
            {
                EmitLinePart(node, parseNode, parts[0], lineID);
                for (var i = 1; i < parts.Count; ++i)
                {
                    EmitLinePart(node, parseNode, parts[i], lineID);
                    node.instructions.Add(new Instruction
                    {
                        operation = ByteCode.Concat,
                        operandA  = null,
                        operandB  = null
                    });
                }

                node.instructions.Add(new Instruction
                {
                    operation = ByteCode.RunLineFromStack,
                    operandA  = null,
                    operandB  = null
                });
            }
        }
Пример #6
0
        // Run a single statement.
        private IEnumerable <Dialogue.RunnerResult> RunStatement(Parser.Statement statement)
        {
            switch (statement.type)
            {
            case Parser.Statement.Type.Block:
                // Blocks just contain statements, so run them!
                foreach (var command in RunStatements(statement.block.statements))
                {
                    yield return(command);
                }
                break;

            case Parser.Statement.Type.Line:
                // Lines get forwarded to the client for display
                yield return(new Dialogue.LineResult(statement.line));

                break;

            case Parser.Statement.Type.IfStatement:

                // Evaluate each clause in the statement, and run its statements if appropriate
                foreach (var clause in statement.ifStatement.clauses)
                {
                    // if this clause's expression doesn't evaluate to 0, run it; alternatively,
                    // if this clause has no expression (ie it's the 'else' clause) then also run it
                    if (clause.expression == null || EvaluateExpression(clause.expression).AsBool != false)
                    {
                        foreach (var command in  RunStatements(clause.statements))
                        {
                            yield return(command);
                        }
                        // don't continue on to the other clauses
                        break;
                    }
                }
                break;

            case Parser.Statement.Type.OptionStatement:
                // If we encounter an option, record it so that we can present it later
                currentOptions.Add(statement.optionStatement);
                break;

            case Parser.Statement.Type.AssignmentStatement:
                // Evaluate the expression and assign it to a variable
                RunAssignmentStatement(statement.assignmentStatement);
                break;

            case Parser.Statement.Type.ShortcutOptionGroup:
                // Evaluate and present the options, then run the stuff that came after the options
                foreach (var command in RunShortcutOptionGroup(statement.shortcutOptionGroup))
                {
                    yield return(command);
                }
                break;

            case Parser.Statement.Type.CustomCommand:
                // Deal with a custom command - it's either an expression or a client command
                // If it's an expression, evaluate it
                // If it's a client command, yield it to the client

                switch (statement.customCommand.type)
                {
                case Parser.CustomCommand.Type.Expression:
                    EvaluateExpression(statement.customCommand.expression);
                    break;

                case Parser.CustomCommand.Type.ClientCommand:
                    yield return(new Dialogue.CommandResult(statement.customCommand.clientCommand));

                    break;
                }

                break;

            default:
                // Just in case we added a new type of statement and didn't implement it here
                throw new NotImplementedException("YarnRunner: Unimplemented statement type " + statement.type);
            }
        }