taskjuggler 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (571) hide show
  1. data/COPYING +280 -0
  2. data/README +31 -0
  3. data/Rakefile +20 -0
  4. data/benchmarks/UTF-8-Strings.rb +58 -0
  5. data/benchmarks/allocate.tjp +30 -0
  6. data/benchmarks/booking.tjp +62 -0
  7. data/benchmarks/depends.tjp +112 -0
  8. data/benchmarks/htmltaskreport.tjp +45 -0
  9. data/benchmarks/runbench.rb +24 -0
  10. data/bin/tj3 +3 -0
  11. data/bin/tj3man +3 -0
  12. data/doc/classes/AppConfig.html +808 -0
  13. data/doc/classes/Arguments.html +226 -0
  14. data/doc/classes/String.html +395 -0
  15. data/doc/classes/TaskJuggler.html +1358 -0
  16. data/doc/classes/TaskJuggler/Account.html +257 -0
  17. data/doc/classes/TaskJuggler/AccountScenario.html +218 -0
  18. data/doc/classes/TaskJuggler/Allocation.html +419 -0
  19. data/doc/classes/TaskJuggler/AllocationAttribute.html +291 -0
  20. data/doc/classes/TaskJuggler/AttributeBase.html +608 -0
  21. data/doc/classes/TaskJuggler/AttributeDefinition.html +259 -0
  22. data/doc/classes/TaskJuggler/Booking.html +307 -0
  23. data/doc/classes/TaskJuggler/BookingListAttribute.html +263 -0
  24. data/doc/classes/TaskJuggler/BooleanAttribute.html +261 -0
  25. data/doc/classes/TaskJuggler/CSVFile.html +325 -0
  26. data/doc/classes/TaskJuggler/Charge.html +279 -0
  27. data/doc/classes/TaskJuggler/ChargeListAttribute.html +229 -0
  28. data/doc/classes/TaskJuggler/ChargeSet.html +440 -0
  29. data/doc/classes/TaskJuggler/ChargeSetListAttribute.html +276 -0
  30. data/doc/classes/TaskJuggler/ColumnTable.html +260 -0
  31. data/doc/classes/TaskJuggler/DateAttribute.html +194 -0
  32. data/doc/classes/TaskJuggler/DependencyListAttribute.html +267 -0
  33. data/doc/classes/TaskJuggler/DurationAttribute.html +229 -0
  34. data/doc/classes/TaskJuggler/FixnumAttribute.html +194 -0
  35. data/doc/classes/TaskJuggler/FlagListAttribute.html +263 -0
  36. data/doc/classes/TaskJuggler/FloatAttribute.html +229 -0
  37. data/doc/classes/TaskJuggler/GanttChart.html +667 -0
  38. data/doc/classes/TaskJuggler/GanttContainer.html +441 -0
  39. data/doc/classes/TaskJuggler/GanttHeader.html +280 -0
  40. data/doc/classes/TaskJuggler/GanttHeaderScaleItem.html +245 -0
  41. data/doc/classes/TaskJuggler/GanttLine.html +398 -0
  42. data/doc/classes/TaskJuggler/GanttLoadStack.html +327 -0
  43. data/doc/classes/TaskJuggler/GanttMilestone.html +415 -0
  44. data/doc/classes/TaskJuggler/GanttRouter.html +425 -0
  45. data/doc/classes/TaskJuggler/GanttTaskBar.html +429 -0
  46. data/doc/classes/TaskJuggler/HTMLDocument.html +240 -0
  47. data/doc/classes/TaskJuggler/HTMLGraphics.html +231 -0
  48. data/doc/classes/TaskJuggler/Interval.html +552 -0
  49. data/doc/classes/TaskJuggler/IntervalListAttribute.html +267 -0
  50. data/doc/classes/TaskJuggler/KeywordDocumentation.html +796 -0
  51. data/doc/classes/TaskJuggler/Limits.html +416 -0
  52. data/doc/classes/TaskJuggler/Limits/Limit.html +381 -0
  53. data/doc/classes/TaskJuggler/LimitsAttribute.html +261 -0
  54. data/doc/classes/TaskJuggler/Log.html +613 -0
  55. data/doc/classes/TaskJuggler/LogicalAttribute.html +226 -0
  56. data/doc/classes/TaskJuggler/LogicalExpression.html +251 -0
  57. data/doc/classes/TaskJuggler/LogicalFlag.html +229 -0
  58. data/doc/classes/TaskJuggler/LogicalFunction.html +324 -0
  59. data/doc/classes/TaskJuggler/LogicalOperation.html +299 -0
  60. data/doc/classes/TaskJuggler/Macro.html +194 -0
  61. data/doc/classes/TaskJuggler/MacroParser.html +360 -0
  62. data/doc/classes/TaskJuggler/MacroTable.html +366 -0
  63. data/doc/classes/TaskJuggler/Message.html +281 -0
  64. data/doc/classes/TaskJuggler/MessageHandler.html +215 -0
  65. data/doc/classes/TaskJuggler/Project.html +1606 -0
  66. data/doc/classes/TaskJuggler/ProjectFileParser.html +412 -0
  67. data/doc/classes/TaskJuggler/PropertyList.html +597 -0
  68. data/doc/classes/TaskJuggler/PropertySet.html +1200 -0
  69. data/doc/classes/TaskJuggler/PropertyTreeNode.html +1449 -0
  70. data/doc/classes/TaskJuggler/Query.html +600 -0
  71. data/doc/classes/TaskJuggler/RealFormat.html +252 -0
  72. data/doc/classes/TaskJuggler/ReferenceAttribute.html +194 -0
  73. data/doc/classes/TaskJuggler/Report.html +528 -0
  74. data/doc/classes/TaskJuggler/ReportElement.html +1070 -0
  75. data/doc/classes/TaskJuggler/ReportTable.html +497 -0
  76. data/doc/classes/TaskJuggler/ReportTableCell.html +518 -0
  77. data/doc/classes/TaskJuggler/ReportTableColumn.html +364 -0
  78. data/doc/classes/TaskJuggler/ReportTableElement.html +644 -0
  79. data/doc/classes/TaskJuggler/ReportTableLegend.html +343 -0
  80. data/doc/classes/TaskJuggler/ReportTableLine.html +431 -0
  81. data/doc/classes/TaskJuggler/Resource.html +211 -0
  82. data/doc/classes/TaskJuggler/ResourceListAttribute.html +267 -0
  83. data/doc/classes/TaskJuggler/ResourceListRE.html +249 -0
  84. data/doc/classes/TaskJuggler/ResourceScenario.html +1137 -0
  85. data/doc/classes/TaskJuggler/RichText.html +537 -0
  86. data/doc/classes/TaskJuggler/RichTextAttribute.html +229 -0
  87. data/doc/classes/TaskJuggler/RichTextDocument.html +418 -0
  88. data/doc/classes/TaskJuggler/RichTextElement.html +829 -0
  89. data/doc/classes/TaskJuggler/RichTextException.html +212 -0
  90. data/doc/classes/TaskJuggler/RichTextParser.html +317 -0
  91. data/doc/classes/TaskJuggler/RichTextProtocolExample.html +303 -0
  92. data/doc/classes/TaskJuggler/RichTextProtocolHandler.html +194 -0
  93. data/doc/classes/TaskJuggler/RichTextScanner.html +561 -0
  94. data/doc/classes/TaskJuggler/RichTextSnip.html +364 -0
  95. data/doc/classes/TaskJuggler/RichTextSyntaxRules.html +883 -0
  96. data/doc/classes/TaskJuggler/Scenario.html +163 -0
  97. data/doc/classes/TaskJuggler/ScenarioData.html +354 -0
  98. data/doc/classes/TaskJuggler/Scoreboard.html +638 -0
  99. data/doc/classes/TaskJuggler/Shift.html +255 -0
  100. data/doc/classes/TaskJuggler/ShiftAssignment.html +488 -0
  101. data/doc/classes/TaskJuggler/ShiftAssignments.html +715 -0
  102. data/doc/classes/TaskJuggler/ShiftAssignmentsAttribute.html +261 -0
  103. data/doc/classes/TaskJuggler/ShiftScenario.html +282 -0
  104. data/doc/classes/TaskJuggler/SourceFileInfo.html +247 -0
  105. data/doc/classes/TaskJuggler/StringAttribute.html +229 -0
  106. data/doc/classes/TaskJuggler/SymbolAttribute.html +194 -0
  107. data/doc/classes/TaskJuggler/SyntaxReference.html +516 -0
  108. data/doc/classes/TaskJuggler/TOCEntry.html +242 -0
  109. data/doc/classes/TaskJuggler/TableColumnDefinition.html +273 -0
  110. data/doc/classes/TaskJuggler/TableOfContents.html +256 -0
  111. data/doc/classes/TaskJuggler/Task.html +203 -0
  112. data/doc/classes/TaskJuggler/TaskDependency.html +251 -0
  113. data/doc/classes/TaskJuggler/TaskListAttribute.html +267 -0
  114. data/doc/classes/TaskJuggler/TaskListRE.html +250 -0
  115. data/doc/classes/TaskJuggler/TaskScenario.html +2206 -0
  116. data/doc/classes/TaskJuggler/TextParser.html +670 -0
  117. data/doc/classes/TaskJuggler/TextParser/Pattern.html +923 -0
  118. data/doc/classes/TaskJuggler/TextParser/Rule.html +779 -0
  119. data/doc/classes/TaskJuggler/TextParser/StackElement.html +267 -0
  120. data/doc/classes/TaskJuggler/TextParser/TextParserResultArray.html +212 -0
  121. data/doc/classes/TaskJuggler/TextParser/TokenDoc.html +221 -0
  122. data/doc/classes/TaskJuggler/TextScanner.html +708 -0
  123. data/doc/classes/TaskJuggler/TextScanner/BufferStreamHandle.html +355 -0
  124. data/doc/classes/TaskJuggler/TextScanner/FileStreamHandle.html +341 -0
  125. data/doc/classes/TaskJuggler/TextScanner/StreamHandle.html +260 -0
  126. data/doc/classes/TaskJuggler/TjException.html +185 -0
  127. data/doc/classes/TaskJuggler/TjTime.html +1845 -0
  128. data/doc/classes/TaskJuggler/TjpExample.html +310 -0
  129. data/doc/classes/TaskJuggler/TjpExportRE.html +329 -0
  130. data/doc/classes/TaskJuggler/TjpSyntaxRules.html +8928 -0
  131. data/doc/classes/TaskJuggler/UserManual.html +606 -0
  132. data/doc/classes/TaskJuggler/WorkingHours.html +582 -0
  133. data/doc/classes/TaskJuggler/WorkingHoursAttribute.html +284 -0
  134. data/doc/classes/TaskJuggler/XMLBlob.html +207 -0
  135. data/doc/classes/TaskJuggler/XMLComment.html +206 -0
  136. data/doc/classes/TaskJuggler/XMLDocument.html +293 -0
  137. data/doc/classes/TaskJuggler/XMLElement.html +341 -0
  138. data/doc/classes/TaskJuggler/XMLNamedText.html +174 -0
  139. data/doc/classes/TaskJuggler/XMLText.html +221 -0
  140. data/doc/files/COPYING.html +448 -0
  141. data/doc/files/README.html +134 -0
  142. data/doc/files/lib/AccountScenario_rb.html +116 -0
  143. data/doc/files/lib/Account_rb.html +118 -0
  144. data/doc/files/lib/Allocation_rb.html +118 -0
  145. data/doc/files/lib/AppConfig_rb.html +116 -0
  146. data/doc/files/lib/AttributeBase_rb.html +106 -0
  147. data/doc/files/lib/AttributeDefinition_rb.html +106 -0
  148. data/doc/files/lib/Attributes_rb.html +130 -0
  149. data/doc/files/lib/Booking_rb.html +106 -0
  150. data/doc/files/lib/ChargeSet_rb.html +116 -0
  151. data/doc/files/lib/Charge_rb.html +116 -0
  152. data/doc/files/lib/HTMLDocument_rb.html +116 -0
  153. data/doc/files/lib/Interval_rb.html +116 -0
  154. data/doc/files/lib/KeywordDocumentation_rb.html +122 -0
  155. data/doc/files/lib/Limits_rb.html +116 -0
  156. data/doc/files/lib/Log_rb.html +116 -0
  157. data/doc/files/lib/LogicalExpression_rb.html +122 -0
  158. data/doc/files/lib/LogicalFlag_rb.html +116 -0
  159. data/doc/files/lib/LogicalFunction_rb.html +116 -0
  160. data/doc/files/lib/LogicalOperation_rb.html +116 -0
  161. data/doc/files/lib/MacroParser_rb.html +118 -0
  162. data/doc/files/lib/MacroTable_rb.html +122 -0
  163. data/doc/files/lib/MessageHandler_rb.html +106 -0
  164. data/doc/files/lib/Message_rb.html +116 -0
  165. data/doc/files/lib/ProjectFileParser_rb.html +122 -0
  166. data/doc/files/lib/Project_rb.html +148 -0
  167. data/doc/files/lib/PropertyList_rb.html +106 -0
  168. data/doc/files/lib/PropertySet_rb.html +118 -0
  169. data/doc/files/lib/PropertyTreeNode_rb.html +106 -0
  170. data/doc/files/lib/Query_rb.html +116 -0
  171. data/doc/files/lib/RealFormat_rb.html +106 -0
  172. data/doc/files/lib/ResourceScenario_rb.html +116 -0
  173. data/doc/files/lib/Resource_rb.html +118 -0
  174. data/doc/files/lib/RichTextDocument_rb.html +120 -0
  175. data/doc/files/lib/RichTextElement_rb.html +120 -0
  176. data/doc/files/lib/RichTextParser_rb.html +120 -0
  177. data/doc/files/lib/RichTextProtocolExample_rb.html +120 -0
  178. data/doc/files/lib/RichTextProtocolHandler_rb.html +106 -0
  179. data/doc/files/lib/RichTextScanner_rb.html +116 -0
  180. data/doc/files/lib/RichTextSnip_rb.html +118 -0
  181. data/doc/files/lib/RichTextSyntaxRules_rb.html +106 -0
  182. data/doc/files/lib/RichText_rb.html +118 -0
  183. data/doc/files/lib/ScenarioData_rb.html +118 -0
  184. data/doc/files/lib/Scenario_rb.html +116 -0
  185. data/doc/files/lib/Scoreboard_rb.html +106 -0
  186. data/doc/files/lib/ShiftAssignments_rb.html +116 -0
  187. data/doc/files/lib/ShiftScenario_rb.html +116 -0
  188. data/doc/files/lib/Shift_rb.html +118 -0
  189. data/doc/files/lib/SourceFileInfo_rb.html +106 -0
  190. data/doc/files/lib/SyntaxReference_rb.html +122 -0
  191. data/doc/files/lib/TOCEntry_rb.html +118 -0
  192. data/doc/files/lib/TableColumnDefinition_rb.html +106 -0
  193. data/doc/files/lib/TableOfContents_rb.html +118 -0
  194. data/doc/files/lib/TaskDependency_rb.html +106 -0
  195. data/doc/files/lib/TaskJuggler_rb.html +120 -0
  196. data/doc/files/lib/TaskScenario_rb.html +116 -0
  197. data/doc/files/lib/Task_rb.html +118 -0
  198. data/doc/files/lib/TextParser/Pattern_rb.html +116 -0
  199. data/doc/files/lib/TextParser/Rule_rb.html +106 -0
  200. data/doc/files/lib/TextParser/StackElement_rb.html +106 -0
  201. data/doc/files/lib/TextParser/TokenDoc_rb.html +106 -0
  202. data/doc/files/lib/TextParser_rb.html +124 -0
  203. data/doc/files/lib/TextScanner_rb.html +128 -0
  204. data/doc/files/lib/Tj3Config_rb.html +118 -0
  205. data/doc/files/lib/TjException_rb.html +106 -0
  206. data/doc/files/lib/TjTime_rb.html +118 -0
  207. data/doc/files/lib/TjpExample_rb.html +116 -0
  208. data/doc/files/lib/TjpSyntaxRules_rb.html +106 -0
  209. data/doc/files/lib/UTF8String_rb.html +132 -0
  210. data/doc/files/lib/UserManual_rb.html +124 -0
  211. data/doc/files/lib/WorkingHours_rb.html +116 -0
  212. data/doc/files/lib/XMLDocument_rb.html +116 -0
  213. data/doc/files/lib/XMLElement_rb.html +116 -0
  214. data/doc/files/lib/reports/CSVFile_rb.html +116 -0
  215. data/doc/files/lib/reports/ColumnTable_rb.html +116 -0
  216. data/doc/files/lib/reports/GanttChart_rb.html +122 -0
  217. data/doc/files/lib/reports/GanttContainer_rb.html +116 -0
  218. data/doc/files/lib/reports/GanttHeaderScaleItem_rb.html +106 -0
  219. data/doc/files/lib/reports/GanttHeader_rb.html +116 -0
  220. data/doc/files/lib/reports/GanttLine_rb.html +126 -0
  221. data/doc/files/lib/reports/GanttLoadStack_rb.html +116 -0
  222. data/doc/files/lib/reports/GanttMilestone_rb.html +116 -0
  223. data/doc/files/lib/reports/GanttRouter_rb.html +106 -0
  224. data/doc/files/lib/reports/GanttTaskBar_rb.html +116 -0
  225. data/doc/files/lib/reports/HTMLGraphics_rb.html +106 -0
  226. data/doc/files/lib/reports/ReportElement_rb.html +118 -0
  227. data/doc/files/lib/reports/ReportTableCell_rb.html +106 -0
  228. data/doc/files/lib/reports/ReportTableColumn_rb.html +106 -0
  229. data/doc/files/lib/reports/ReportTableElement_rb.html +122 -0
  230. data/doc/files/lib/reports/ReportTableLegend_rb.html +106 -0
  231. data/doc/files/lib/reports/ReportTableLine_rb.html +116 -0
  232. data/doc/files/lib/reports/ReportTable_rb.html +118 -0
  233. data/doc/files/lib/reports/Report_rb.html +126 -0
  234. data/doc/files/lib/reports/ResourceListRE_rb.html +122 -0
  235. data/doc/files/lib/reports/TaskListRE_rb.html +122 -0
  236. data/doc/files/lib/reports/TjpExportRE_rb.html +116 -0
  237. data/doc/files/lib/taskjuggler3_rb.html +276 -0
  238. data/doc/files/lib/tj3man_rb.html +189 -0
  239. data/doc/fr_class_index.html +285 -0
  240. data/doc/fr_file_index.html +223 -0
  241. data/doc/fr_method_index.html +1953 -0
  242. data/doc/index.html +21 -0
  243. data/doc/rdoc-style.css +299 -0
  244. data/examples/tutorial.tjp +361 -0
  245. data/gem_spec.rb +30 -0
  246. data/lib/Account.rb +50 -0
  247. data/lib/AccountScenario.rb +39 -0
  248. data/lib/Allocation.rb +102 -0
  249. data/lib/AppConfig.rb +134 -0
  250. data/lib/AttributeBase.rb +131 -0
  251. data/lib/AttributeDefinition.rb +47 -0
  252. data/lib/Attributes.rb +478 -0
  253. data/lib/BatchProcessor.rb +209 -0
  254. data/lib/Booking.rb +59 -0
  255. data/lib/Charge.rb +71 -0
  256. data/lib/ChargeSet.rb +126 -0
  257. data/lib/HTMLDocument.rb +59 -0
  258. data/lib/Interval.rb +127 -0
  259. data/lib/KeywordDocumentation.rb +560 -0
  260. data/lib/Limits.rb +219 -0
  261. data/lib/Log.rb +160 -0
  262. data/lib/LogicalExpression.rb +71 -0
  263. data/lib/LogicalFlag.rb +34 -0
  264. data/lib/LogicalFunction.rb +102 -0
  265. data/lib/LogicalOperation.rb +118 -0
  266. data/lib/MacroParser.rb +77 -0
  267. data/lib/MacroTable.rb +84 -0
  268. data/lib/Message.rb +56 -0
  269. data/lib/MessageHandler.rb +34 -0
  270. data/lib/Project.rb +662 -0
  271. data/lib/ProjectFileParser.rb +333 -0
  272. data/lib/PropertyList.rb +181 -0
  273. data/lib/PropertySet.rb +304 -0
  274. data/lib/PropertyTreeNode.rb +461 -0
  275. data/lib/Query.rb +227 -0
  276. data/lib/RealFormat.rb +73 -0
  277. data/lib/Resource.rb +42 -0
  278. data/lib/ResourceScenario.rb +511 -0
  279. data/lib/RichText.rb +147 -0
  280. data/lib/RichTextDocument.rb +139 -0
  281. data/lib/RichTextElement.rb +391 -0
  282. data/lib/RichTextParser.rb +66 -0
  283. data/lib/RichTextProtocolExample.rb +65 -0
  284. data/lib/RichTextProtocolHandler.rb +35 -0
  285. data/lib/RichTextScanner.rb +390 -0
  286. data/lib/RichTextSnip.rb +104 -0
  287. data/lib/RichTextSyntaxRules.rb +265 -0
  288. data/lib/Scenario.rb +27 -0
  289. data/lib/ScenarioData.rb +65 -0
  290. data/lib/Scoreboard.rb +141 -0
  291. data/lib/Shift.rb +48 -0
  292. data/lib/ShiftAssignments.rb +291 -0
  293. data/lib/ShiftScenario.rb +46 -0
  294. data/lib/SourceFileInfo.rb +37 -0
  295. data/lib/SyntaxReference.rb +284 -0
  296. data/lib/TOCEntry.rb +76 -0
  297. data/lib/TableColumnDefinition.rb +54 -0
  298. data/lib/TableOfContents.rb +46 -0
  299. data/lib/Task.rb +37 -0
  300. data/lib/TaskDependency.rb +39 -0
  301. data/lib/TaskJuggler.rb +84 -0
  302. data/lib/TaskScenario.rb +1622 -0
  303. data/lib/TextParser.rb +416 -0
  304. data/lib/TextParser/Pattern.rb +263 -0
  305. data/lib/TextParser/Rule.rb +171 -0
  306. data/lib/TextParser/StackElement.rb +45 -0
  307. data/lib/TextParser/TokenDoc.rb +38 -0
  308. data/lib/TextScanner.rb +682 -0
  309. data/lib/Tj3Config.rb +27 -0
  310. data/lib/TjException.rb +27 -0
  311. data/lib/TjTime.rb +395 -0
  312. data/lib/TjpExample.rb +119 -0
  313. data/lib/TjpSyntaxRules.rb +4022 -0
  314. data/lib/UTF8String.rb +100 -0
  315. data/lib/UserManual.rb +282 -0
  316. data/lib/WorkingHours.rb +323 -0
  317. data/lib/XMLDocument.rb +54 -0
  318. data/lib/XMLElement.rb +175 -0
  319. data/lib/reports/CSVFile.rb +146 -0
  320. data/lib/reports/ColumnTable.rb +66 -0
  321. data/lib/reports/GanttChart.rb +308 -0
  322. data/lib/reports/GanttContainer.rb +107 -0
  323. data/lib/reports/GanttHeader.rb +141 -0
  324. data/lib/reports/GanttHeaderScaleItem.rb +42 -0
  325. data/lib/reports/GanttLine.rb +329 -0
  326. data/lib/reports/GanttLoadStack.rb +113 -0
  327. data/lib/reports/GanttMilestone.rb +80 -0
  328. data/lib/reports/GanttRouter.rb +375 -0
  329. data/lib/reports/GanttTaskBar.rb +95 -0
  330. data/lib/reports/HTMLGraphics.rb +65 -0
  331. data/lib/reports/Report.rb +344 -0
  332. data/lib/reports/ReportElement.rb +427 -0
  333. data/lib/reports/ReportTable.rb +144 -0
  334. data/lib/reports/ReportTableCell.rb +142 -0
  335. data/lib/reports/ReportTableColumn.rb +82 -0
  336. data/lib/reports/ReportTableElement.rb +852 -0
  337. data/lib/reports/ReportTableLegend.rb +167 -0
  338. data/lib/reports/ReportTableLine.rb +87 -0
  339. data/lib/reports/ResourceListRE.rb +72 -0
  340. data/lib/reports/TaskListRE.rb +73 -0
  341. data/lib/reports/TjpExportRE.rb +394 -0
  342. data/lib/taskjuggler3.rb +106 -0
  343. data/lib/tj3man.rb +88 -0
  344. data/manual/Day_To_Day_Juggling +168 -0
  345. data/manual/Getting_Started +61 -0
  346. data/manual/How_To_Contribute +185 -0
  347. data/manual/Installation +68 -0
  348. data/manual/Intro +102 -0
  349. data/manual/Reporting_Bugs +26 -0
  350. data/manual/Rich_Text_Attributes +90 -0
  351. data/manual/TaskJuggler_2x_Migration +40 -0
  352. data/manual/Tutorial +579 -0
  353. data/manual/fdl +450 -0
  354. data/prj_cfg.rb +43 -0
  355. data/setup.rb +1585 -0
  356. data/tasks/csts.rake +72 -0
  357. data/tasks/gem.rake +14 -0
  358. data/tasks/manual.rake +10 -0
  359. data/tasks/missing.rake +21 -0
  360. data/tasks/rcov.rake +14 -0
  361. data/tasks/rdoc.rake +17 -0
  362. data/tasks/rexml_fix.rb +16 -0
  363. data/tasks/rexml_fix_19.rb +49 -0
  364. data/tasks/show.rake +21 -0
  365. data/tasks/stats.rake +25 -0
  366. data/tasks/test.rake +11 -0
  367. data/test/MessageChecker.rb +53 -0
  368. data/test/TestSuite/CSV-Reports/celltext-Reference.csv +14 -0
  369. data/test/TestSuite/CSV-Reports/celltext.tjp +7 -0
  370. data/test/TestSuite/CSV-Reports/genrefs +6 -0
  371. data/test/TestSuite/CSV-Reports/project-1.tji +57 -0
  372. data/test/TestSuite/CSV-Reports/resourcereport-Reference.csv +4 -0
  373. data/test/TestSuite/CSV-Reports/resourcereport.tjp +10 -0
  374. data/test/TestSuite/CSV-Reports/resourcereport_with_tasks-Reference.csv +22 -0
  375. data/test/TestSuite/CSV-Reports/resourcereport_with_tasks.tjp +11 -0
  376. data/test/TestSuite/CSV-Reports/sortByTree-Reference.csv +14 -0
  377. data/test/TestSuite/CSV-Reports/sortByTree.tjp +8 -0
  378. data/test/TestSuite/CSV-Reports/sortBy_duration.down-Reference.csv +14 -0
  379. data/test/TestSuite/CSV-Reports/sortBy_duration.down.tjp +10 -0
  380. data/test/TestSuite/CSV-Reports/sortBy_effort.up-Reference.csv +14 -0
  381. data/test/TestSuite/CSV-Reports/sortBy_effort.up.tjp +10 -0
  382. data/test/TestSuite/CSV-Reports/sortBy_plan.start.down-Reference.csv +14 -0
  383. data/test/TestSuite/CSV-Reports/sortBy_plan.start.down.tjp +10 -0
  384. data/test/TestSuite/CSV-Reports/taskreport-Reference.csv +14 -0
  385. data/test/TestSuite/CSV-Reports/taskreport.tjp +10 -0
  386. data/test/TestSuite/CSV-Reports/taskreport_with_resources-Reference.csv +24 -0
  387. data/test/TestSuite/CSV-Reports/taskreport_with_resources.tjp +11 -0
  388. data/test/TestSuite/Scheduler/Correct/Allocate.tjp +86 -0
  389. data/test/TestSuite/Scheduler/Correct/AutomaticMilestones.tjp +63 -0
  390. data/test/TestSuite/Scheduler/Correct/Booking.tjp +161 -0
  391. data/test/TestSuite/Scheduler/Correct/Depends.tjp +50 -0
  392. data/test/TestSuite/Scheduler/Correct/Duration.tjp +34 -0
  393. data/test/TestSuite/Scheduler/Correct/InheritStartEnd.tjp +129 -0
  394. data/test/TestSuite/Scheduler/Correct/Limits.tjp +81 -0
  395. data/test/TestSuite/Scheduler/Correct/MultipleMandatories.tjp +43 -0
  396. data/test/TestSuite/Scheduler/Correct/Optimize-1.tjp +28 -0
  397. data/test/TestSuite/Scheduler/Correct/Optimize-2.tjp +33 -0
  398. data/test/TestSuite/Scheduler/Correct/Optimize-3.tjp +33 -0
  399. data/test/TestSuite/Scheduler/Correct/Optimize-4.tjp +34 -0
  400. data/test/TestSuite/Scheduler/Correct/Optimize-5.tjp +62 -0
  401. data/test/TestSuite/Scheduler/Correct/Precedes.tjp +50 -0
  402. data/test/TestSuite/Scheduler/Correct/Shift.tjp +102 -0
  403. data/test/TestSuite/Scheduler/Errors/account_no_leaf.tjp +13 -0
  404. data/test/TestSuite/Scheduler/Errors/booking_conflict.tjp +10 -0
  405. data/test/TestSuite/Scheduler/Errors/booking_no_duty.tjp +9 -0
  406. data/test/TestSuite/Scheduler/Errors/booking_on_vacation.tjp +9 -0
  407. data/test/TestSuite/Scheduler/Errors/container_booking.tjp +14 -0
  408. data/test/TestSuite/Scheduler/Errors/container_duration.tjp +11 -0
  409. data/test/TestSuite/Scheduler/Errors/effort_no_allocations.tjp +7 -0
  410. data/test/TestSuite/Scheduler/Errors/loop_detected_1.tjp +19 -0
  411. data/test/TestSuite/Scheduler/Errors/loop_detected_10.tjp +36 -0
  412. data/test/TestSuite/Scheduler/Errors/loop_detected_11.tjp +27 -0
  413. data/test/TestSuite/Scheduler/Errors/loop_detected_12.tjp +20 -0
  414. data/test/TestSuite/Scheduler/Errors/loop_detected_13.tjp +27 -0
  415. data/test/TestSuite/Scheduler/Errors/loop_detected_14.tjp +26 -0
  416. data/test/TestSuite/Scheduler/Errors/loop_detected_2.tjp +24 -0
  417. data/test/TestSuite/Scheduler/Errors/loop_detected_3.tjp +18 -0
  418. data/test/TestSuite/Scheduler/Errors/loop_detected_4.tjp +36 -0
  419. data/test/TestSuite/Scheduler/Errors/loop_detected_5.tjp +37 -0
  420. data/test/TestSuite/Scheduler/Errors/loop_detected_6.tjp +35 -0
  421. data/test/TestSuite/Scheduler/Errors/loop_detected_7.tjp +46 -0
  422. data/test/TestSuite/Scheduler/Errors/loop_detected_8.tjp +51 -0
  423. data/test/TestSuite/Scheduler/Errors/loop_detected_9.tjp +20 -0
  424. data/test/TestSuite/Scheduler/Errors/maxend.tjp +8 -0
  425. data/test/TestSuite/Scheduler/Errors/maxstart.tjp +8 -0
  426. data/test/TestSuite/Scheduler/Errors/milestone_booking.tjp +10 -0
  427. data/test/TestSuite/Scheduler/Errors/milestone_duration.tjp +8 -0
  428. data/test/TestSuite/Scheduler/Errors/milestone_start_end.tjp +8 -0
  429. data/test/TestSuite/Scheduler/Errors/minend.tjp +8 -0
  430. data/test/TestSuite/Scheduler/Errors/minstart.tjp +8 -0
  431. data/test/TestSuite/Scheduler/Errors/multiple_durations.tjp +11 -0
  432. data/test/TestSuite/Scheduler/Errors/no_tasks.tjp +6 -0
  433. data/test/TestSuite/Scheduler/Errors/not_scheduled.tjp +8 -0
  434. data/test/TestSuite/Scheduler/Errors/task_depend_child.tjp +10 -0
  435. data/test/TestSuite/Scheduler/Errors/task_depend_multi.tjp +13 -0
  436. data/test/TestSuite/Scheduler/Errors/task_depend_parent.tjp +11 -0
  437. data/test/TestSuite/Scheduler/Errors/task_depend_self.tjp +10 -0
  438. data/test/TestSuite/Scheduler/Errors/task_depend_unknown.tjp +10 -0
  439. data/test/TestSuite/Scheduler/Errors/task_overspecified_1.tjp +9 -0
  440. data/test/TestSuite/Scheduler/Errors/task_overspecified_2.tjp +14 -0
  441. data/test/TestSuite/Scheduler/Errors/task_overspecified_3.tjp +14 -0
  442. data/test/TestSuite/Scheduler/Errors/task_underspecified_1.tjp +8 -0
  443. data/test/TestSuite/Scheduler/Errors/task_underspecified_2.tjp +8 -0
  444. data/test/TestSuite/Scheduler/Errors/task_underspecified_3.tjp +9 -0
  445. data/test/TestSuite/Syntax/Correct/Account.tjp +53 -0
  446. data/test/TestSuite/Syntax/Correct/Allocate-1.tjp +24 -0
  447. data/test/TestSuite/Syntax/Correct/Alternative.tjp +13 -0
  448. data/test/TestSuite/Syntax/Correct/AutoMacros.tjp +14 -0
  449. data/test/TestSuite/Syntax/Correct/Booking.tjp +26 -0
  450. data/test/TestSuite/Syntax/Correct/Caption.tjp +33 -0
  451. data/test/TestSuite/Syntax/Correct/Celltext.tjp +28 -0
  452. data/test/TestSuite/Syntax/Correct/Comments.tjp +29 -0
  453. data/test/TestSuite/Syntax/Correct/Complete.tjp +16 -0
  454. data/test/TestSuite/Syntax/Correct/CompletedWork.tji +20 -0
  455. data/test/TestSuite/Syntax/Correct/CriticalPath.tjp +31 -0
  456. data/test/TestSuite/Syntax/Correct/Currencyformat.tjp +12 -0
  457. data/test/TestSuite/Syntax/Correct/CustomAttributes.tjp +14 -0
  458. data/test/TestSuite/Syntax/Correct/Depends1.tjp +22 -0
  459. data/test/TestSuite/Syntax/Correct/Durations.tjp +29 -0
  460. data/test/TestSuite/Syntax/Correct/Efficiency.tjp +19 -0
  461. data/test/TestSuite/Syntax/Correct/Export.tjp +40 -0
  462. data/test/TestSuite/Syntax/Correct/Flags.tjp +32 -0
  463. data/test/TestSuite/Syntax/Correct/Freeze.tjp +28 -0
  464. data/test/TestSuite/Syntax/Correct/Gap.tjp +15 -0
  465. data/test/TestSuite/Syntax/Correct/HtmlTaskReport.tjp +33 -0
  466. data/test/TestSuite/Syntax/Correct/Limits-1.tjp +71 -0
  467. data/test/TestSuite/Syntax/Correct/LoadUnits.tjp +31 -0
  468. data/test/TestSuite/Syntax/Correct/Macro-1.tjp +19 -0
  469. data/test/TestSuite/Syntax/Correct/Mandatory.tjp +17 -0
  470. data/test/TestSuite/Syntax/Correct/Milestone.tjp +12 -0
  471. data/test/TestSuite/Syntax/Correct/MinMax.tjp +17 -0
  472. data/test/TestSuite/Syntax/Correct/Numberformat.tjp +12 -0
  473. data/test/TestSuite/Syntax/Correct/Period.tjp +16 -0
  474. data/test/TestSuite/Syntax/Correct/Persistent.tjp +11 -0
  475. data/test/TestSuite/Syntax/Correct/Precedes1.tjp +17 -0
  476. data/test/TestSuite/Syntax/Correct/Priority.tjp +30 -0
  477. data/test/TestSuite/Syntax/Correct/Project.tjp +21 -0
  478. data/test/TestSuite/Syntax/Correct/ProjectIDs.tjp +23 -0
  479. data/test/TestSuite/Syntax/Correct/RawHTML.tjp +29 -0
  480. data/test/TestSuite/Syntax/Correct/Reports.tjp +54 -0
  481. data/test/TestSuite/Syntax/Correct/Resource.tjp +20 -0
  482. data/test/TestSuite/Syntax/Correct/Responsible.tjp +16 -0
  483. data/test/TestSuite/Syntax/Correct/Scenario.tjp +15 -0
  484. data/test/TestSuite/Syntax/Correct/Scheduling.tjp +26 -0
  485. data/test/TestSuite/Syntax/Correct/Select.tjp +27 -0
  486. data/test/TestSuite/Syntax/Correct/Shift.tjp +55 -0
  487. data/test/TestSuite/Syntax/Correct/Simple.tjp +25 -0
  488. data/test/TestSuite/Syntax/Correct/String.tjp +12 -0
  489. data/test/TestSuite/Syntax/Correct/Supplement.tjp +24 -0
  490. data/test/TestSuite/Syntax/Correct/TaskRoot.tjp +34 -0
  491. data/test/TestSuite/Syntax/Correct/TimeFrame.tjp +19 -0
  492. data/test/TestSuite/Syntax/Correct/Timezone.tjp +8 -0
  493. data/test/TestSuite/Syntax/Correct/Vacation.tjp +33 -0
  494. data/test/TestSuite/Syntax/Correct/csvtest +16 -0
  495. data/test/TestSuite/Syntax/Correct/manual2example.rb +24 -0
  496. data/test/TestSuite/Syntax/Correct/tutorial.tjp +485 -0
  497. data/test/TestSuite/Syntax/Errors/bad_include.tjp +11 -0
  498. data/test/TestSuite/Syntax/Errors/booking_group.tjp +14 -0
  499. data/test/TestSuite/Syntax/Errors/booking_milestone.tjp +13 -0
  500. data/test/TestSuite/Syntax/Errors/booking_no_leaf.tjp +13 -0
  501. data/test/TestSuite/Syntax/Errors/chargeset.tjp +14 -0
  502. data/test/TestSuite/Syntax/Errors/chargeset_master.tjp +15 -0
  503. data/test/TestSuite/Syntax/Errors/container_attribute.tjp +13 -0
  504. data/test/TestSuite/Syntax/Errors/cost_acct_no_top.tjp +24 -0
  505. data/test/TestSuite/Syntax/Errors/cost_rev_same.tjp +24 -0
  506. data/test/TestSuite/Syntax/Errors/date_in_range.tjp +7 -0
  507. data/test/TestSuite/Syntax/Errors/effort_zero.tjp +8 -0
  508. data/test/TestSuite/Syntax/Errors/empty.tjp +1 -0
  509. data/test/TestSuite/Syntax/Errors/export_bad_extn.tjp +9 -0
  510. data/test/TestSuite/Syntax/Errors/extend_id_cap.tjp +7 -0
  511. data/test/TestSuite/Syntax/Errors/interval_end_in_range.tjp +7 -0
  512. data/test/TestSuite/Syntax/Errors/interval_start_in_range.tjp +7 -0
  513. data/test/TestSuite/Syntax/Errors/leaf_resource_id_expected.tjp +12 -0
  514. data/test/TestSuite/Syntax/Errors/misaligned_date.tjp +7 -0
  515. data/test/TestSuite/Syntax/Errors/no_csv_suffix.tjp +10 -0
  516. data/test/TestSuite/Syntax/Errors/no_html_suffix.tjp +10 -0
  517. data/test/TestSuite/Syntax/Errors/operand_attribute.tjp +11 -0
  518. data/test/TestSuite/Syntax/Errors/operand_unkn_flag.tjp +11 -0
  519. data/test/TestSuite/Syntax/Errors/operand_unkn_scen.tjp +11 -0
  520. data/test/TestSuite/Syntax/Errors/overtime_range.tjp +13 -0
  521. data/test/TestSuite/Syntax/Errors/purge_no_list.tjp +8 -0
  522. data/test/TestSuite/Syntax/Errors/purge_unknown_id.tjp +8 -0
  523. data/test/TestSuite/Syntax/Errors/report_end.tjp +10 -0
  524. data/test/TestSuite/Syntax/Errors/report_redifinition.tjp +10 -0
  525. data/test/TestSuite/Syntax/Errors/report_start.tjp +10 -0
  526. data/test/TestSuite/Syntax/Errors/resource_exists.tjp +7 -0
  527. data/test/TestSuite/Syntax/Errors/resource_id_expected.tjp +8 -0
  528. data/test/TestSuite/Syntax/Errors/rev_acct_no_top.tjp +24 -0
  529. data/test/TestSuite/Syntax/Errors/scenario_exists.tjp +7 -0
  530. data/test/TestSuite/Syntax/Errors/shift_assignment_overlap.tjp +15 -0
  531. data/test/TestSuite/Syntax/Errors/shift_exists.tjp +7 -0
  532. data/test/TestSuite/Syntax/Errors/shift_id_expected.tjp +7 -0
  533. data/test/TestSuite/Syntax/Errors/sloppy_range.tjp +13 -0
  534. data/test/TestSuite/Syntax/Errors/sort_direction.tjp +11 -0
  535. data/test/TestSuite/Syntax/Errors/sort_unknown_scen.tjp +11 -0
  536. data/test/TestSuite/Syntax/Errors/sorting_crit_exptd1.tjp +11 -0
  537. data/test/TestSuite/Syntax/Errors/sorting_crit_exptd2.tjp +11 -0
  538. data/test/TestSuite/Syntax/Errors/sorting_wbs.tjp +11 -0
  539. data/test/TestSuite/Syntax/Errors/start_before_end1.tjp +7 -0
  540. data/test/TestSuite/Syntax/Errors/start_before_end2.tjp +6 -0
  541. data/test/TestSuite/Syntax/Errors/task_complete.tjp +8 -0
  542. data/test/TestSuite/Syntax/Errors/task_exists.tjp +7 -0
  543. data/test/TestSuite/Syntax/Errors/task_priority.tjp +8 -0
  544. data/test/TestSuite/Syntax/Errors/task_without_chargeset.tjp +9 -0
  545. data/test/TestSuite/Syntax/Errors/time_interval.tjp +12 -0
  546. data/test/TestSuite/Syntax/Errors/too_many_bangs.tjp +10 -0
  547. data/test/TestSuite/Syntax/Errors/undecl_flag.tjp +6 -0
  548. data/test/TestSuite/Syntax/Errors/unknown_projectid.tjp +7 -0
  549. data/test/TestSuite/Syntax/Errors/unknown_scenario_id.tjp +6 -0
  550. data/test/TestSuite/Syntax/Errors/unknown_scenario_idx.tjp +11 -0
  551. data/test/TestSuite/Syntax/Errors/unknown_task.tjp +10 -0
  552. data/test/all.rb +31 -0
  553. data/test/test_BatchProcessor.rb +54 -0
  554. data/test/test_CSV-Reports.rb +101 -0
  555. data/test/test_Limits.rb +104 -0
  556. data/test/test_LogicalExpression.rb +110 -0
  557. data/test/test_MacroTable.rb +51 -0
  558. data/test/test_Project.rb +57 -0
  559. data/test/test_PropertySet.rb +71 -0
  560. data/test/test_Query.rb +83 -0
  561. data/test/test_RealFormat.rb +83 -0
  562. data/test/test_RichText.rb +869 -0
  563. data/test/test_Scheduler.rb +42 -0
  564. data/test/test_ShiftAssignments.rb +77 -0
  565. data/test/test_Syntax.rb +41 -0
  566. data/test/test_TextScanner.rb +95 -0
  567. data/test/test_TjTime.rb +114 -0
  568. data/test/test_TjpExample.rb +169 -0
  569. data/test/test_UTF8String.rb +84 -0
  570. data/test/test_WorkingHours.rb +56 -0
  571. metadata +649 -0
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = TextParser/Rule.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 by Chris Schlaeger <cs@kde.org>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of version 2 of the GNU General Public License as
10
+ # published by the Free Software Foundation.
11
+ #
12
+
13
+ class TaskJuggler::TextParser
14
+
15
+ # The TextParserRule holds the basic elment of the syntax description. Each
16
+ # rule has a name and a set of patterns. The parser uses these rules to parse
17
+ # the input files. The first token of a pattern must resolve to a terminal
18
+ # token. The resolution can run transitively over a set of rules. The first
19
+ # tokens of each pattern of a rule must resolve to a terminal symbol and all
20
+ # terminals must be unique in the scope that they appear in. The parser uses
21
+ # this first token to select the next pattern it uses for the syntactical
22
+ # analysis. A rule can be marked as repeatable and/or optional. In this case
23
+ # the syntax element described by the rule may occur 0 or multiple times in
24
+ # the parsed file.
25
+ class Rule
26
+
27
+ attr_reader :name, :patterns, :optional, :repeatable, :keyword, :doc
28
+ attr_accessor :transitions
29
+
30
+ # Create a new syntax rule called +name+.
31
+ def initialize(name)
32
+ @name = name
33
+ @patterns = []
34
+ @repeatable = false
35
+ @optional = false
36
+ @transitions = []
37
+ # In case a rule is optional or any of the patterns is fully optional,
38
+ # this variable is set to true.
39
+ @transitiveOptional = nil
40
+ @keyword = nil
41
+ end
42
+
43
+ # Add a new +pattern+ to the Rule. It should be of type
44
+ # TextParser::Pattern.
45
+ def addPattern(pattern)
46
+ @patterns << pattern
47
+ end
48
+
49
+ # Mark the rule as an optional element of the syntax.
50
+ def setOptional
51
+ @optional = true
52
+ end
53
+
54
+ # Return true if the rule describes optional elements. The evaluation
55
+ # recursively descends into the pattern if necessary and stores the result
56
+ # to be reused for later calls.
57
+ def optional?(rules)
58
+ # If we have a cached result, use this.
59
+ return @transitiveOptional if @transitiveOptional
60
+
61
+ # If the rule is marked optional, then it is optional.
62
+ if @optional
63
+ return @transitiveOptional = true
64
+ end
65
+
66
+ # If all patterns describe optional content, then this rule is optional
67
+ # as well.
68
+ @transitiveOptional = true
69
+ @patterns.each do |pat|
70
+ return @transitiveOptional = false unless pat.optional?(rules)
71
+ end
72
+ end
73
+
74
+ # Mark the syntax element described by this Rule as a repeatable element
75
+ # that can occur once or more times in sequence.
76
+ def setRepeatable
77
+ @repeatable = true
78
+ end
79
+
80
+ # Add a description for the syntax elements of this Rule. +doc+ is a
81
+ # RichText and +keyword+ is a unique name of this Rule. To avoid
82
+ # ambiguouties, an optional scope can be appended, separated by a dot
83
+ # (E.g. name.scope).
84
+ def setDoc(keyword, doc)
85
+ raise 'No pattern defined yet' if @patterns.empty?
86
+ @patterns[-1].setDoc(keyword, doc)
87
+ end
88
+
89
+ # Add a description for a pattern element of the last added pattern.
90
+ def setArg(idx, doc)
91
+ raise 'No pattern defined yet' if @patterns.empty?
92
+ @patterns[-1].setArg(idx, doc)
93
+ end
94
+
95
+ # Specify the index +idx+ of the last token to be used for the syntax
96
+ # documentation. All subsequent tokens will be ignored.
97
+ def setLastSyntaxToken(idx)
98
+ raise 'No pattern defined yet' if @patterns.empty?
99
+ raise 'Token index too large' if idx >= @patterns[-1].tokens.length
100
+ @patterns[-1].setLastSyntaxToken(idx)
101
+ end
102
+
103
+ # Add a reference to another rule for documentation purposes.
104
+ def setSeeAlso(also)
105
+ raise 'No pattern defined yet' if @patterns.empty?
106
+ @patterns[-1].setSeeAlso(also)
107
+ end
108
+
109
+ # Add a reference to a code example. +file+ is the name of the file. +tag+
110
+ # is a tag within the file that specifies a part of this file.
111
+ def setExample(file, tag)
112
+ @patterns[-1].setExample(file, tag)
113
+ end
114
+
115
+ # Return a reference the pattern of this Rule.
116
+ def pattern(idx)
117
+ @patterns[idx]
118
+ end
119
+
120
+ # Return the pattern of this rule that matches the given +token+. If no
121
+ # pattern matches, return nil.
122
+ def matchingPatternIndex(token)
123
+ @transitions.length.times do |i|
124
+ return i if @transitions[i].has_key?(token)
125
+ end
126
+
127
+ nil
128
+ end
129
+
130
+ def to_syntax(stack, docs, rules, skip)
131
+ str = ''
132
+ str << '[' if @optional || @repeatable
133
+ str << '(' if @patterns.length > 1
134
+ first = true
135
+ pStr = ''
136
+ @patterns.each do |pat|
137
+ if first
138
+ first = false
139
+ else
140
+ pStr << ' | '
141
+ end
142
+ pStr << pat.to_syntax_r(stack, docs, rules, skip)
143
+ end
144
+ return '' if pStr == ''
145
+ str << pStr
146
+ str << '...' if @repeatable
147
+ str << ')' if @patterns.length > 1
148
+ str << ']' if @optional || @repeatable
149
+ str
150
+ end
151
+
152
+ def dump
153
+ puts "Rule: #{name} #{@optional ? "[optional]" : ""} " +
154
+ "#{@repeatable ? "[repeatable]" : ""}"
155
+ @patterns.length.times do |i|
156
+ puts " Pattern: \"#{@patterns[i]}\""
157
+ @transitions[i].each do |key, rule|
158
+ if key[0] == ?_
159
+ token = "\"" + key.slice(1, key.length - 1) + "\""
160
+ else
161
+ token = key.slice(1, key.length - 1)
162
+ end
163
+ puts " #{token} -> #{rule.name}"
164
+ end
165
+ end
166
+ puts
167
+ end
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = TextParser/StackElement.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 by Chris Schlaeger <cs@kde.org>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of version 2 of the GNU General Public License as
10
+ # published by the Free Software Foundation.
11
+ #
12
+
13
+ class TaskJuggler::TextParser
14
+
15
+ # This class models the elements of the stack that the TextParser uses to keep
16
+ # track of its state. It stores the current TextParserRule, the current
17
+ # pattern position and the TextScanner position at the start of processing. It
18
+ # also store the function that must be called to store the collected values.
19
+ class StackElement
20
+
21
+ attr_reader :val, :rule, :function, :sourceFileInfo
22
+
23
+ # Create a new stack element. _rule_ is the TextParserRule that triggered
24
+ # the creation of this element. _function_ is the function that will be
25
+ # called at the end to store the collected data. _sourceFileInfo_ is a
26
+ # SourceFileInfo reference that describes the TextScanner position when the
27
+ # rule was entered.
28
+ def initialize(rule, function, sourceFileInfo)
29
+ # This Array stores the collected values.
30
+ @val = []
31
+ @position = 0
32
+ @rule = rule
33
+ @function = function
34
+ @sourceFileInfo = sourceFileInfo
35
+ end
36
+
37
+ # Store a collected value and move the position to the next pattern.
38
+ def store(val)
39
+ @val[@position] = val
40
+ @position += 1
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = ParserTokenDoc.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 by Chris Schlaeger <cs@kde.org>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of version 2 of the GNU General Public License as
10
+ # published by the Free Software Foundation.
11
+ #
12
+
13
+ class TaskJuggler::TextParser
14
+
15
+ # Utility class to store a name and a textual description of the meaning of a
16
+ # token used by the parser syntax tree. A specification of the variable type
17
+ # and a reference to a specific pattern are optional.
18
+ class TokenDoc
19
+
20
+ attr_reader :text
21
+ attr_accessor :name, :typeSpec, :pattern
22
+
23
+ # Construct a ParserTokenDoc object. _name_ and _text_ are Strings that
24
+ # hold the name and textual description of the parser token.
25
+ def initialize(name, arg)
26
+ @name = name
27
+ if arg.is_a?(String)
28
+ @text = arg
29
+ else
30
+ @pattern = arg
31
+ end
32
+ @typeSpec = nil
33
+ @pattern = nil
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,682 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = TextScanner.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009 by Chris Schlaeger <cs@kde.org>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of version 2 of the GNU General Public License as
10
+ # published by the Free Software Foundation.
11
+ #
12
+
13
+ require 'UTF8String'
14
+ require 'TjTime'
15
+ require 'TjException'
16
+ require 'SourceFileInfo'
17
+ require 'MacroTable'
18
+ require 'MacroParser'
19
+ require 'Log'
20
+
21
+ class TaskJuggler
22
+
23
+ # The TextScanner class can scan text files and chop then into tokens to be
24
+ # used by a parser. Files can be nested. A file can include an other file.
25
+ class TextScanner
26
+
27
+ # This class is used to handle the low-level input operations. It knows
28
+ # whether it deals with a text buffer or a file and abstracts this to the
29
+ # TextScanner. For each nested file the scanner puts an StreamHandle on the
30
+ # stack while the file is scanned. With this stack the scanner can resume
31
+ # the processing of the enclosing file once the included files has been
32
+ # completely processed.
33
+ class StreamHandle
34
+
35
+ attr_accessor :lineNo, :columnNo, :line, :charBuffer
36
+ attr_reader :fileName
37
+
38
+ def initialize
39
+ @lineNo = 1
40
+ @columnNo = 1
41
+ @line = ""
42
+ @charBuffer = []
43
+ @fileName = nil
44
+ end
45
+
46
+ def dirname
47
+ @fileName ? File.dirname(@fileName) : ''
48
+ end
49
+
50
+ end
51
+
52
+ # Specialized version of StreamHandle for operations on files.
53
+ class FileStreamHandle < StreamHandle
54
+
55
+ attr_reader :fileName
56
+
57
+ def initialize(fileName)
58
+ super()
59
+ @fileName = fileName
60
+ @file = File.new(fileName, 'r')
61
+ @bytes = 0
62
+ Log << "Parsing file #{@fileName} ..."
63
+ Log.startProgressMeter("Reading file #{fileName}")
64
+
65
+ end
66
+
67
+ def close
68
+ @file.close
69
+ end
70
+
71
+ def getc19
72
+ Log.activity if @bytes & 0x3FFF == 0
73
+ @bytes += 1
74
+ @file.getc
75
+ end
76
+
77
+ def getc18
78
+ Log.activity if @bytes & 0x3FFF == 0
79
+ @bytes += 1
80
+ c = @file.getc
81
+ return nil if c.nil?
82
+ '' << c
83
+ end
84
+
85
+ if RUBY_VERSION < '1.9.0'
86
+ alias getc getc18
87
+ else
88
+ alias getc getc19
89
+ end
90
+
91
+ end
92
+
93
+ # Specialized version of StreamHandle for operations on Strings.
94
+ class BufferStreamHandle < StreamHandle
95
+
96
+ def initialize(buffer)
97
+ super()
98
+ @buffer = buffer
99
+ @length = @buffer.length_utf8
100
+ @pos = 0
101
+ Log << "Parsing buffer #{@buffer[0, 20]} ..."
102
+ end
103
+
104
+ def close
105
+ @buffer = nil
106
+ end
107
+
108
+ def getc18
109
+ return nil if @pos >= @length
110
+
111
+ c = @buffer[@pos]
112
+ @pos += 1
113
+ '' << c
114
+ end
115
+
116
+ def getc19
117
+ return nil if @pos >= @length
118
+
119
+ c = @buffer[@pos]
120
+ @pos += 1
121
+ c
122
+ end
123
+
124
+ if RUBY_VERSION < '1.9.0'
125
+ alias getc getc18
126
+ else
127
+ alias getc getc19
128
+ end
129
+
130
+ def fileName
131
+ ''
132
+ end
133
+ end
134
+
135
+ # Create a new instance of TextScanner. _masterFile_ must be a String that
136
+ # either contains the name of the file to start with or the text itself.
137
+ # _messageHandler_ is a MessageHandler that is used for error messages.
138
+ def initialize(masterFile, messageHandler)
139
+ @masterFile = masterFile
140
+ @messageHandler = messageHandler
141
+ # This table contains all macros that may be expanded when found in the
142
+ # text.
143
+ @macroTable = MacroTable.new(messageHandler)
144
+ # This Array stores the currently processed nested files. It's an Array
145
+ # of Arrays. The nested Array consists of 3 elements, the @cf,
146
+ # @tokenBuffer and the @pos of the file.
147
+ @fileStack = []
148
+ # This Array stores the currently processed nested macros.
149
+ @macroStack = []
150
+ # In certain situation we want to ignore Macro replacement and this flag
151
+ # is set to true.
152
+ @ignoreMacros = false
153
+ end
154
+
155
+ # Start the processing. if _fileNameIsBuffer_ is true, we operate on a
156
+ # String, else on a File.
157
+ def open(fileNameIsBuffer = false)
158
+ if fileNameIsBuffer
159
+ @fileStack = [ [ @cf = BufferStreamHandle.new(@masterFile), nil, nil ] ]
160
+ else
161
+ begin
162
+ @fileStack = [ [ @cf = FileStreamHandle.new(@masterFile), nil, nil ] ]
163
+ rescue StandardError
164
+ raise TjException.new, "Cannot open file #{@masterFile}"
165
+ end
166
+ end
167
+ @masterPath = @cf.dirname + '/'
168
+ @tokenBuffer = @pos = nil
169
+ end
170
+
171
+ # Finish processing and reset all data structures.
172
+ def close
173
+ Log.startProgressMeter("Reading file #{@masterFile}")
174
+ Log.stopProgressMeter
175
+ @fileStack = []
176
+ @cf = @tokenBuffer = @pos = nil
177
+ end
178
+
179
+ # Continue processing with a new file specified by _fileName_. When this
180
+ # file is finished, we will continue in the old file after the location
181
+ # where we started with the new file.
182
+ def include(fileName)
183
+ begin
184
+ if @fileStack.empty?
185
+ path = @masterPath
186
+ else
187
+ path = @fileStack.last[0].dirname + '/'
188
+ @fileStack.last[1, 2] = [ @tokenBuffer, @pos ]
189
+ end
190
+ if fileName[0] != '/'
191
+ # If the included file is not an absolute name, we interpret the file
192
+ # name relative to the including file.
193
+ fileName = path + fileName
194
+ end
195
+
196
+ @tokenBuffer = @pos = nil
197
+ @fileStack << [ (@cf = FileStreamHandle.new(fileName)), nil, nil ]
198
+ rescue StandardError
199
+ error('bad_include', "Cannot open include file #{fileName}")
200
+ end
201
+ end
202
+
203
+ # Return SourceFileInfo for the current processing prosition.
204
+ def sourceFileInfo
205
+ @pos ? @pos.clone : SourceFileInfo.new(fileName, lineNo, columnNo)
206
+ end
207
+
208
+ # Return the name of the currently processed file. If we are working on a
209
+ # text buffer, the text will be returned.
210
+ def fileName
211
+ @cf ? @cf.fileName : @masterFile
212
+ end
213
+
214
+ def lineNo # :nodoc:
215
+ @cf ? @cf.lineNo : 0
216
+ end
217
+
218
+ def columnNo # :nodoc:
219
+ @cf ? @cf.columnNo : 0
220
+ end
221
+
222
+ def line # :nodoc:
223
+ @cf ? @cf.line : 0
224
+ end
225
+
226
+ # Scan for the next token in the input stream and return it. The result will
227
+ # be an Array of the form [ TokenType, TokenValue ].
228
+ def nextToken
229
+ # If we have a pushed-back token, return that first.
230
+ unless @tokenBuffer.nil?
231
+ res = @tokenBuffer
232
+ @tokenBuffer = @pos = nil
233
+ return res
234
+ end
235
+
236
+ # Start processing characters from the input.
237
+ token = [ '.', '<END>' ]
238
+ while c = nextChar
239
+ case c
240
+ when ' ', "\n", "\t"
241
+ if (tok = readBlanks(c))
242
+ token = tok
243
+ break
244
+ end
245
+ when '#'
246
+ skipComment
247
+ when '/'
248
+ skipCPlusPlusComments
249
+ when '0'..'9'
250
+ token = readNumber(c)
251
+ break
252
+ when "'"
253
+ token = readString(c)
254
+ break
255
+ when '"'
256
+ token = readString(c)
257
+ break
258
+ when '!'
259
+ token = readRelativeId(c)
260
+ break
261
+ when 'a'..'z', 'A'..'Z', '_'
262
+ token = readId(c)
263
+ break
264
+ when '['
265
+ token = readMacro
266
+ break
267
+ when nil
268
+ # We've reached an end of file or buffer
269
+ break
270
+ else
271
+ str = ""
272
+ str << c
273
+ token = [ 'LITERAL', str ]
274
+ break
275
+ end
276
+ end
277
+ @lastPos = @pos
278
+ @pos = SourceFileInfo.new(fileName, lineNo, columnNo)
279
+ return token
280
+ end
281
+
282
+ # Return a token to retrieve it with the next nextToken() call again. Only 1
283
+ # token can be returned before the next nextToken() call.
284
+ def returnToken(token)
285
+ unless @tokenBuffer.nil?
286
+ $stderr.puts @tokenBuffer
287
+ raise "Fatal Error: Cannot return more than 1 token in a row"
288
+ end
289
+ @tokenBuffer = token
290
+ @pos = @lastPos
291
+ end
292
+
293
+ # Add a Macro to the macro translation table.
294
+ def addMacro(macro)
295
+ @macroTable.add(macro)
296
+ end
297
+
298
+ # Return true if the Macro _name_ has been added already.
299
+ def macroDefined?(name)
300
+ @macroTable.include?(name)
301
+ end
302
+
303
+ def expandMacro(args)
304
+ macro, text = @macroTable.resolve(args, sourceFileInfo)
305
+ return if text == ''
306
+
307
+ @macroStack << [ macro, args ]
308
+ # Mark end of macro with a 0 element
309
+ @cf.charBuffer << 0
310
+ text.reverse.each_utf8_char do |c|
311
+ @cf.charBuffer << c
312
+ end
313
+ @cf.line = ''
314
+ end
315
+
316
+ # Call this function to report any errors related to the parsed input.
317
+ def error(id, text, property = nil)
318
+ message = Message.new(id, 'error', text + "\n" + line.to_s,
319
+ property, nil, sourceFileInfo)
320
+ @messageHandler.send(message)
321
+
322
+ until @macroStack.empty?
323
+ macro, args = @macroStack.pop
324
+ args.collect! { |a| '"' + a + '"' }
325
+ message = Message.new('macro_stack', 'info',
326
+ " #{macro.name} #{args.join(' ')}", nil, nil,
327
+ macro.sourceFileInfo)
328
+ @messageHandler.send(message)
329
+ end
330
+
331
+ raise TjException.new, 'Syntax error during parse'
332
+ end
333
+
334
+ private
335
+
336
+ # This function is called by the scanner to get the next character. It
337
+ # features a FIFO buffer that can hold any amount of returned characters.
338
+ # When it has reached the end of the master file it returns nil.
339
+ def nextChar
340
+ if (c = nextCharI) == '$' && !@ignoreMacros
341
+ # Double $ are reduced to a single $.
342
+ return c if (c = nextCharI) == '$'
343
+
344
+ # Macros start with $( or ${. All other $. are ignored.
345
+ if c != '(' && c != '{'
346
+ returnChar(c)
347
+ return '$'
348
+ end
349
+
350
+ @ignoreMacros = true
351
+ returnChar(c)
352
+ macroParser = MacroParser.new(self, @messageHandler)
353
+ begin
354
+ macroParser.parse('macroCall', false)
355
+ rescue TjException
356
+ end
357
+ @ignoreMacros = false
358
+ return nextCharI
359
+ else
360
+ return c
361
+ end
362
+ end
363
+
364
+ def nextCharI
365
+ # This can only happen when a previous call already returned nil.
366
+ return nil if @cf.nil?
367
+
368
+ c = nil
369
+ # If there are characters in the return buffer process them first.
370
+ # Otherwise get next character from input stream.
371
+ unless @cf.charBuffer.empty?
372
+ c = @cf.charBuffer.pop
373
+ @cf.lineNo -= 1 if c == "\n" && !@macroStack.empty?
374
+ while !@cf.charBuffer.empty? && @cf.charBuffer[-1] == 0
375
+ @cf.charBuffer.pop
376
+ @macroStack.pop
377
+ end
378
+ else
379
+ # If EOF has been reached, try the parent file until even the master
380
+ # file has been processed completely.
381
+ if (c = @cf.getc).nil?
382
+ @cf.close
383
+ @fileStack.pop
384
+ if @fileStack.empty?
385
+ # We are done with the top-level file now.
386
+ @cf = @tokenBuffer = @pos = nil
387
+ else
388
+ @cf, @tokenBuffer, @pos = @fileStack.last
389
+ Log << "Parsing file #{@cf.fileName} ..."
390
+ # We have been called by nextToken() already, so we can't just
391
+ # restore @tokenBuffer and be done. We need to feed the token text
392
+ # back into the charBuffer and return the first character.
393
+ if @tokenBuffer
394
+ @tokenBuffer[1].reverse.each_utf8_char do |ch|
395
+ @cf.charBuffer.push(ch)
396
+ end
397
+ @tokenBuffer = nil
398
+ end
399
+ end
400
+ return nil
401
+ end
402
+ end
403
+ unless c.nil?
404
+ @cf.lineNo += 1 if c == "\n"
405
+ @cf.line = "" if @cf.line[-1] == ?\n
406
+ @cf.line << c
407
+ end
408
+ c
409
+ end
410
+
411
+ def returnChar(c)
412
+ return if @cf.nil?
413
+
414
+ @cf.line.chop! if c
415
+ @cf.charBuffer << c
416
+ @cf.lineNo -= 1 if c == "\n" && @macroStack.empty?
417
+ end
418
+
419
+ def skipComment
420
+ # Read all characters until line or file end is found
421
+ @ignoreMacros = true
422
+ while (c = nextChar) && c != "\n"
423
+ end
424
+ @ignoreMacros = false
425
+ returnChar(c)
426
+ end
427
+
428
+ def skipCPlusPlusComments
429
+ if (c = nextChar) == '*'
430
+ # /* */ style multi-line comment
431
+ @ignoreMacros = true
432
+ begin
433
+ while (c = nextChar) != '*'
434
+ end
435
+ end until (c = nextChar) == '/'
436
+ @ignoreMacros = false
437
+ elsif c == '/'
438
+ # // style single line comment
439
+ skipComment
440
+ else
441
+ error('bad_comment', "'/' or '*' expected after start of comment")
442
+ end
443
+ end
444
+
445
+ def readBlanks(c)
446
+ loop do
447
+ if c == ' '
448
+ if (c2 = nextChar) == '-'
449
+ # Special case for the dash between period dates. It must be
450
+ # surrounded by blanks.
451
+ if (c3 = nextChar) == ' '
452
+ return [ 'LITERAL', ' - ']
453
+ end
454
+ returnChar(c3)
455
+ end
456
+ returnChar(c2)
457
+ elsif c != "\n" && c != "\t"
458
+ returnChar(c)
459
+ return nil
460
+ end
461
+ c = nextChar
462
+ end
463
+ end
464
+
465
+ def readNumber(c)
466
+ token = ""
467
+ token << c
468
+ while ('0'..'9') === (c = nextChar)
469
+ token << c
470
+ end
471
+ if c == '-'
472
+ return readDate(token)
473
+ elsif c == '.'
474
+ frac = readDigits
475
+
476
+ return [ 'FLOAT', token.to_f + frac.to_f / (10.0 ** frac.length) ]
477
+ elsif c == ':'
478
+ hours = token.to_i
479
+ mins = readDigits.to_i
480
+ if hours < 0 || hours > 24
481
+ raise TjException.new, "Hour must be between 0 and 23"
482
+ end
483
+ if mins < 0 || mins > 59
484
+ raise TjException.new, "Minutes must be between 0 and 59"
485
+ end
486
+ if hours == 24 && mins != 0
487
+ raise TjException.new, "Time may not be larger than 24:00"
488
+ end
489
+
490
+ # Return time as seconds of day since midnight.
491
+ return [ 'TIME', hours * 60 * 60 + mins * 60 ]
492
+ else
493
+ returnChar(c)
494
+ end
495
+
496
+ [ 'INTEGER', token.to_i ]
497
+ end
498
+
499
+ def readRelativeId(c)
500
+ token = ""
501
+ token << c
502
+ while (c = nextChar) && c == '!'
503
+ token << c
504
+ end
505
+ unless ('a'..'z') === c || ('A'..'Z') === c || c == '_'
506
+ raise TjException.new, "Identifier expected"
507
+ end
508
+ id = readId(c)
509
+ id[0] = 'RELATIVE_ID'
510
+ id[1] = token + id[1]
511
+ id
512
+ end
513
+
514
+ def readDate(token)
515
+ year = token.to_i
516
+ if year < 1970 || year > 2030
517
+ raise TjException.new, "Year must be between 1970 and 2030"
518
+ end
519
+
520
+ month = readDigits.to_i
521
+ if month < 1 || month > 12
522
+ raise TjException.new, "Month must be between 1 and 12"
523
+ end
524
+ if nextChar != '-'
525
+ raise TjException.new, "Corrupted date"
526
+ end
527
+
528
+ day = readDigits.to_i
529
+ if day < 1 || day > 31
530
+ raise TjException.new, "Day must be between 1 and 31"
531
+ end
532
+
533
+ if (c = nextChar) != '-'
534
+ returnChar(c)
535
+ return [ 'DATE', TjTime.local(year, month, day) ]
536
+ end
537
+
538
+ hour = readDigits.to_i
539
+ if hour < 0 || hour > 23
540
+ raise TjException.new, "Hour must be between 0 and 23"
541
+ end
542
+
543
+ if nextChar != ':'
544
+ raise TjException.new, "Corrupted time. ':' expected."
545
+ end
546
+
547
+ minutes = readDigits.to_i
548
+ if minutes < 0 || minutes > 59
549
+ raise TjException.new, "Minutes must be between 0 and 59"
550
+ end
551
+
552
+ if (c = nextChar) == ':'
553
+ seconds = readDigits.to_i
554
+ if seconds < 0 || seconds > 59
555
+ raise TjException.new, "Seconds must be between 0 and 59"
556
+ end
557
+ else
558
+ seconds = 0
559
+ returnChar(c)
560
+ end
561
+
562
+ if (c = nextChar) != '-'
563
+ returnChar(c)
564
+ return [ 'DATE', TjTime.local(year, month, day, hour, minutes, seconds) ]
565
+ end
566
+
567
+ if (c = nextChar) == '-'
568
+ delta = 1
569
+ elsif c == '+'
570
+ delta = -1
571
+ else
572
+ # An actual time zone name
573
+ tz = readId(c)[1]
574
+ oldTz = ENV['TZ']
575
+ ENV['TZ'] = tz
576
+ timeVal = TjTime.local(year, month, day, hour, minutes, seconds)
577
+ ENV['TZ'] = oldTz
578
+ if timeVal.to_a[9] != tz
579
+ raise TjException.new, "Unknown time zone #{tz}"
580
+ end
581
+ return [ 'DATE', timeVal ]
582
+ end
583
+
584
+ utcDiff = readDigits
585
+ utcHour = utcDiff[0, 2].to_i
586
+ if utcHour < 0 || utcHour > 23
587
+ raise TjException.new, "Hour must be between 0 and 23"
588
+ end
589
+ utcMin = utcDiff[2, 2].to_i
590
+ if utcMin < 0 || utcMin > 59
591
+ raise TjException.new, "Minutes must be between 0 and 59"
592
+ end
593
+
594
+ [ 'DATE', TjTime.gm(year, month, day, hour, minutes, seconds) +
595
+ delta * ((utcHour * 3600) + utcMin * 60) ]
596
+ end
597
+
598
+ def readString(terminator)
599
+ token = ""
600
+ while (c = nextChar) && c != terminator
601
+ if c == "\\"
602
+ # Terminators can be used as regular characters when prefixed by a \.
603
+ if (c = nextChar) && c != terminator
604
+ # \ followed by non-terminator. Just add both.
605
+ token << "\\"
606
+ end
607
+ end
608
+ token << c
609
+ end
610
+
611
+ [ 'STRING', token ]
612
+ end
613
+
614
+ def readId(c)
615
+ token = ""
616
+ token << c
617
+ while (c = nextChar) &&
618
+ (('a'..'z') === c || ('A'..'Z') === c || ('0'..'9') === c ||
619
+ c == '_')
620
+ token << c
621
+ end
622
+ if c == ':'
623
+ return [ 'ID_WITH_COLON', token ]
624
+ elsif c == '.'
625
+ token << c
626
+ loop do
627
+ token += readIdentifier
628
+ break if (c = nextChar) != '.'
629
+ token += '.'
630
+ end
631
+ returnChar c
632
+
633
+ return [ 'ABSOLUTE_ID', token ]
634
+ else
635
+ returnChar c
636
+ return [ 'ID', token ]
637
+ end
638
+ end
639
+
640
+ def readMacro
641
+ token = ''
642
+ while (c = nextCharI) != ']'
643
+ error('unterminated_macro', "Unterminated macro #{token}") unless c
644
+ token << c
645
+ end
646
+ return [ 'MACRO', token ]
647
+ end
648
+
649
+ # Read only decimal digits and return the result als Fixnum.
650
+ def readDigits
651
+ token = ""
652
+ while ('0'..'9') === (c = nextChar)
653
+ token << c
654
+ end
655
+ # Make sure that we have read at least one digit.
656
+ if token == ""
657
+ raise TjException.new, "Digit (0 - 9) expected"
658
+ end
659
+ # Push back the non-digit that terminated the digits.
660
+ returnChar(c)
661
+ token
662
+ end
663
+
664
+ def readIdentifier(noDigit = true)
665
+ token = ""
666
+ while (c = nextChar) &&
667
+ (('a'..'z') === c || ('A'..'Z') === c ||
668
+ (!noDigit && (('0'..'9') === c)) || c == '_')
669
+ token << c
670
+ noDigit = false
671
+ end
672
+ returnChar(c)
673
+ if token == ""
674
+ raise TjException.new, "Identifier expected"
675
+ end
676
+ token
677
+ end
678
+
679
+ end
680
+
681
+ end
682
+