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); }
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); }
// 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(); } }
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 }); } }
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 }); } }
// 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); } }