Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Ink / InkLibs / InkCompiler / Compiler.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using Ink;
  4. namespace Ink
  5. {
  6. public class Compiler
  7. {
  8. public class Options
  9. {
  10. public string sourceFilename;
  11. public List<string> pluginDirectories;
  12. public bool countAllVisits;
  13. public Ink.ErrorHandler errorHandler;
  14. public Ink.IFileHandler fileHandler;
  15. }
  16. public Parsed.Story parsedStory {
  17. get {
  18. return _parsedStory;
  19. }
  20. }
  21. public Compiler (string inkSource, Options options = null)
  22. {
  23. _inputString = inkSource;
  24. _options = options ?? new Options();
  25. if( _options.pluginDirectories != null )
  26. _pluginManager = new PluginManager (_options.pluginDirectories);
  27. }
  28. public Parsed.Story Parse()
  29. {
  30. _parser = new InkParser(_inputString, _options.sourceFilename, OnParseError, _options.fileHandler);
  31. _parsedStory = _parser.Parse();
  32. return _parsedStory;
  33. }
  34. public Runtime.Story Compile ()
  35. {
  36. if( _pluginManager != null )
  37. _inputString = _pluginManager.PreParse(_inputString);
  38. Parse();
  39. if( _pluginManager != null )
  40. _parsedStory = _pluginManager.PostParse(_parsedStory);
  41. if (_parsedStory != null && !_hadParseError) {
  42. _parsedStory.countAllVisits = _options.countAllVisits;
  43. _runtimeStory = _parsedStory.ExportRuntime (_options.errorHandler);
  44. if( _pluginManager != null )
  45. _runtimeStory = _pluginManager.PostExport (_parsedStory, _runtimeStory);
  46. } else {
  47. _runtimeStory = null;
  48. }
  49. return _runtimeStory;
  50. }
  51. public class CommandLineInputResult {
  52. public bool requestsExit;
  53. public int choiceIdx = -1;
  54. public string divertedPath;
  55. public string output;
  56. }
  57. public CommandLineInputResult HandleInput (CommandLineInput inputResult)
  58. {
  59. var result = new CommandLineInputResult ();
  60. // Request for debug source line number
  61. if (inputResult.debugSource != null) {
  62. var offset = (int)inputResult.debugSource;
  63. var dm = DebugMetadataForContentAtOffset (offset);
  64. if (dm != null)
  65. result.output = "DebugSource: " + dm.ToString ();
  66. else
  67. result.output = "DebugSource: Unknown source";
  68. }
  69. // Request for runtime path lookup (to line number)
  70. else if (inputResult.debugPathLookup != null) {
  71. var pathStr = inputResult.debugPathLookup;
  72. var contentResult = _runtimeStory.ContentAtPath (new Runtime.Path (pathStr));
  73. var dm = contentResult.obj.debugMetadata;
  74. if( dm != null )
  75. result.output = "DebugSource: " + dm.ToString ();
  76. else
  77. result.output = "DebugSource: Unknown source";
  78. }
  79. // User entered some ink
  80. else if (inputResult.userImmediateModeStatement != null) {
  81. var parsedObj = inputResult.userImmediateModeStatement as Parsed.Object;
  82. return ExecuteImmediateStatement(parsedObj);
  83. } else {
  84. return null;
  85. }
  86. return result;
  87. }
  88. CommandLineInputResult ExecuteImmediateStatement(Parsed.Object parsedObj) {
  89. var result = new CommandLineInputResult ();
  90. // Variable assignment: create in Parsed.Story as well as the Runtime.Story
  91. // so that we don't get an error message during reference resolution
  92. if (parsedObj is Parsed.VariableAssignment) {
  93. var varAssign = (Parsed.VariableAssignment)parsedObj;
  94. if (varAssign.isNewTemporaryDeclaration) {
  95. _parsedStory.TryAddNewVariableDeclaration (varAssign);
  96. }
  97. }
  98. parsedObj.parent = _parsedStory;
  99. var runtimeObj = parsedObj.runtimeObject;
  100. parsedObj.ResolveReferences (_parsedStory);
  101. if (!_parsedStory.hadError) {
  102. // Divert
  103. if (parsedObj is Parsed.Divert) {
  104. var parsedDivert = parsedObj as Parsed.Divert;
  105. result.divertedPath = parsedDivert.runtimeDivert.targetPath.ToString();
  106. }
  107. // Expression or variable assignment
  108. else if (parsedObj is Parsed.Expression || parsedObj is Parsed.VariableAssignment) {
  109. var evalResult = _runtimeStory.EvaluateExpression ((Runtime.Container)runtimeObj);
  110. if (evalResult != null) {
  111. result.output = evalResult.ToString ();
  112. }
  113. }
  114. } else {
  115. _parsedStory.ResetError ();
  116. }
  117. return result;
  118. }
  119. public void RetrieveDebugSourceForLatestContent ()
  120. {
  121. foreach (var outputObj in _runtimeStory.state.outputStream) {
  122. var textContent = outputObj as Runtime.StringValue;
  123. if (textContent != null) {
  124. var range = new DebugSourceRange ();
  125. range.length = textContent.value.Length;
  126. range.debugMetadata = textContent.debugMetadata;
  127. range.text = textContent.value;
  128. _debugSourceRanges.Add (range);
  129. }
  130. }
  131. }
  132. Runtime.DebugMetadata DebugMetadataForContentAtOffset (int offset)
  133. {
  134. int currOffset = 0;
  135. Runtime.DebugMetadata lastValidMetadata = null;
  136. foreach (var range in _debugSourceRanges) {
  137. if (range.debugMetadata != null)
  138. lastValidMetadata = range.debugMetadata;
  139. if (offset >= currOffset && offset < currOffset + range.length)
  140. return lastValidMetadata;
  141. currOffset += range.length;
  142. }
  143. return null;
  144. }
  145. public struct DebugSourceRange
  146. {
  147. public int length;
  148. public Runtime.DebugMetadata debugMetadata;
  149. public string text;
  150. }
  151. // Need to wrap the error handler so that we know
  152. // when there was a critical error between parse and codegen stages
  153. void OnParseError (string message, ErrorType errorType)
  154. {
  155. if( errorType == ErrorType.Error )
  156. _hadParseError = true;
  157. if (_options.errorHandler != null)
  158. _options.errorHandler (message, errorType);
  159. else
  160. throw new System.Exception(message);
  161. }
  162. string _inputString;
  163. Options _options;
  164. InkParser _parser;
  165. Parsed.Story _parsedStory;
  166. Runtime.Story _runtimeStory;
  167. PluginManager _pluginManager;
  168. bool _hadParseError;
  169. List<DebugSourceRange> _debugSourceRanges = new List<DebugSourceRange> ();
  170. }
  171. }