utctree.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2025 by Michael Van Canneyt ([email protected])
  4. Test EBNF AST elements
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit utctree;
  12. interface
  13. uses
  14. fpcunit, testregistry, SysUtils,
  15. ebnf.tree;
  16. type
  17. TTestEBNFElementsToString = class(TTestCase)
  18. protected
  19. procedure SetUp; override;
  20. procedure TearDown; override;
  21. published
  22. procedure TestElementToString;
  23. procedure TestRuleToString;
  24. procedure TestExpressionToString;
  25. procedure TestTermToString;
  26. procedure TestFactorIdentifierToString;
  27. procedure TestFactorStringLiteralToString;
  28. procedure TestFactorOptionalToString;
  29. procedure TestFactorRepetitionToString;
  30. procedure TestFactorGroupToString;
  31. procedure TestFactorSpecialSequenceToString;
  32. procedure TestGrammarToString;
  33. end;
  34. implementation
  35. { TTestEBNFElementsToString }
  36. procedure TTestEBNFElementsToString.SetUp;
  37. begin
  38. inherited SetUp;
  39. end;
  40. procedure TTestEBNFElementsToString.TearDown;
  41. begin
  42. inherited TearDown;
  43. end;
  44. procedure TTestEBNFElementsToString.TestElementToString;
  45. var
  46. Node: TEBNFElement;
  47. begin
  48. Node := TEBNFElement.Create(etRule);
  49. try
  50. CheckEquals('Node Type: etRule', Node.ToString, 'Base AST Node ToString should show node type');
  51. finally
  52. Node.Free;
  53. end;
  54. end;
  55. procedure TTestEBNFElementsToString.TestRuleToString;
  56. var
  57. Rule: TEBNFRule;
  58. Expression: TEBNFExpression;
  59. Term: TEBNFTerm;
  60. Factor: TEBNFFactor;
  61. begin
  62. Factor := TEBNFFactor.Create(etFactorStringLiteral, 'keyword');
  63. Term := TEBNFTerm.Create;
  64. Term.AddFactor(Factor);
  65. Expression := TEBNFExpression.Create;
  66. Expression.AddTerm(Term);
  67. Rule := TEBNFRule.Create('myRule', Expression); // Rule takes ownership of Expression
  68. try
  69. CheckEquals('myRule = "keyword";', Rule.ToString, 'Rule ToString should be "identifier = expression;"');
  70. finally
  71. Rule.Free;
  72. end;
  73. end;
  74. procedure TTestEBNFElementsToString.TestExpressionToString;
  75. var
  76. Expression: TEBNFExpression;
  77. Term1, Term2: TEBNFTerm;
  78. Factor1, Factor2: TEBNFFactor;
  79. begin
  80. // (id1) | (id2)
  81. Factor1 := TEBNFFactor.Create(etFactorIdentifier, 'id1');
  82. Term1 := TEBNFTerm.Create;
  83. Term1.AddFactor(Factor1);
  84. Factor2 := TEBNFFactor.Create(etFactorIdentifier, 'id2');
  85. Term2 := TEBNFTerm.Create;
  86. Term2.AddFactor(Factor2);
  87. Expression := TEBNFExpression.Create;
  88. Expression.AddTerm(Term1);
  89. Expression.AddTerm(Term2);
  90. try
  91. CheckEquals('id1 | id2', Expression.ToString, 'Expression ToString should concatenate terms with |');
  92. finally
  93. Expression.Free;
  94. end;
  95. end;
  96. procedure TTestEBNFElementsToString.TestTermToString;
  97. var
  98. Term: TEBNFTerm;
  99. Factor1, Factor2: TEBNFFactor;
  100. begin
  101. // factorA "literalB"
  102. Factor1 := TEBNFFactor.Create(etFactorIdentifier, 'factorA');
  103. Factor2 := TEBNFFactor.Create(etFactorStringLiteral, 'literalB');
  104. Term := TEBNFTerm.Create;
  105. Term.AddFactor(Factor1);
  106. Term.AddFactor(Factor2);
  107. try
  108. CheckEquals('factorA "literalB"', Term.ToString, 'Term ToString should concatenate factors with space');
  109. finally
  110. Term.Free;
  111. end;
  112. end;
  113. procedure TTestEBNFElementsToString.TestFactorIdentifierToString;
  114. var
  115. Factor: TEBNFFactor;
  116. begin
  117. Factor := TEBNFFactor.Create(etFactorIdentifier, 'myIdentifier');
  118. try
  119. CheckEquals('myIdentifier', Factor.ToString, 'Identifier factor ToString should return its value');
  120. finally
  121. Factor.Free;
  122. end;
  123. end;
  124. procedure TTestEBNFElementsToString.TestFactorStringLiteralToString;
  125. var
  126. Factor: TEBNFFactor;
  127. begin
  128. Factor := TEBNFFactor.Create(etFactorStringLiteral, 'hello');
  129. try
  130. CheckEquals('"hello"', Factor.ToString, 'String literal factor ToString should return quoted value');
  131. finally
  132. Factor.Free;
  133. end;
  134. end;
  135. procedure TTestEBNFElementsToString.TestFactorOptionalToString;
  136. var
  137. Factor: TEBNFFactor;
  138. InnerExpression: TEBNFExpression;
  139. InnerTerm: TEBNFTerm;
  140. InnerFactor: TEBNFFactor;
  141. begin
  142. InnerFactor := TEBNFFactor.Create(etFactorIdentifier, 'optionalPart');
  143. InnerTerm := TEBNFTerm.Create;
  144. InnerTerm.AddFactor(InnerFactor);
  145. InnerExpression := TEBNFExpression.Create;
  146. InnerExpression.AddTerm(InnerTerm);
  147. Factor := TEBNFFactor.Create(etFactorOptional, InnerExpression); // Factor takes ownership of InnerExpression
  148. try
  149. CheckEquals('[optionalPart]', Factor.ToString, 'Optional factor ToString should be [expression]');
  150. finally
  151. Factor.Free;
  152. end;
  153. end;
  154. procedure TTestEBNFElementsToString.TestFactorRepetitionToString;
  155. var
  156. Factor: TEBNFFactor;
  157. InnerExpression: TEBNFExpression;
  158. InnerTerm: TEBNFTerm;
  159. InnerFactor: TEBNFFactor;
  160. begin
  161. InnerFactor := TEBNFFactor.Create(etFactorStringLiteral, 'repeated');
  162. InnerTerm := TEBNFTerm.Create;
  163. InnerTerm.AddFactor(InnerFactor);
  164. InnerExpression := TEBNFExpression.Create;
  165. InnerExpression.AddTerm(InnerTerm);
  166. Factor := TEBNFFactor.Create(etFactorRepetition, InnerExpression); // Factor takes ownership of InnerExpression
  167. try
  168. CheckEquals('{"repeated"}', Factor.ToString, 'Repetition factor ToString should be {expression}');
  169. finally
  170. Factor.Free;
  171. end;
  172. end;
  173. procedure TTestEBNFElementsToString.TestFactorGroupToString;
  174. var
  175. Factor: TEBNFFactor;
  176. InnerExpression: TEBNFExpression;
  177. InnerTerm1, InnerTerm2: TEBNFTerm;
  178. InnerFactor1, InnerFactor2: TEBNFFactor;
  179. begin
  180. InnerFactor1 := TEBNFFactor.Create(etFactorIdentifier, 'choiceA');
  181. InnerTerm1 := TEBNFTerm.Create;
  182. InnerTerm1.AddFactor(InnerFactor1);
  183. InnerFactor2 := TEBNFFactor.Create(etFactorIdentifier, 'choiceB');
  184. InnerTerm2 := TEBNFTerm.Create;
  185. InnerTerm2.AddFactor(InnerFactor2);
  186. InnerExpression := TEBNFExpression.Create;
  187. InnerExpression.AddTerm(InnerTerm1);
  188. InnerExpression.AddTerm(InnerTerm2);
  189. Factor := TEBNFFactor.Create(etFactorGroup, InnerExpression); // Factor takes ownership of InnerExpression
  190. try
  191. CheckEquals('(choiceA | choiceB)', Factor.ToString, 'Group factor ToString should be (expression)');
  192. finally
  193. Factor.Free; // This will free InnerExpression, InnerTerm1, InnerTerm2, InnerFactor1, InnerFactor2
  194. end;
  195. end;
  196. procedure TTestEBNFElementsToString.TestFactorSpecialSequenceToString;
  197. var
  198. Factor: TEBNFFactor;
  199. begin
  200. Factor := TEBNFFactor.Create(etFactorSpecialSequence, 'this is a comment');
  201. try
  202. CheckEquals('?this is a comment?', Factor.ToString, 'Special sequence factor ToString should be ?value?');
  203. finally
  204. Factor.Free;
  205. end;
  206. end;
  207. procedure TTestEBNFElementsToString.TestGrammarToString;
  208. var
  209. Grammar: TEBNFGrammar;
  210. Rule1, Rule2: TEBNFRule;
  211. Expr1, Expr2: TEBNFExpression;
  212. Term1, Term2: TEBNFTerm;
  213. Factor1, Factor2: TEBNFFactor;
  214. begin
  215. Grammar := TEBNFGrammar.Create;
  216. // Rule 1: ruleA = "litA" ;
  217. Factor1 := TEBNFFactor.Create(etFactorStringLiteral, 'litA');
  218. Term1 := TEBNFTerm.Create;
  219. Term1.AddFactor(Factor1);
  220. Expr1 := TEBNFExpression.Create;
  221. Expr1.AddTerm(Term1);
  222. Rule1 := TEBNFRule.Create('ruleA', Expr1);
  223. Grammar.AddRule(Rule1);
  224. // Rule 2: ruleB = idB ;
  225. Factor2 := TEBNFFactor.Create(etFactorIdentifier, 'idB');
  226. Term2 := TEBNFTerm.Create;
  227. Term2.AddFactor(Factor2);
  228. Expr2 := TEBNFExpression.Create;
  229. Expr2.AddTerm(Term2);
  230. Rule2 := TEBNFRule.Create('ruleB', Expr2);
  231. Grammar.AddRule(Rule2);
  232. try
  233. CheckEquals(
  234. 'ruleA = "litA";' + sLineBreak +
  235. sLineBreak +
  236. 'ruleB = idB;' + sLineBreak +
  237. sLineBreak,
  238. Grammar.ToString,
  239. 'Grammar ToString should list all rules with line breaks'
  240. );
  241. finally
  242. Grammar.Free;
  243. end;
  244. end;
  245. initialization
  246. RegisterTest(TTestEBNFElementsToString);
  247. end.