Parser.cs 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2015-2017 Secret Lab Pty. Ltd. and Yarn Spinner contributors.
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in all
  11. copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18. SOFTWARE.
  19. */
  20. using System;
  21. using System.Collections;
  22. using System.Collections.Generic;
  23. using System.Runtime.Serialization;
  24. using System.Text;
  25. namespace Yarn {
  26. // Magic abstract syntax tree producer - feed it tokens, and it gives you
  27. // a tree representation! Or an error!
  28. internal class Parser {
  29. // Indents the 'input' string 'indentLevel' times
  30. private static string Tab(int indentLevel, string input, bool newLine = true) {
  31. var sb = new StringBuilder();
  32. for (int i = 0; i < indentLevel; i++) {
  33. sb.Append ("| ");
  34. }
  35. sb.Append (input);
  36. if (newLine)
  37. sb.Append ("\n");
  38. return sb.ToString ();
  39. }
  40. #region Parse Nodes
  41. // Base class for nodes in th parse tree
  42. internal abstract class ParseNode {
  43. internal ParseNode parent;
  44. // The line that this parse node begins on.
  45. internal int lineNumber;
  46. // ParseNodes do their parsing by consuming tokens from the Parser.
  47. // You parse tokens into a ParseNode by using its constructor.
  48. internal ParseNode(ParseNode parent, Parser p) {
  49. this.parent = parent;
  50. if (p.tokens.Count > 0)
  51. this.lineNumber = p.tokens.Peek().lineNumber;
  52. else
  53. this.lineNumber = -1;
  54. }
  55. // Recursively prints the ParseNode and all of its child ParseNodes.
  56. internal abstract string PrintTree (int indentLevel);
  57. internal string[] tags = {};
  58. public string TagsToString(int indentLevel)
  59. {
  60. if (tags.Length > 0) {
  61. var s = new StringBuilder ();
  62. s.Append (Tab (indentLevel + 1, "Tags:"));
  63. foreach (var tag in this.tags) {
  64. s.Append(Tab (indentLevel + 2, "#" + tag));
  65. }
  66. return s.ToString ();
  67. } else {
  68. return "";
  69. }
  70. }
  71. public override string ToString ()
  72. {
  73. return this.GetType ().Name;
  74. }
  75. // The closest parent to this ParseNode that is a Node.
  76. internal Node NodeParent() {
  77. var node = this;
  78. do {
  79. if (node is Node) {
  80. return node as Node;
  81. }
  82. node = node.parent;
  83. } while (node
  84. != null);
  85. return null;
  86. }
  87. }
  88. // The top-level unit of parsing.
  89. // Node = (Statement)* EndOfInput
  90. internal class Node : ParseNode {
  91. internal string name { get; set;}
  92. internal string source { get; set; }
  93. // defined in the Yarn editor
  94. internal List<string> nodeTags { get; set; }
  95. // Read-only internal accessor for statements
  96. internal IEnumerable<Statement> statements { get { return _statements; }}
  97. // The statements in this node
  98. List<Statement> _statements = new List<Statement> ();
  99. internal Node(string name, ParseNode parent, Parser p) : base(parent, p) {
  100. this.name = name;
  101. // Consume statements until we run out of input or we hit a dedent
  102. while (p.tokens.Count > 0 && p.NextSymbolIs(TokenType.Dedent,TokenType.EndOfInput) == false) {
  103. _statements.Add(new Statement(this, p));
  104. }
  105. }
  106. // Print the statements we have
  107. internal override string PrintTree (int indentLevel)
  108. {
  109. var sb = new StringBuilder ();
  110. sb.Append (Tab (indentLevel, "Node "+name+" {"));
  111. foreach (var statement in _statements) {
  112. sb.Append( statement.PrintTree (indentLevel + 1));
  113. }
  114. sb.Append (Tab (indentLevel, "}"));
  115. return sb.ToString();
  116. }
  117. }
  118. // Statements are the items of execution in nodes.
  119. // Statement = Block
  120. // Statement = IfStatement
  121. // Statement = OptionStatement
  122. // Statement = ShortcutOptionGroup
  123. // Statement = CustomCommand
  124. // Statement = AssignmentStatement
  125. // Statement = <Text>
  126. internal class Statement : ParseNode {
  127. internal enum Type {
  128. CustomCommand,
  129. ShortcutOptionGroup,
  130. Block,
  131. IfStatement,
  132. OptionStatement,
  133. AssignmentStatement,
  134. Line
  135. }
  136. internal Statement.Type type { get; private set; }
  137. // The possible types of statements we can have
  138. internal Block block { get; private set;}
  139. internal IfStatement ifStatement {get; private set;}
  140. internal OptionStatement optionStatement {get; private set;}
  141. internal AssignmentStatement assignmentStatement {get; private set;}
  142. internal CustomCommand customCommand {get;private set;}
  143. internal string line {get; private set;}
  144. internal ShortcutOptionGroup shortcutOptionGroup { get; private set; }
  145. internal Statement(ParseNode parent, Parser p) : base(parent, p) {
  146. if (Block.CanParse(p)) {
  147. type = Type.Block;
  148. block = new Block(this, p);
  149. } else if (IfStatement.CanParse(p)) {
  150. type = Type.IfStatement;
  151. ifStatement = new IfStatement(this, p);
  152. } else if (OptionStatement.CanParse(p)) {
  153. type = Type.OptionStatement;
  154. optionStatement = new OptionStatement(this, p);
  155. } else if (AssignmentStatement.CanParse(p)) {
  156. type = Type.AssignmentStatement;
  157. assignmentStatement = new AssignmentStatement(this, p);
  158. } else if (ShortcutOptionGroup.CanParse(p)) {
  159. type = Type.ShortcutOptionGroup;
  160. shortcutOptionGroup = new ShortcutOptionGroup(this, p);
  161. } else if (CustomCommand.CanParse(p)) {
  162. type = Type.CustomCommand;
  163. customCommand = new CustomCommand(this, p);
  164. } else if (p.NextSymbolIs(TokenType.Text)) {
  165. line = p.ExpectSymbol(TokenType.Text).value as string;
  166. type = Type.Line;
  167. } else {
  168. throw ParseException.Make(p.tokens.Peek(), "Expected a statement here but got " + p.tokens.Peek().ToString() +" instead (was there an unbalanced if statement earlier?)");
  169. }
  170. // Parse the optional tags that follow this statement
  171. var tags = new List<string>();
  172. while (p.NextSymbolIs(TokenType.TagMarker)) {
  173. p.ExpectSymbol(TokenType.TagMarker);
  174. var tag = p.ExpectSymbol(TokenType.Identifier).value;
  175. tags.Add(tag);
  176. }
  177. if (tags.Count > 0)
  178. this.tags = tags.ToArray();
  179. }
  180. internal override string PrintTree (int indentLevel)
  181. {
  182. StringBuilder s = new StringBuilder ();
  183. switch (type) {
  184. case Type.Block:
  185. s.Append(block.PrintTree (indentLevel));
  186. break;
  187. case Type.IfStatement:
  188. s.Append (ifStatement.PrintTree (indentLevel));
  189. break;
  190. case Type.OptionStatement:
  191. s.Append (optionStatement.PrintTree (indentLevel));
  192. break;
  193. case Type.AssignmentStatement:
  194. s.Append (assignmentStatement.PrintTree (indentLevel));
  195. break;
  196. case Type.ShortcutOptionGroup:
  197. s.Append (shortcutOptionGroup.PrintTree (indentLevel));
  198. break;
  199. case Type.CustomCommand:
  200. s.Append (customCommand.PrintTree (indentLevel));
  201. break;
  202. case Type.Line:
  203. s.Append (Tab (indentLevel, "Line: " + line));
  204. break;
  205. default:
  206. throw new ArgumentNullException ();
  207. }
  208. s.Append (TagsToString (indentLevel));
  209. return s.ToString ();
  210. }
  211. }
  212. // Custom commands are meant to be interpreted by whatever
  213. // system that owns this dialogue sytem. eg <<stand>>
  214. // CustomCommand = BeginCommand <ANY>* EndCommand
  215. internal class CustomCommand : ParseNode {
  216. internal enum Type {
  217. Expression,
  218. ClientCommand
  219. }
  220. internal Type type;
  221. internal Expression expression {get; private set;}
  222. internal string clientCommand { get; private set;}
  223. internal static bool CanParse (Parser p)
  224. {
  225. return p.NextSymbolsAre (TokenType.BeginCommand, TokenType.Text) ||
  226. p.NextSymbolsAre (TokenType.BeginCommand, TokenType.Identifier);
  227. }
  228. internal CustomCommand(ParseNode parent, Parser p) : base(parent, p) {
  229. p.ExpectSymbol(TokenType.BeginCommand);
  230. // Custom commands can have ANY token in them. Read them all until we hit the
  231. // end command token.
  232. var commandTokens = new List<Token>();
  233. do {
  234. commandTokens.Add(p.ExpectSymbol());
  235. } while (p.NextSymbolIs(TokenType.EndCommand) == false);
  236. p.ExpectSymbol(TokenType.EndCommand);
  237. // If the first token is an identifier and the second is
  238. // a left paren, it may be a function call expression;
  239. // evaluate it as such
  240. if (commandTokens.Count > 1 &&
  241. commandTokens[0].type == TokenType.Identifier &&
  242. commandTokens[1].type == TokenType.LeftParen) {
  243. var parser = new Parser(commandTokens, p.library);
  244. var expression = Expression.Parse(this, parser);
  245. type = Type.Expression;
  246. this.expression = expression;
  247. } else {
  248. // Otherwise, evaluate it as a command
  249. type = Type.ClientCommand;
  250. this.clientCommand = commandTokens[0].value;
  251. }
  252. }
  253. internal override string PrintTree (int indentLevel)
  254. {
  255. switch (type) {
  256. case Type.Expression:
  257. return Tab (indentLevel, "Expression: ") + expression.PrintTree (indentLevel + 1);
  258. case Type.ClientCommand:
  259. return Tab (indentLevel, "Command: " + clientCommand);
  260. }
  261. return "";
  262. }
  263. }
  264. // Shortcut option groups are groups of shortcut options,
  265. // followed by the node that they rejoin.
  266. // ShortcutOptionGroup = ShortcutOption+ Node
  267. internal class ShortcutOptionGroup : ParseNode {
  268. internal static bool CanParse (Parser p)
  269. {
  270. return p.NextSymbolIs (TokenType.ShortcutOption);
  271. }
  272. internal IEnumerable<ShortcutOption> options { get { return _options; }}
  273. // The options in this group
  274. private List<ShortcutOption> _options = new List<ShortcutOption>();
  275. internal ShortcutOptionGroup(ParseNode parent, Parser p) : base(parent, p) {
  276. // keep parsing options until we can't, but expect at least one (otherwise it's
  277. // not actually a list of options)
  278. int shortcutIndex = 1; // give each option a number so it can name itself
  279. do {
  280. _options.Add(new ShortcutOption(shortcutIndex++, this, p));
  281. } while (p.NextSymbolIs(TokenType.ShortcutOption));
  282. }
  283. internal override string PrintTree (int indentLevel)
  284. {
  285. var sb = new StringBuilder ();
  286. sb.Append (Tab (indentLevel, "Shortcut option group {"));
  287. foreach (var option in options) {
  288. sb.Append (option.PrintTree (indentLevel + 1));
  289. }
  290. sb.Append (Tab (indentLevel, "}"));
  291. return sb.ToString ();
  292. }
  293. }
  294. // Shortcut options are a convenient way to define new options.
  295. // ShortcutOption = -> <text> [BeginCommand If Expression EndCommand] [Block]
  296. internal class ShortcutOption : ParseNode {
  297. internal string label { get; private set;}
  298. internal Expression condition { get; private set;}
  299. internal Node optionNode { get; private set;}
  300. internal ShortcutOption(int optionIndex, ParseNode parent, Parser p) : base(parent, p) {
  301. p.ExpectSymbol(TokenType.ShortcutOption);
  302. label = p.ExpectSymbol(TokenType.Text).value as string;
  303. // Parse the conditional ("<<if $foo>>") if it's there
  304. var tags = new List<string>();
  305. while (
  306. p.NextSymbolsAre(TokenType.BeginCommand, TokenType.If) ||
  307. p.NextSymbolIs(TokenType.TagMarker)) {
  308. if (p.NextSymbolsAre(TokenType.BeginCommand, TokenType.If)) {
  309. p.ExpectSymbol(TokenType.BeginCommand);
  310. p.ExpectSymbol(TokenType.If);
  311. condition = Expression.Parse(this, p);
  312. p.ExpectSymbol(TokenType.EndCommand);
  313. } else if (p.NextSymbolIs(TokenType.TagMarker)) {
  314. p.ExpectSymbol(TokenType.TagMarker);
  315. var tag = p.ExpectSymbol(TokenType.Identifier).value;
  316. tags.Add(tag);
  317. }
  318. }
  319. this.tags = tags.ToArray();
  320. // Parse the statements belonging to this option if it has any
  321. if (p.NextSymbolIs(TokenType.Indent)) {
  322. p.ExpectSymbol(TokenType.Indent);
  323. optionNode = new Node(NodeParent().name + "." + optionIndex, this, p);
  324. p.ExpectSymbol(TokenType.Dedent);
  325. }
  326. }
  327. internal override string PrintTree (int indentLevel)
  328. {
  329. var sb = new StringBuilder ();
  330. sb.Append (Tab (indentLevel, "Option \"" +label + "\""));
  331. if (condition != null) {
  332. sb.Append (Tab (indentLevel + 1, "(when:"));
  333. sb.Append (condition.PrintTree(indentLevel+2));
  334. sb.Append (Tab (indentLevel + 1, "),"));
  335. }
  336. if (optionNode != null) {
  337. sb.Append (Tab (indentLevel, "{"));
  338. sb.Append (optionNode.PrintTree (indentLevel + 1));
  339. sb.Append (Tab (indentLevel, "}"));
  340. }
  341. sb.Append (TagsToString (indentLevel));
  342. return sb.ToString ();
  343. }
  344. }
  345. // Blocks are indented groups of statements
  346. // Block = Indent Statement* Dedent
  347. internal class Block : ParseNode {
  348. internal static bool CanParse (Parser p)
  349. {
  350. return p.NextSymbolIs (TokenType.Indent);
  351. }
  352. internal IEnumerable<Statement> statements { get { return _statements; }}
  353. List<Statement> _statements = new List<Statement> ();
  354. internal Block(ParseNode parent, Parser p) : base(parent, p) {
  355. // Read the indent token
  356. p.ExpectSymbol(TokenType.Indent);
  357. // Keep reading statements until we hit a dedent
  358. while (p.NextSymbolIs(TokenType.Dedent) == false) {
  359. // fun fact! because Blocks are a type of Statement,
  360. // we get nested block parsing for free! \:D/
  361. _statements.Add(new Statement(this, p));
  362. }
  363. // Tidy up by reading the dedent
  364. p.ExpectSymbol(TokenType.Dedent);
  365. }
  366. internal override string PrintTree (int indentLevel)
  367. {
  368. var sb = new StringBuilder ();
  369. sb.Append (Tab(indentLevel, "Block {"));
  370. foreach (var statement in _statements) {
  371. sb.Append (statement.PrintTree (indentLevel + 1));
  372. }
  373. sb.Append (Tab(indentLevel, "}"));
  374. return sb.ToString ();
  375. }
  376. }
  377. // Options are links to other nodes
  378. // OptionStatement = OptionStart <Text> OptionEnd
  379. // OptionStatement = OptionStart <Text> OptionDelimit <Text>|<Identifier> OptionEnd
  380. internal class OptionStatement : ParseNode {
  381. internal static bool CanParse (Parser p)
  382. {
  383. return p.NextSymbolIs (TokenType.OptionStart);
  384. }
  385. internal string destination { get; private set;}
  386. internal string label { get; private set;}
  387. internal OptionStatement(ParseNode parent, Parser p) : base(parent, p) {
  388. // The meaning of the string(s) we have changes
  389. // depending on whether we have one or two, so
  390. // keep them both and decide their meaning once
  391. // we know more
  392. string firstString;
  393. string secondString;
  394. // Parse "[[LABEL"
  395. p.ExpectSymbol(TokenType.OptionStart);
  396. firstString = p.ExpectSymbol(TokenType.Text).value as String;
  397. // If there's a | in there, get the string that comes after it
  398. if (p.NextSymbolIs(TokenType.OptionDelimit)) {
  399. p.ExpectSymbol(TokenType.OptionDelimit);
  400. secondString = p.ExpectSymbol(TokenType.Text, TokenType.Identifier).value as String;
  401. // Two strings mean that the first is the label, and the second
  402. // is the name of the node that we should head to if this option
  403. // is selected
  404. label = firstString;
  405. destination = secondString;
  406. } else {
  407. // One string means we don't have a label
  408. label = null;
  409. destination = firstString;
  410. }
  411. // Parse the closing ]]
  412. p.ExpectSymbol(TokenType.OptionEnd);
  413. }
  414. internal override string PrintTree (int indentLevel)
  415. {
  416. if (label != null) {
  417. return Tab (indentLevel, string.Format ("Option: \"{0}\" -> {1}", label, destination));
  418. } else {
  419. return Tab (indentLevel, string.Format ("Option: -> {0}", destination));
  420. }
  421. }
  422. }
  423. // If statements are the usual if-else-elseif-endif business.
  424. // If = BeginCommand If Expression EndCommand Statement* BeginCommand EndIf EndCommand
  425. // TODO: elseif
  426. internal class IfStatement : ParseNode {
  427. internal static bool CanParse (Parser p)
  428. {
  429. return p.NextSymbolsAre (TokenType.BeginCommand, TokenType.If);
  430. }
  431. // Clauses are collections of statements with an
  432. // optional conditional that determines whether they're run
  433. // or not. The condition is used by the If and ElseIf parts of
  434. // an if statement, and not used by the Else statement.
  435. internal struct Clause {
  436. internal Expression expression;
  437. internal IEnumerable<Statement> statements;
  438. internal string PrintTree(int indentLevel) {
  439. var sb = new StringBuilder ();
  440. if (expression != null)
  441. sb.Append (expression.PrintTree (indentLevel));
  442. sb.Append (Tab (indentLevel, "{"));
  443. foreach (var statement in statements) {
  444. sb.Append (statement.PrintTree (indentLevel + 1));
  445. }
  446. sb.Append (Tab (indentLevel, "}"));
  447. return sb.ToString ();
  448. }
  449. }
  450. internal List<Clause> clauses = new List<Clause>();
  451. internal IfStatement(ParseNode parent, Parser p) : base(parent, p) {
  452. // All if statements begin with "<<if EXPRESSION>>", so parse that
  453. Clause primaryClause = new Clause();
  454. p.ExpectSymbol(TokenType.BeginCommand);
  455. p.ExpectSymbol(TokenType.If);
  456. primaryClause.expression = Expression.Parse(this, p);
  457. p.ExpectSymbol(TokenType.EndCommand);
  458. // Read the statements for this clause until we hit an <<endif or <<else
  459. // (which could be an "<<else>>" or an "<<else if"
  460. var statements = new List<Statement>();
  461. while (p.NextSymbolsAre(TokenType.BeginCommand, TokenType.EndIf) == false &&
  462. p.NextSymbolsAre(TokenType.BeginCommand, TokenType.Else) == false &&
  463. p.NextSymbolsAre(TokenType.BeginCommand, TokenType.ElseIf) == false) {
  464. statements.Add(new Statement(this, p));
  465. // Ignore any dedents
  466. while (p.NextSymbolIs(TokenType.Dedent)) {
  467. p.ExpectSymbol(TokenType.Dedent);
  468. }
  469. }
  470. primaryClause.statements = statements;
  471. clauses.Add(primaryClause);
  472. // Handle as many <<elseif clauses as we find
  473. while (p.NextSymbolsAre(TokenType.BeginCommand, TokenType.ElseIf)) {
  474. var elseIfClause = new Clause();
  475. // Parse the syntax for this clause's condition
  476. p.ExpectSymbol(TokenType.BeginCommand);
  477. p.ExpectSymbol(TokenType.ElseIf);
  478. elseIfClause.expression = Expression.Parse(this, p);
  479. p.ExpectSymbol(TokenType.EndCommand);
  480. // Read statements until we hit an <<endif, <<else or another <<elseif
  481. var clauseStatements = new List<Statement>();
  482. while (p.NextSymbolsAre(TokenType.BeginCommand, TokenType.EndIf) == false &&
  483. p.NextSymbolsAre(TokenType.BeginCommand, TokenType.Else) == false &&
  484. p.NextSymbolsAre(TokenType.BeginCommand, TokenType.ElseIf) == false) {
  485. clauseStatements.Add(new Statement(this, p));
  486. // Ignore any dedents
  487. while (p.NextSymbolIs(TokenType.Dedent)) {
  488. p.ExpectSymbol(TokenType.Dedent);
  489. }
  490. }
  491. elseIfClause.statements = clauseStatements;
  492. clauses.Add(elseIfClause);
  493. }
  494. // Handle <<else>> if we have it
  495. if (p.NextSymbolsAre(TokenType.BeginCommand, TokenType.Else, TokenType.EndCommand)) {
  496. // parse the syntax (no expression this time, just "<<else>>"
  497. p.ExpectSymbol(TokenType.BeginCommand);
  498. p.ExpectSymbol(TokenType.Else);
  499. p.ExpectSymbol(TokenType.EndCommand);
  500. // and parse statements until we hit "<<endif"
  501. var elseClause = new Clause();
  502. var clauseStatements = new List<Statement>();
  503. while (p.NextSymbolsAre(TokenType.BeginCommand, TokenType.EndIf) == false) {
  504. clauseStatements.Add(new Statement(this, p));
  505. }
  506. elseClause.statements = clauseStatements;
  507. this.clauses.Add(elseClause);
  508. // Ignore any dedents
  509. while (p.NextSymbolIs(TokenType.Dedent)) {
  510. p.ExpectSymbol(TokenType.Dedent);
  511. }
  512. }
  513. // Finish up by reading the <<endif>>
  514. p.ExpectSymbol(TokenType.BeginCommand);
  515. p.ExpectSymbol(TokenType.EndIf);
  516. p.ExpectSymbol(TokenType.EndCommand);
  517. }
  518. internal override string PrintTree (int indentLevel)
  519. {
  520. var sb = new StringBuilder ();
  521. var first = true;
  522. foreach (var clause in clauses) {
  523. if (first) {
  524. sb.Append (Tab (indentLevel, "If:"));
  525. first = false;
  526. } else if (clause.expression != null) {
  527. sb.Append (Tab (indentLevel, "Else If:"));
  528. } else {
  529. sb.Append (Tab (indentLevel, "Else:"));
  530. }
  531. sb.Append (clause.PrintTree (indentLevel + 1));
  532. }
  533. return sb.ToString ();
  534. }
  535. }
  536. // A value, which forms part of an expression.
  537. public class ValueNode : ParseNode {
  538. public Value value { get; private set;}
  539. private void UseToken(Token t) {
  540. // Store the value depending on token's type
  541. switch (t.type) {
  542. case TokenType.Number:
  543. value = new Value (float.Parse (t.value as String));
  544. break;
  545. case TokenType.String:
  546. value = new Value (t.value as String);
  547. break;
  548. case TokenType.False:
  549. value = new Value (false);
  550. break;
  551. case TokenType.True:
  552. value = new Value (true);
  553. break;
  554. case TokenType.Variable:
  555. value = new Value(t.value);
  556. value.type = Value.Type.Variable;
  557. break;
  558. case TokenType.Null:
  559. value = Value.NULL;
  560. break;
  561. default:
  562. throw ParseException.Make (t, "Invalid token type " + t.ToString ());
  563. }
  564. }
  565. // Use a provided token
  566. internal ValueNode(ParseNode parent, Token t, Parser p) : base (parent, p) {
  567. UseToken(t);
  568. }
  569. // Read a number or a variable name from the parser
  570. internal ValueNode(ParseNode parent, Parser p) : base(parent, p) {
  571. Token t = p.ExpectSymbol(TokenType.Number, TokenType.Variable, TokenType.String);
  572. UseToken(t);
  573. }
  574. internal override string PrintTree(int indentLevel)
  575. {
  576. if (value.type == Value.Type.String)
  577. return Tab(indentLevel, String.Format("\"{0}\"", value.AsString));
  578. return Tab(indentLevel, value.AsString);
  579. }
  580. }
  581. // Expressions are things like "1 + 2 * 5 / 2 - 1"
  582. // Expression = Expression Operator Expression
  583. // Expression = Identifier ( Expression [, Expression]* )
  584. // Expression = Value
  585. internal class Expression : ParseNode {
  586. internal enum Type {
  587. Value,
  588. FunctionCall
  589. }
  590. internal Type type;
  591. internal ValueNode value;
  592. // - or -
  593. internal FunctionInfo function;
  594. internal List<Expression> parameters;
  595. internal Expression(ParseNode parent, ValueNode value, Parser p) : base(parent, p) {
  596. this.type = Type.Value;
  597. this.value = value;
  598. }
  599. internal Expression(ParseNode parent, FunctionInfo function, List<Expression> parameters, Parser p) : base(parent, p) {
  600. type = Type.FunctionCall;
  601. this.function = function;
  602. this.parameters = parameters;
  603. }
  604. internal static Expression Parse(ParseNode parent, Parser p) {
  605. // Applies Djikstra's "shunting-yard" algorithm to convert the
  606. // stream of infix expressions into postfix notation; we then
  607. // build a tree of expressions from the result
  608. // https://en.wikipedia.org/wiki/Shunting-yard_algorithm
  609. Queue<Token> _expressionRPN = new Queue<Token> ();
  610. var operatorStack = new Stack<Token>();
  611. // used for keeping count of parameters for each function
  612. var functionStack = new Stack<Token> ();
  613. var allValidTokenTypes = new List<TokenType>(Operator.OperatorTypes);
  614. allValidTokenTypes.Add(TokenType.Number);
  615. allValidTokenTypes.Add(TokenType.Variable);
  616. allValidTokenTypes.Add(TokenType.String);
  617. allValidTokenTypes.Add(TokenType.LeftParen);
  618. allValidTokenTypes.Add(TokenType.RightParen);
  619. allValidTokenTypes.Add(TokenType.Identifier);
  620. allValidTokenTypes.Add(TokenType.Comma);
  621. allValidTokenTypes.Add(TokenType.True);
  622. allValidTokenTypes.Add(TokenType.False);
  623. allValidTokenTypes.Add(TokenType.Null);
  624. Token lastToken = null;
  625. // Read all the contents of the expression
  626. while (p.tokens.Count > 0 && p.NextSymbolIs(allValidTokenTypes.ToArray())) {
  627. Token nextToken = p.ExpectSymbol(allValidTokenTypes.ToArray());
  628. if (nextToken.type == TokenType.Number ||
  629. nextToken.type == TokenType.Variable ||
  630. nextToken.type == TokenType.String ||
  631. nextToken.type == TokenType.True ||
  632. nextToken.type == TokenType.False ||
  633. nextToken.type == TokenType.Null) {
  634. // Primitive values go straight onto the output
  635. _expressionRPN.Enqueue (nextToken);
  636. } else if (nextToken.type == TokenType.Identifier) {
  637. operatorStack.Push (nextToken);
  638. functionStack.Push (nextToken);
  639. // next token must be a left paren, so process that immediately
  640. nextToken = p.ExpectSymbol (TokenType.LeftParen);
  641. // enter that sub-expression
  642. operatorStack.Push (nextToken);
  643. } else if (nextToken.type == TokenType.Comma) {
  644. // Resolve this sub-expression before moving on to the
  645. // next parameter
  646. try {
  647. // pop operators until we reach a left paren
  648. while (operatorStack.Peek().type != TokenType.LeftParen) {
  649. _expressionRPN.Enqueue(operatorStack.Pop());
  650. }
  651. } catch (InvalidOperationException) {
  652. // we reached the end of the stack prematurely
  653. // this means unbalanced parens!
  654. throw ParseException.Make(nextToken, "Error parsing expression: " +
  655. "unbalanced parentheses");
  656. }
  657. // We expect the top of the stack to now contain the left paren that
  658. // began the list of parameters
  659. if (operatorStack.Peek().type != TokenType.LeftParen) {
  660. throw ParseException.Make (operatorStack.Peek (), "Expression parser got " +
  661. "confused dealing with a function");
  662. }
  663. // The next token is not allowed to be a right-paren or a comma
  664. // (that is, you can't say "foo(2,,)")
  665. if (p.NextSymbolIs(TokenType.RightParen, TokenType.Comma)) {
  666. throw ParseException.Make (p.tokens.Peek(), "Expected expression");
  667. }
  668. // Find the closest function on the stack
  669. // and increment the number of parameters
  670. functionStack.Peek().parameterCount++;
  671. } else if (Operator.IsOperator(nextToken.type)) {
  672. // This is an operator
  673. // If this is a Minus, we need to determine if it's a
  674. // unary minus or a binary minus.
  675. // Unary minus looks like this: "-1"
  676. // Binary minus looks like this: "2 - 3"
  677. // Things get complex when we say stuff like "1 + -1".
  678. // But it's easier when we realise that a minus
  679. // is ONLY unary when the last token was a left paren,
  680. // an operator, or it's the first token.
  681. if (nextToken.type == TokenType.Minus) {
  682. if (lastToken == null ||
  683. lastToken.type == TokenType.LeftParen ||
  684. Operator.IsOperator(lastToken.type)) {
  685. // This is actually a unary minus.
  686. nextToken.type = TokenType.UnaryMinus;
  687. }
  688. }
  689. // We cannot assign values inside an expression. That is,
  690. // saying "$foo = 2" in an express does not assign $foo to 2
  691. // and then evaluate to 2. Instead, Yarn defines this
  692. // to mean "$foo == 2"
  693. if (nextToken.type == TokenType.EqualToOrAssign) {
  694. nextToken.type = TokenType.EqualTo;
  695. }
  696. // O1 = this operator
  697. // O2 = the token at the top of the stack
  698. // While O2 is an operator, and EITHER: 1. O1 is left-associative and
  699. // has precedence <= O2, or 2. O1 is right-associative and
  700. // has precedence > O2:
  701. while (ShouldApplyPrecedence(nextToken.type, operatorStack)) {
  702. var o = operatorStack.Pop();
  703. _expressionRPN.Enqueue(o);
  704. }
  705. operatorStack.Push(nextToken);
  706. } else if (nextToken.type == TokenType.LeftParen) {
  707. // Record that we have entered a paren-delimited
  708. // subexpression
  709. operatorStack.Push(nextToken);
  710. } else if (nextToken.type == TokenType.RightParen) {
  711. // We're leaving a subexpression; time to resolve the
  712. // order of operations that we saw in between the parens.
  713. try {
  714. // pop operators until we reach a left paren
  715. while (operatorStack.Peek().type != TokenType.LeftParen) {
  716. _expressionRPN.Enqueue(operatorStack.Pop());
  717. }
  718. // pop the left paren
  719. operatorStack.Pop();
  720. } catch (InvalidOperationException) {
  721. // we reached the end of the stack prematurely
  722. // this means unbalanced parens!
  723. throw ParseException.Make(nextToken, "Error parsing expression: unbalanced parentheses");
  724. }
  725. if (operatorStack.Peek().type == TokenType.Identifier) {
  726. // This whole paren-delimited subexpression is actually
  727. // a function call
  728. // If the last token was a left-paren, then this
  729. // was a function with no parameters; otherwise, we
  730. // have an additional parameter (on top of the ones we counted
  731. // while encountering commas)
  732. if (lastToken.type != TokenType.LeftParen) {
  733. functionStack.Peek ().parameterCount++;
  734. }
  735. _expressionRPN.Enqueue(operatorStack.Pop());
  736. functionStack.Pop ();
  737. }
  738. }
  739. // Record this as the last token we saw; we'll use
  740. // this to figure out if minuses are unary or not
  741. lastToken = nextToken;
  742. }
  743. // No more tokens; pop all operators onto the output queue
  744. while (operatorStack.Count > 0) {
  745. _expressionRPN.Enqueue(operatorStack.Pop());
  746. }
  747. // If the output queue is empty, then this is not an expression
  748. if (_expressionRPN.Count == 0) {
  749. throw new ParseException ("Error parsing expression: no expression found!");
  750. }
  751. // We've now got this in more easily parsed RPN form;
  752. // time to build the expression tree.
  753. Token firstToken = _expressionRPN.Peek();
  754. var evaluationStack = new Stack<Expression>();
  755. while (_expressionRPN.Count > 0) {
  756. var next = _expressionRPN.Dequeue();
  757. if (Operator.IsOperator(next.type)) {
  758. // This is an operation
  759. var info = Operator.InfoForOperator(next.type);
  760. if (evaluationStack.Count < info.arguments) {
  761. throw ParseException.Make(next, "Error parsing expression: not enough " +
  762. "arguments for operator "+next.type.ToString());
  763. }
  764. var parameters = new List<Expression> ();
  765. for (int i = 0; i < info.arguments; i++) {
  766. parameters.Add (evaluationStack.Pop ());
  767. }
  768. parameters.Reverse ();
  769. var operatorFunc = p.library.GetFunction (next.type.ToString());
  770. var expr = new Expression (parent, operatorFunc, parameters, p);
  771. evaluationStack.Push(expr);
  772. } else if (next.type == TokenType.Identifier) {
  773. // This is a function call
  774. FunctionInfo info = null;
  775. // If we have a library, use it to check if the
  776. // number of parameters provided is correct
  777. if (p.library != null) {
  778. info = p.library.GetFunction(next.value as String);
  779. // Ensure that this call has the right number of params
  780. if (info.IsParameterCountCorrect(next.parameterCount) == false) {
  781. string error = string.Format("Error parsing expression: " +
  782. "Unsupported number of parameters for function {0} (expected {1}, got {2})",
  783. next.value as String,
  784. info.paramCount,
  785. next.parameterCount
  786. );
  787. throw ParseException.Make(next, error);
  788. }
  789. } else {
  790. // Use a dummy FunctionInfo to represent info about the
  791. // fact that a function is called; note that
  792. // attempting to call this will fail
  793. info = new FunctionInfo (next.value, next.parameterCount, (Function)null);
  794. }
  795. var parameterList = new List<Expression> ();
  796. for (int i = 0; i < next.parameterCount; i++) {
  797. parameterList.Add (evaluationStack.Pop());
  798. }
  799. parameterList.Reverse ();
  800. var expr = new Expression (parent, info, parameterList, p);
  801. evaluationStack.Push (expr);
  802. } else {
  803. // This is a raw value
  804. var v = new ValueNode(parent, next, p);
  805. Expression expr = new Expression(parent, v, p);
  806. evaluationStack.Push(expr);
  807. }
  808. }
  809. // We should now have a single expression in this stack, which is the root
  810. // of the expression's tree. If we have more than one, then we have a problem.
  811. if (evaluationStack.Count != 1) {
  812. throw ParseException.Make(firstToken, "Error parsing expression " +
  813. "(stack did not reduce correctly)");
  814. }
  815. // Return it
  816. return evaluationStack.Pop ();
  817. }
  818. // Used to determine whether the shunting-yard algorithm should pop operators from
  819. // the operator stack.
  820. private static bool ShouldApplyPrecedence(TokenType o1, Stack<Token> operatorStack) {
  821. if (operatorStack.Count == 0) {
  822. return false;
  823. }
  824. if (Operator.IsOperator (o1) == false) {
  825. throw new ParseException ("Internal error parsing expression");
  826. }
  827. TokenType o2 = operatorStack.Peek ().type;
  828. if (Operator.IsOperator (o2) == false)
  829. return false;
  830. var o1Info = Operator.InfoForOperator (o1);
  831. var o2Info = Operator.InfoForOperator (o2);
  832. if (o1Info.associativity == Operator.Associativity.Left && o1Info.precedence <= o2Info.precedence) {
  833. return true;
  834. }
  835. if (o1Info.associativity == Operator.Associativity.Right && o1Info.precedence < o2Info.precedence) {
  836. return true;
  837. }
  838. return false;
  839. }
  840. internal override string PrintTree (int indentLevel)
  841. {
  842. var stringBuilder = new StringBuilder ();
  843. switch (type) {
  844. case Type.Value:
  845. return value.PrintTree (indentLevel);
  846. case Type.FunctionCall:
  847. if (parameters.Count == 0) {
  848. stringBuilder.Append(Tab(indentLevel, "Function call to " + function.name + " (no parameters)"));
  849. } else {
  850. stringBuilder.Append(Tab(indentLevel, "Function call to " + function.name + " (" +parameters.Count+" parameters) {"));
  851. foreach (var param in parameters) {
  852. stringBuilder.Append(param.PrintTree(indentLevel+1));
  853. }
  854. stringBuilder.Append(Tab(indentLevel, "}"));
  855. }
  856. return stringBuilder.ToString();
  857. }
  858. return Tab(indentLevel, "<error printing expression!>");
  859. }
  860. }
  861. // AssignmentStatements are things like <<set $foo = 1>>
  862. // AssignmentStatement = BeginCommand Set <variable> <operation> Expression EndCommand
  863. internal class AssignmentStatement : ParseNode {
  864. internal static bool CanParse (Parser p)
  865. {
  866. return p.NextSymbolsAre (TokenType.BeginCommand, TokenType.Set);
  867. }
  868. internal string destinationVariableName { get; private set; }
  869. internal Expression valueExpression { get; private set; }
  870. internal TokenType operation { get; private set; }
  871. private static TokenType[] validOperators = {
  872. TokenType.EqualToOrAssign,
  873. TokenType.AddAssign,
  874. TokenType.MinusAssign,
  875. TokenType.DivideAssign,
  876. TokenType.MultiplyAssign
  877. };
  878. internal AssignmentStatement(ParseNode parent, Parser p) : base(parent, p) {
  879. p.ExpectSymbol(TokenType.BeginCommand);
  880. p.ExpectSymbol(TokenType.Set);
  881. destinationVariableName = p.ExpectSymbol(TokenType.Variable).value as string;
  882. operation = p.ExpectSymbol(validOperators).type;
  883. valueExpression = Expression.Parse(this, p);
  884. p.ExpectSymbol(TokenType.EndCommand);
  885. }
  886. internal override string PrintTree (int indentLevel)
  887. {
  888. var sb = new StringBuilder ();
  889. sb.Append (Tab(indentLevel, "Set:"));
  890. sb.Append (Tab(indentLevel+1, destinationVariableName));
  891. sb.Append (Tab (indentLevel+1, operation.ToString()));
  892. sb.Append (valueExpression.PrintTree (indentLevel + 1));
  893. return sb.ToString ();
  894. }
  895. }
  896. // Operators are used in expressions - things like + - / * != neq
  897. internal class Operator : ParseNode {
  898. internal TokenType operatorType { get; private set; }
  899. internal enum Associativity {
  900. Left, // resolve leftmost operand first
  901. Right, // resolve rightmost operand first
  902. None // special-case (like "(", ")", ","
  903. }
  904. // Info used during expression parsing
  905. internal struct OperatorInfo {
  906. internal Associativity associativity;
  907. internal int precedence;
  908. internal int arguments;
  909. internal OperatorInfo(Associativity associativity, int precedence, int arguments) {
  910. this.associativity = associativity;
  911. this.precedence = precedence;
  912. this.arguments = arguments;
  913. }
  914. }
  915. internal static OperatorInfo InfoForOperator(TokenType op) {
  916. if (Array.IndexOf(OperatorTypes, op) == -1) {
  917. throw new ParseException (op.ToString () + " is not a valid operator");
  918. }
  919. // Determine the precendence, associativity and
  920. // number of operands that each operator has.
  921. switch (op) {
  922. case TokenType.Not:
  923. case TokenType.UnaryMinus:
  924. return new OperatorInfo (Associativity.Right, 30, 1);
  925. case TokenType.Multiply:
  926. case TokenType.Divide:
  927. case TokenType.Modulo:
  928. return new OperatorInfo(Associativity.Left, 20,2);
  929. case TokenType.Add:
  930. case TokenType.Minus:
  931. return new OperatorInfo(Associativity.Left, 15,2);
  932. case TokenType.GreaterThan:
  933. case TokenType.LessThan:
  934. case TokenType.GreaterThanOrEqualTo:
  935. case TokenType.LessThanOrEqualTo:
  936. return new OperatorInfo(Associativity.Left, 10,2);
  937. case TokenType.EqualTo:
  938. case TokenType.EqualToOrAssign:
  939. case TokenType.NotEqualTo:
  940. return new OperatorInfo(Associativity.Left, 5,2);
  941. case TokenType.And:
  942. return new OperatorInfo(Associativity.Left, 4,2);
  943. case TokenType.Or:
  944. return new OperatorInfo(Associativity.Left, 3,2);
  945. case TokenType.Xor:
  946. return new OperatorInfo(Associativity.Left, 2,2);
  947. }
  948. throw new InvalidOperationException ("Unknown operator " + op.ToString());
  949. }
  950. internal static bool IsOperator(TokenType type) {
  951. return Array.IndexOf (OperatorTypes, type) != -1;
  952. }
  953. // Valid types of operators.
  954. internal static TokenType[] OperatorTypes {
  955. get {
  956. return new TokenType[] {
  957. TokenType.Not,
  958. TokenType.UnaryMinus,
  959. TokenType.Add,
  960. TokenType.Minus,
  961. TokenType.Divide,
  962. TokenType.Multiply,
  963. TokenType.Modulo,
  964. TokenType.EqualToOrAssign,
  965. TokenType.EqualTo,
  966. TokenType.GreaterThan,
  967. TokenType.GreaterThanOrEqualTo,
  968. TokenType.LessThan,
  969. TokenType.LessThanOrEqualTo,
  970. TokenType.NotEqualTo,
  971. TokenType.And,
  972. TokenType.Or,
  973. TokenType.Xor
  974. };
  975. }
  976. }
  977. internal Operator(ParseNode parent, TokenType t, Parser p) : base(parent, p) {
  978. operatorType = t;
  979. }
  980. internal Operator(ParseNode parent, Parser p) : base(parent, p) {
  981. operatorType = p.ExpectSymbol(Operator.OperatorTypes).type;
  982. }
  983. internal override string PrintTree (int indentLevel)
  984. {
  985. return Tab (indentLevel, operatorType.ToString ());
  986. }
  987. }
  988. #endregion Parse Nodes
  989. // Use a queue since we're continuously consuming them as
  990. // we parse
  991. Queue<Token> tokens;
  992. Library library;
  993. // Take whatever we were given and make a queue out of it.
  994. // If library is null, no checks are made to function calls, and
  995. // all function calls are assumed to be valid.
  996. internal Parser(ICollection<Token> tokens, Library library) {
  997. this.tokens = new Queue<Token>(tokens);
  998. this.library = library;
  999. }
  1000. internal Node Parse() {
  1001. // Kick off the parsing process by trying to parse a whole node
  1002. return new Node("Start", null, this);
  1003. }
  1004. // Returns true if the next symbol is one of 'validTypes'
  1005. bool NextSymbolIs(params TokenType[] validTypes) {
  1006. var t = this.tokens.Peek().type;
  1007. foreach (var validType in validTypes) {
  1008. if (t == validType) {
  1009. return true;
  1010. }
  1011. }
  1012. return false;
  1013. }
  1014. // Returns true if the next symbols are of the same type as
  1015. // 'validTypes' - this is used to look further ahead in the
  1016. // token stream, eg when we're looking for '<<' 'else'
  1017. bool NextSymbolsAre(params TokenType[] validTypes) {
  1018. var tempQueue = new Queue<Token> (tokens);
  1019. foreach (var type in validTypes) {
  1020. if (tempQueue.Dequeue ().type != type)
  1021. return false;
  1022. }
  1023. return true;
  1024. }
  1025. // Return the next token, which must be of type 'type',
  1026. // or throw an exception
  1027. Token ExpectSymbol(TokenType type) {
  1028. var t = this.tokens.Dequeue();
  1029. if (t.type != type) {
  1030. throw ParseException.Make(t, type);
  1031. }
  1032. return t;
  1033. }
  1034. // Return the next token, which can be of any type except EndOfInput.
  1035. Token ExpectSymbol() {
  1036. var token = this.tokens.Dequeue ();
  1037. if (token.type == TokenType.EndOfInput) {
  1038. throw ParseException.Make (token, "Unexpected end of input");
  1039. }
  1040. return token;
  1041. }
  1042. // Return the next token, which must be one of 'validTypes',
  1043. // or throw an exception
  1044. Token ExpectSymbol(params TokenType[] validTypes) {
  1045. var t = this.tokens.Dequeue();
  1046. foreach (var validType in validTypes) {
  1047. if (t.type == validType) {
  1048. return t;
  1049. }
  1050. }
  1051. throw ParseException.Make(t, validTypes);
  1052. }
  1053. }
  1054. }