Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Ink / InkLibs / InkCompiler / InkParser / InkParser_Statements.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Ink.Parsed;
  5. namespace Ink
  6. {
  7. public partial class InkParser
  8. {
  9. protected enum StatementLevel
  10. {
  11. InnerBlock,
  12. Stitch,
  13. Knot,
  14. Top
  15. }
  16. protected List<Parsed.Object> StatementsAtLevel(StatementLevel level)
  17. {
  18. // Check for error: Should not be allowed gather dashes within an inner block
  19. if (level == StatementLevel.InnerBlock) {
  20. object badGatherDashCount = Parse(GatherDashes);
  21. if (badGatherDashCount != null) {
  22. Error ("You can't use a gather (the dashes) within the { curly braces } context. For multi-line sequences and conditions, you should only use one dash.");
  23. }
  24. }
  25. return Interleave<Parsed.Object>(
  26. Optional (MultilineWhitespace),
  27. () => StatementAtLevel (level),
  28. untilTerminator: () => StatementsBreakForLevel(level));
  29. }
  30. protected object StatementAtLevel(StatementLevel level)
  31. {
  32. ParseRule[] rulesAtLevel = _statementRulesAtLevel[(int)level];
  33. var statement = OneOf (rulesAtLevel);
  34. // For some statements, allow them to parse, but create errors, since
  35. // writers may think they can use the statement, so it's useful to have
  36. // the error message.
  37. if (level == StatementLevel.Top) {
  38. if( statement is Return )
  39. Error ("should not have return statement outside of a knot");
  40. }
  41. return statement;
  42. }
  43. protected object StatementsBreakForLevel(StatementLevel level)
  44. {
  45. Whitespace ();
  46. ParseRule[] breakRules = _statementBreakRulesAtLevel[(int)level];
  47. var breakRuleResult = OneOf (breakRules);
  48. if (breakRuleResult == null)
  49. return null;
  50. return breakRuleResult;
  51. }
  52. void GenerateStatementLevelRules()
  53. {
  54. var levels = Enum.GetValues (typeof(StatementLevel)).Cast<StatementLevel> ().ToList();
  55. _statementRulesAtLevel = new ParseRule[levels.Count][];
  56. _statementBreakRulesAtLevel = new ParseRule[levels.Count][];
  57. foreach (var level in levels) {
  58. List<ParseRule> rulesAtLevel = new List<ParseRule> ();
  59. List<ParseRule> breakingRules = new List<ParseRule> ();
  60. // Diverts can go anywhere
  61. rulesAtLevel.Add(Line(MultiDivert));
  62. // Knots can only be parsed at Top/Global scope
  63. if (level >= StatementLevel.Top)
  64. rulesAtLevel.Add (KnotDefinition);
  65. rulesAtLevel.Add(Line(Choice));
  66. rulesAtLevel.Add(Line(AuthorWarning));
  67. // Gather lines would be confused with multi-line block separators, like
  68. // within a multi-line if statement
  69. if (level > StatementLevel.InnerBlock) {
  70. rulesAtLevel.Add (Gather);
  71. }
  72. // Stitches (and gathers) can (currently) only go in Knots and top level
  73. if (level >= StatementLevel.Knot) {
  74. rulesAtLevel.Add (StitchDefinition);
  75. }
  76. // Global variable declarations can go anywhere
  77. rulesAtLevel.Add(Line(ListDeclaration));
  78. rulesAtLevel.Add(Line(VariableDeclaration));
  79. rulesAtLevel.Add(Line(ConstDeclaration));
  80. rulesAtLevel.Add(Line(ExternalDeclaration));
  81. // Global include can go anywhere
  82. rulesAtLevel.Add(Line(IncludeStatement));
  83. // Normal logic / text can go anywhere
  84. rulesAtLevel.Add(LogicLine);
  85. rulesAtLevel.Add(LineOfMixedTextAndLogic);
  86. // --------
  87. // Breaking rules
  88. // Break current knot with a new knot
  89. if (level <= StatementLevel.Knot) {
  90. breakingRules.Add (KnotDeclaration);
  91. }
  92. // Break current stitch with a new stitch
  93. if (level <= StatementLevel.Stitch) {
  94. breakingRules.Add (StitchDeclaration);
  95. }
  96. // Breaking an inner block (like a multi-line condition statement)
  97. if (level <= StatementLevel.InnerBlock) {
  98. breakingRules.Add (ParseDashNotArrow);
  99. breakingRules.Add (String ("}"));
  100. }
  101. _statementRulesAtLevel [(int)level] = rulesAtLevel.ToArray ();
  102. _statementBreakRulesAtLevel [(int)level] = breakingRules.ToArray ();
  103. }
  104. }
  105. protected object SkipToNextLine()
  106. {
  107. ParseUntilCharactersFromString ("\n\r");
  108. ParseNewline ();
  109. return ParseSuccess;
  110. }
  111. // Modifier to turn a rule into one that expects a newline on the end.
  112. // e.g. anywhere you can use "MixedTextAndLogic" as a rule, you can use
  113. // "Line(MixedTextAndLogic)" to specify that it expects a newline afterwards.
  114. protected ParseRule Line(ParseRule inlineRule)
  115. {
  116. return () => {
  117. object result = ParseObject(inlineRule);
  118. if (result == null) {
  119. return null;
  120. }
  121. Expect(EndOfLine, "end of line", recoveryRule: SkipToNextLine);
  122. return result;
  123. };
  124. }
  125. ParseRule[][] _statementRulesAtLevel;
  126. ParseRule[][] _statementBreakRulesAtLevel;
  127. }
  128. }