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.
- data/COPYING +280 -0
- data/README +31 -0
- data/Rakefile +20 -0
- data/benchmarks/UTF-8-Strings.rb +58 -0
- data/benchmarks/allocate.tjp +30 -0
- data/benchmarks/booking.tjp +62 -0
- data/benchmarks/depends.tjp +112 -0
- data/benchmarks/htmltaskreport.tjp +45 -0
- data/benchmarks/runbench.rb +24 -0
- data/bin/tj3 +3 -0
- data/bin/tj3man +3 -0
- data/doc/classes/AppConfig.html +808 -0
- data/doc/classes/Arguments.html +226 -0
- data/doc/classes/String.html +395 -0
- data/doc/classes/TaskJuggler.html +1358 -0
- data/doc/classes/TaskJuggler/Account.html +257 -0
- data/doc/classes/TaskJuggler/AccountScenario.html +218 -0
- data/doc/classes/TaskJuggler/Allocation.html +419 -0
- data/doc/classes/TaskJuggler/AllocationAttribute.html +291 -0
- data/doc/classes/TaskJuggler/AttributeBase.html +608 -0
- data/doc/classes/TaskJuggler/AttributeDefinition.html +259 -0
- data/doc/classes/TaskJuggler/Booking.html +307 -0
- data/doc/classes/TaskJuggler/BookingListAttribute.html +263 -0
- data/doc/classes/TaskJuggler/BooleanAttribute.html +261 -0
- data/doc/classes/TaskJuggler/CSVFile.html +325 -0
- data/doc/classes/TaskJuggler/Charge.html +279 -0
- data/doc/classes/TaskJuggler/ChargeListAttribute.html +229 -0
- data/doc/classes/TaskJuggler/ChargeSet.html +440 -0
- data/doc/classes/TaskJuggler/ChargeSetListAttribute.html +276 -0
- data/doc/classes/TaskJuggler/ColumnTable.html +260 -0
- data/doc/classes/TaskJuggler/DateAttribute.html +194 -0
- data/doc/classes/TaskJuggler/DependencyListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/DurationAttribute.html +229 -0
- data/doc/classes/TaskJuggler/FixnumAttribute.html +194 -0
- data/doc/classes/TaskJuggler/FlagListAttribute.html +263 -0
- data/doc/classes/TaskJuggler/FloatAttribute.html +229 -0
- data/doc/classes/TaskJuggler/GanttChart.html +667 -0
- data/doc/classes/TaskJuggler/GanttContainer.html +441 -0
- data/doc/classes/TaskJuggler/GanttHeader.html +280 -0
- data/doc/classes/TaskJuggler/GanttHeaderScaleItem.html +245 -0
- data/doc/classes/TaskJuggler/GanttLine.html +398 -0
- data/doc/classes/TaskJuggler/GanttLoadStack.html +327 -0
- data/doc/classes/TaskJuggler/GanttMilestone.html +415 -0
- data/doc/classes/TaskJuggler/GanttRouter.html +425 -0
- data/doc/classes/TaskJuggler/GanttTaskBar.html +429 -0
- data/doc/classes/TaskJuggler/HTMLDocument.html +240 -0
- data/doc/classes/TaskJuggler/HTMLGraphics.html +231 -0
- data/doc/classes/TaskJuggler/Interval.html +552 -0
- data/doc/classes/TaskJuggler/IntervalListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/KeywordDocumentation.html +796 -0
- data/doc/classes/TaskJuggler/Limits.html +416 -0
- data/doc/classes/TaskJuggler/Limits/Limit.html +381 -0
- data/doc/classes/TaskJuggler/LimitsAttribute.html +261 -0
- data/doc/classes/TaskJuggler/Log.html +613 -0
- data/doc/classes/TaskJuggler/LogicalAttribute.html +226 -0
- data/doc/classes/TaskJuggler/LogicalExpression.html +251 -0
- data/doc/classes/TaskJuggler/LogicalFlag.html +229 -0
- data/doc/classes/TaskJuggler/LogicalFunction.html +324 -0
- data/doc/classes/TaskJuggler/LogicalOperation.html +299 -0
- data/doc/classes/TaskJuggler/Macro.html +194 -0
- data/doc/classes/TaskJuggler/MacroParser.html +360 -0
- data/doc/classes/TaskJuggler/MacroTable.html +366 -0
- data/doc/classes/TaskJuggler/Message.html +281 -0
- data/doc/classes/TaskJuggler/MessageHandler.html +215 -0
- data/doc/classes/TaskJuggler/Project.html +1606 -0
- data/doc/classes/TaskJuggler/ProjectFileParser.html +412 -0
- data/doc/classes/TaskJuggler/PropertyList.html +597 -0
- data/doc/classes/TaskJuggler/PropertySet.html +1200 -0
- data/doc/classes/TaskJuggler/PropertyTreeNode.html +1449 -0
- data/doc/classes/TaskJuggler/Query.html +600 -0
- data/doc/classes/TaskJuggler/RealFormat.html +252 -0
- data/doc/classes/TaskJuggler/ReferenceAttribute.html +194 -0
- data/doc/classes/TaskJuggler/Report.html +528 -0
- data/doc/classes/TaskJuggler/ReportElement.html +1070 -0
- data/doc/classes/TaskJuggler/ReportTable.html +497 -0
- data/doc/classes/TaskJuggler/ReportTableCell.html +518 -0
- data/doc/classes/TaskJuggler/ReportTableColumn.html +364 -0
- data/doc/classes/TaskJuggler/ReportTableElement.html +644 -0
- data/doc/classes/TaskJuggler/ReportTableLegend.html +343 -0
- data/doc/classes/TaskJuggler/ReportTableLine.html +431 -0
- data/doc/classes/TaskJuggler/Resource.html +211 -0
- data/doc/classes/TaskJuggler/ResourceListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/ResourceListRE.html +249 -0
- data/doc/classes/TaskJuggler/ResourceScenario.html +1137 -0
- data/doc/classes/TaskJuggler/RichText.html +537 -0
- data/doc/classes/TaskJuggler/RichTextAttribute.html +229 -0
- data/doc/classes/TaskJuggler/RichTextDocument.html +418 -0
- data/doc/classes/TaskJuggler/RichTextElement.html +829 -0
- data/doc/classes/TaskJuggler/RichTextException.html +212 -0
- data/doc/classes/TaskJuggler/RichTextParser.html +317 -0
- data/doc/classes/TaskJuggler/RichTextProtocolExample.html +303 -0
- data/doc/classes/TaskJuggler/RichTextProtocolHandler.html +194 -0
- data/doc/classes/TaskJuggler/RichTextScanner.html +561 -0
- data/doc/classes/TaskJuggler/RichTextSnip.html +364 -0
- data/doc/classes/TaskJuggler/RichTextSyntaxRules.html +883 -0
- data/doc/classes/TaskJuggler/Scenario.html +163 -0
- data/doc/classes/TaskJuggler/ScenarioData.html +354 -0
- data/doc/classes/TaskJuggler/Scoreboard.html +638 -0
- data/doc/classes/TaskJuggler/Shift.html +255 -0
- data/doc/classes/TaskJuggler/ShiftAssignment.html +488 -0
- data/doc/classes/TaskJuggler/ShiftAssignments.html +715 -0
- data/doc/classes/TaskJuggler/ShiftAssignmentsAttribute.html +261 -0
- data/doc/classes/TaskJuggler/ShiftScenario.html +282 -0
- data/doc/classes/TaskJuggler/SourceFileInfo.html +247 -0
- data/doc/classes/TaskJuggler/StringAttribute.html +229 -0
- data/doc/classes/TaskJuggler/SymbolAttribute.html +194 -0
- data/doc/classes/TaskJuggler/SyntaxReference.html +516 -0
- data/doc/classes/TaskJuggler/TOCEntry.html +242 -0
- data/doc/classes/TaskJuggler/TableColumnDefinition.html +273 -0
- data/doc/classes/TaskJuggler/TableOfContents.html +256 -0
- data/doc/classes/TaskJuggler/Task.html +203 -0
- data/doc/classes/TaskJuggler/TaskDependency.html +251 -0
- data/doc/classes/TaskJuggler/TaskListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/TaskListRE.html +250 -0
- data/doc/classes/TaskJuggler/TaskScenario.html +2206 -0
- data/doc/classes/TaskJuggler/TextParser.html +670 -0
- data/doc/classes/TaskJuggler/TextParser/Pattern.html +923 -0
- data/doc/classes/TaskJuggler/TextParser/Rule.html +779 -0
- data/doc/classes/TaskJuggler/TextParser/StackElement.html +267 -0
- data/doc/classes/TaskJuggler/TextParser/TextParserResultArray.html +212 -0
- data/doc/classes/TaskJuggler/TextParser/TokenDoc.html +221 -0
- data/doc/classes/TaskJuggler/TextScanner.html +708 -0
- data/doc/classes/TaskJuggler/TextScanner/BufferStreamHandle.html +355 -0
- data/doc/classes/TaskJuggler/TextScanner/FileStreamHandle.html +341 -0
- data/doc/classes/TaskJuggler/TextScanner/StreamHandle.html +260 -0
- data/doc/classes/TaskJuggler/TjException.html +185 -0
- data/doc/classes/TaskJuggler/TjTime.html +1845 -0
- data/doc/classes/TaskJuggler/TjpExample.html +310 -0
- data/doc/classes/TaskJuggler/TjpExportRE.html +329 -0
- data/doc/classes/TaskJuggler/TjpSyntaxRules.html +8928 -0
- data/doc/classes/TaskJuggler/UserManual.html +606 -0
- data/doc/classes/TaskJuggler/WorkingHours.html +582 -0
- data/doc/classes/TaskJuggler/WorkingHoursAttribute.html +284 -0
- data/doc/classes/TaskJuggler/XMLBlob.html +207 -0
- data/doc/classes/TaskJuggler/XMLComment.html +206 -0
- data/doc/classes/TaskJuggler/XMLDocument.html +293 -0
- data/doc/classes/TaskJuggler/XMLElement.html +341 -0
- data/doc/classes/TaskJuggler/XMLNamedText.html +174 -0
- data/doc/classes/TaskJuggler/XMLText.html +221 -0
- data/doc/files/COPYING.html +448 -0
- data/doc/files/README.html +134 -0
- data/doc/files/lib/AccountScenario_rb.html +116 -0
- data/doc/files/lib/Account_rb.html +118 -0
- data/doc/files/lib/Allocation_rb.html +118 -0
- data/doc/files/lib/AppConfig_rb.html +116 -0
- data/doc/files/lib/AttributeBase_rb.html +106 -0
- data/doc/files/lib/AttributeDefinition_rb.html +106 -0
- data/doc/files/lib/Attributes_rb.html +130 -0
- data/doc/files/lib/Booking_rb.html +106 -0
- data/doc/files/lib/ChargeSet_rb.html +116 -0
- data/doc/files/lib/Charge_rb.html +116 -0
- data/doc/files/lib/HTMLDocument_rb.html +116 -0
- data/doc/files/lib/Interval_rb.html +116 -0
- data/doc/files/lib/KeywordDocumentation_rb.html +122 -0
- data/doc/files/lib/Limits_rb.html +116 -0
- data/doc/files/lib/Log_rb.html +116 -0
- data/doc/files/lib/LogicalExpression_rb.html +122 -0
- data/doc/files/lib/LogicalFlag_rb.html +116 -0
- data/doc/files/lib/LogicalFunction_rb.html +116 -0
- data/doc/files/lib/LogicalOperation_rb.html +116 -0
- data/doc/files/lib/MacroParser_rb.html +118 -0
- data/doc/files/lib/MacroTable_rb.html +122 -0
- data/doc/files/lib/MessageHandler_rb.html +106 -0
- data/doc/files/lib/Message_rb.html +116 -0
- data/doc/files/lib/ProjectFileParser_rb.html +122 -0
- data/doc/files/lib/Project_rb.html +148 -0
- data/doc/files/lib/PropertyList_rb.html +106 -0
- data/doc/files/lib/PropertySet_rb.html +118 -0
- data/doc/files/lib/PropertyTreeNode_rb.html +106 -0
- data/doc/files/lib/Query_rb.html +116 -0
- data/doc/files/lib/RealFormat_rb.html +106 -0
- data/doc/files/lib/ResourceScenario_rb.html +116 -0
- data/doc/files/lib/Resource_rb.html +118 -0
- data/doc/files/lib/RichTextDocument_rb.html +120 -0
- data/doc/files/lib/RichTextElement_rb.html +120 -0
- data/doc/files/lib/RichTextParser_rb.html +120 -0
- data/doc/files/lib/RichTextProtocolExample_rb.html +120 -0
- data/doc/files/lib/RichTextProtocolHandler_rb.html +106 -0
- data/doc/files/lib/RichTextScanner_rb.html +116 -0
- data/doc/files/lib/RichTextSnip_rb.html +118 -0
- data/doc/files/lib/RichTextSyntaxRules_rb.html +106 -0
- data/doc/files/lib/RichText_rb.html +118 -0
- data/doc/files/lib/ScenarioData_rb.html +118 -0
- data/doc/files/lib/Scenario_rb.html +116 -0
- data/doc/files/lib/Scoreboard_rb.html +106 -0
- data/doc/files/lib/ShiftAssignments_rb.html +116 -0
- data/doc/files/lib/ShiftScenario_rb.html +116 -0
- data/doc/files/lib/Shift_rb.html +118 -0
- data/doc/files/lib/SourceFileInfo_rb.html +106 -0
- data/doc/files/lib/SyntaxReference_rb.html +122 -0
- data/doc/files/lib/TOCEntry_rb.html +118 -0
- data/doc/files/lib/TableColumnDefinition_rb.html +106 -0
- data/doc/files/lib/TableOfContents_rb.html +118 -0
- data/doc/files/lib/TaskDependency_rb.html +106 -0
- data/doc/files/lib/TaskJuggler_rb.html +120 -0
- data/doc/files/lib/TaskScenario_rb.html +116 -0
- data/doc/files/lib/Task_rb.html +118 -0
- data/doc/files/lib/TextParser/Pattern_rb.html +116 -0
- data/doc/files/lib/TextParser/Rule_rb.html +106 -0
- data/doc/files/lib/TextParser/StackElement_rb.html +106 -0
- data/doc/files/lib/TextParser/TokenDoc_rb.html +106 -0
- data/doc/files/lib/TextParser_rb.html +124 -0
- data/doc/files/lib/TextScanner_rb.html +128 -0
- data/doc/files/lib/Tj3Config_rb.html +118 -0
- data/doc/files/lib/TjException_rb.html +106 -0
- data/doc/files/lib/TjTime_rb.html +118 -0
- data/doc/files/lib/TjpExample_rb.html +116 -0
- data/doc/files/lib/TjpSyntaxRules_rb.html +106 -0
- data/doc/files/lib/UTF8String_rb.html +132 -0
- data/doc/files/lib/UserManual_rb.html +124 -0
- data/doc/files/lib/WorkingHours_rb.html +116 -0
- data/doc/files/lib/XMLDocument_rb.html +116 -0
- data/doc/files/lib/XMLElement_rb.html +116 -0
- data/doc/files/lib/reports/CSVFile_rb.html +116 -0
- data/doc/files/lib/reports/ColumnTable_rb.html +116 -0
- data/doc/files/lib/reports/GanttChart_rb.html +122 -0
- data/doc/files/lib/reports/GanttContainer_rb.html +116 -0
- data/doc/files/lib/reports/GanttHeaderScaleItem_rb.html +106 -0
- data/doc/files/lib/reports/GanttHeader_rb.html +116 -0
- data/doc/files/lib/reports/GanttLine_rb.html +126 -0
- data/doc/files/lib/reports/GanttLoadStack_rb.html +116 -0
- data/doc/files/lib/reports/GanttMilestone_rb.html +116 -0
- data/doc/files/lib/reports/GanttRouter_rb.html +106 -0
- data/doc/files/lib/reports/GanttTaskBar_rb.html +116 -0
- data/doc/files/lib/reports/HTMLGraphics_rb.html +106 -0
- data/doc/files/lib/reports/ReportElement_rb.html +118 -0
- data/doc/files/lib/reports/ReportTableCell_rb.html +106 -0
- data/doc/files/lib/reports/ReportTableColumn_rb.html +106 -0
- data/doc/files/lib/reports/ReportTableElement_rb.html +122 -0
- data/doc/files/lib/reports/ReportTableLegend_rb.html +106 -0
- data/doc/files/lib/reports/ReportTableLine_rb.html +116 -0
- data/doc/files/lib/reports/ReportTable_rb.html +118 -0
- data/doc/files/lib/reports/Report_rb.html +126 -0
- data/doc/files/lib/reports/ResourceListRE_rb.html +122 -0
- data/doc/files/lib/reports/TaskListRE_rb.html +122 -0
- data/doc/files/lib/reports/TjpExportRE_rb.html +116 -0
- data/doc/files/lib/taskjuggler3_rb.html +276 -0
- data/doc/files/lib/tj3man_rb.html +189 -0
- data/doc/fr_class_index.html +285 -0
- data/doc/fr_file_index.html +223 -0
- data/doc/fr_method_index.html +1953 -0
- data/doc/index.html +21 -0
- data/doc/rdoc-style.css +299 -0
- data/examples/tutorial.tjp +361 -0
- data/gem_spec.rb +30 -0
- data/lib/Account.rb +50 -0
- data/lib/AccountScenario.rb +39 -0
- data/lib/Allocation.rb +102 -0
- data/lib/AppConfig.rb +134 -0
- data/lib/AttributeBase.rb +131 -0
- data/lib/AttributeDefinition.rb +47 -0
- data/lib/Attributes.rb +478 -0
- data/lib/BatchProcessor.rb +209 -0
- data/lib/Booking.rb +59 -0
- data/lib/Charge.rb +71 -0
- data/lib/ChargeSet.rb +126 -0
- data/lib/HTMLDocument.rb +59 -0
- data/lib/Interval.rb +127 -0
- data/lib/KeywordDocumentation.rb +560 -0
- data/lib/Limits.rb +219 -0
- data/lib/Log.rb +160 -0
- data/lib/LogicalExpression.rb +71 -0
- data/lib/LogicalFlag.rb +34 -0
- data/lib/LogicalFunction.rb +102 -0
- data/lib/LogicalOperation.rb +118 -0
- data/lib/MacroParser.rb +77 -0
- data/lib/MacroTable.rb +84 -0
- data/lib/Message.rb +56 -0
- data/lib/MessageHandler.rb +34 -0
- data/lib/Project.rb +662 -0
- data/lib/ProjectFileParser.rb +333 -0
- data/lib/PropertyList.rb +181 -0
- data/lib/PropertySet.rb +304 -0
- data/lib/PropertyTreeNode.rb +461 -0
- data/lib/Query.rb +227 -0
- data/lib/RealFormat.rb +73 -0
- data/lib/Resource.rb +42 -0
- data/lib/ResourceScenario.rb +511 -0
- data/lib/RichText.rb +147 -0
- data/lib/RichTextDocument.rb +139 -0
- data/lib/RichTextElement.rb +391 -0
- data/lib/RichTextParser.rb +66 -0
- data/lib/RichTextProtocolExample.rb +65 -0
- data/lib/RichTextProtocolHandler.rb +35 -0
- data/lib/RichTextScanner.rb +390 -0
- data/lib/RichTextSnip.rb +104 -0
- data/lib/RichTextSyntaxRules.rb +265 -0
- data/lib/Scenario.rb +27 -0
- data/lib/ScenarioData.rb +65 -0
- data/lib/Scoreboard.rb +141 -0
- data/lib/Shift.rb +48 -0
- data/lib/ShiftAssignments.rb +291 -0
- data/lib/ShiftScenario.rb +46 -0
- data/lib/SourceFileInfo.rb +37 -0
- data/lib/SyntaxReference.rb +284 -0
- data/lib/TOCEntry.rb +76 -0
- data/lib/TableColumnDefinition.rb +54 -0
- data/lib/TableOfContents.rb +46 -0
- data/lib/Task.rb +37 -0
- data/lib/TaskDependency.rb +39 -0
- data/lib/TaskJuggler.rb +84 -0
- data/lib/TaskScenario.rb +1622 -0
- data/lib/TextParser.rb +416 -0
- data/lib/TextParser/Pattern.rb +263 -0
- data/lib/TextParser/Rule.rb +171 -0
- data/lib/TextParser/StackElement.rb +45 -0
- data/lib/TextParser/TokenDoc.rb +38 -0
- data/lib/TextScanner.rb +682 -0
- data/lib/Tj3Config.rb +27 -0
- data/lib/TjException.rb +27 -0
- data/lib/TjTime.rb +395 -0
- data/lib/TjpExample.rb +119 -0
- data/lib/TjpSyntaxRules.rb +4022 -0
- data/lib/UTF8String.rb +100 -0
- data/lib/UserManual.rb +282 -0
- data/lib/WorkingHours.rb +323 -0
- data/lib/XMLDocument.rb +54 -0
- data/lib/XMLElement.rb +175 -0
- data/lib/reports/CSVFile.rb +146 -0
- data/lib/reports/ColumnTable.rb +66 -0
- data/lib/reports/GanttChart.rb +308 -0
- data/lib/reports/GanttContainer.rb +107 -0
- data/lib/reports/GanttHeader.rb +141 -0
- data/lib/reports/GanttHeaderScaleItem.rb +42 -0
- data/lib/reports/GanttLine.rb +329 -0
- data/lib/reports/GanttLoadStack.rb +113 -0
- data/lib/reports/GanttMilestone.rb +80 -0
- data/lib/reports/GanttRouter.rb +375 -0
- data/lib/reports/GanttTaskBar.rb +95 -0
- data/lib/reports/HTMLGraphics.rb +65 -0
- data/lib/reports/Report.rb +344 -0
- data/lib/reports/ReportElement.rb +427 -0
- data/lib/reports/ReportTable.rb +144 -0
- data/lib/reports/ReportTableCell.rb +142 -0
- data/lib/reports/ReportTableColumn.rb +82 -0
- data/lib/reports/ReportTableElement.rb +852 -0
- data/lib/reports/ReportTableLegend.rb +167 -0
- data/lib/reports/ReportTableLine.rb +87 -0
- data/lib/reports/ResourceListRE.rb +72 -0
- data/lib/reports/TaskListRE.rb +73 -0
- data/lib/reports/TjpExportRE.rb +394 -0
- data/lib/taskjuggler3.rb +106 -0
- data/lib/tj3man.rb +88 -0
- data/manual/Day_To_Day_Juggling +168 -0
- data/manual/Getting_Started +61 -0
- data/manual/How_To_Contribute +185 -0
- data/manual/Installation +68 -0
- data/manual/Intro +102 -0
- data/manual/Reporting_Bugs +26 -0
- data/manual/Rich_Text_Attributes +90 -0
- data/manual/TaskJuggler_2x_Migration +40 -0
- data/manual/Tutorial +579 -0
- data/manual/fdl +450 -0
- data/prj_cfg.rb +43 -0
- data/setup.rb +1585 -0
- data/tasks/csts.rake +72 -0
- data/tasks/gem.rake +14 -0
- data/tasks/manual.rake +10 -0
- data/tasks/missing.rake +21 -0
- data/tasks/rcov.rake +14 -0
- data/tasks/rdoc.rake +17 -0
- data/tasks/rexml_fix.rb +16 -0
- data/tasks/rexml_fix_19.rb +49 -0
- data/tasks/show.rake +21 -0
- data/tasks/stats.rake +25 -0
- data/tasks/test.rake +11 -0
- data/test/MessageChecker.rb +53 -0
- data/test/TestSuite/CSV-Reports/celltext-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/celltext.tjp +7 -0
- data/test/TestSuite/CSV-Reports/genrefs +6 -0
- data/test/TestSuite/CSV-Reports/project-1.tji +57 -0
- data/test/TestSuite/CSV-Reports/resourcereport-Reference.csv +4 -0
- data/test/TestSuite/CSV-Reports/resourcereport.tjp +10 -0
- data/test/TestSuite/CSV-Reports/resourcereport_with_tasks-Reference.csv +22 -0
- data/test/TestSuite/CSV-Reports/resourcereport_with_tasks.tjp +11 -0
- data/test/TestSuite/CSV-Reports/sortByTree-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortByTree.tjp +8 -0
- data/test/TestSuite/CSV-Reports/sortBy_duration.down-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortBy_duration.down.tjp +10 -0
- data/test/TestSuite/CSV-Reports/sortBy_effort.up-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortBy_effort.up.tjp +10 -0
- data/test/TestSuite/CSV-Reports/sortBy_plan.start.down-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortBy_plan.start.down.tjp +10 -0
- data/test/TestSuite/CSV-Reports/taskreport-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/taskreport.tjp +10 -0
- data/test/TestSuite/CSV-Reports/taskreport_with_resources-Reference.csv +24 -0
- data/test/TestSuite/CSV-Reports/taskreport_with_resources.tjp +11 -0
- data/test/TestSuite/Scheduler/Correct/Allocate.tjp +86 -0
- data/test/TestSuite/Scheduler/Correct/AutomaticMilestones.tjp +63 -0
- data/test/TestSuite/Scheduler/Correct/Booking.tjp +161 -0
- data/test/TestSuite/Scheduler/Correct/Depends.tjp +50 -0
- data/test/TestSuite/Scheduler/Correct/Duration.tjp +34 -0
- data/test/TestSuite/Scheduler/Correct/InheritStartEnd.tjp +129 -0
- data/test/TestSuite/Scheduler/Correct/Limits.tjp +81 -0
- data/test/TestSuite/Scheduler/Correct/MultipleMandatories.tjp +43 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-1.tjp +28 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-2.tjp +33 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-3.tjp +33 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-4.tjp +34 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-5.tjp +62 -0
- data/test/TestSuite/Scheduler/Correct/Precedes.tjp +50 -0
- data/test/TestSuite/Scheduler/Correct/Shift.tjp +102 -0
- data/test/TestSuite/Scheduler/Errors/account_no_leaf.tjp +13 -0
- data/test/TestSuite/Scheduler/Errors/booking_conflict.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/booking_no_duty.tjp +9 -0
- data/test/TestSuite/Scheduler/Errors/booking_on_vacation.tjp +9 -0
- data/test/TestSuite/Scheduler/Errors/container_booking.tjp +14 -0
- data/test/TestSuite/Scheduler/Errors/container_duration.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/effort_no_allocations.tjp +7 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_1.tjp +19 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_10.tjp +36 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_11.tjp +27 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_12.tjp +20 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_13.tjp +27 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_14.tjp +26 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_2.tjp +24 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_3.tjp +18 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_4.tjp +36 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_5.tjp +37 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_6.tjp +35 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_7.tjp +46 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_8.tjp +51 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_9.tjp +20 -0
- data/test/TestSuite/Scheduler/Errors/maxend.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/maxstart.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/milestone_booking.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/milestone_duration.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/milestone_start_end.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/minend.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/minstart.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/multiple_durations.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/no_tasks.tjp +6 -0
- data/test/TestSuite/Scheduler/Errors/not_scheduled.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_child.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_multi.tjp +13 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_parent.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_self.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_unknown.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/task_overspecified_1.tjp +9 -0
- data/test/TestSuite/Scheduler/Errors/task_overspecified_2.tjp +14 -0
- data/test/TestSuite/Scheduler/Errors/task_overspecified_3.tjp +14 -0
- data/test/TestSuite/Scheduler/Errors/task_underspecified_1.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/task_underspecified_2.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/task_underspecified_3.tjp +9 -0
- data/test/TestSuite/Syntax/Correct/Account.tjp +53 -0
- data/test/TestSuite/Syntax/Correct/Allocate-1.tjp +24 -0
- data/test/TestSuite/Syntax/Correct/Alternative.tjp +13 -0
- data/test/TestSuite/Syntax/Correct/AutoMacros.tjp +14 -0
- data/test/TestSuite/Syntax/Correct/Booking.tjp +26 -0
- data/test/TestSuite/Syntax/Correct/Caption.tjp +33 -0
- data/test/TestSuite/Syntax/Correct/Celltext.tjp +28 -0
- data/test/TestSuite/Syntax/Correct/Comments.tjp +29 -0
- data/test/TestSuite/Syntax/Correct/Complete.tjp +16 -0
- data/test/TestSuite/Syntax/Correct/CompletedWork.tji +20 -0
- data/test/TestSuite/Syntax/Correct/CriticalPath.tjp +31 -0
- data/test/TestSuite/Syntax/Correct/Currencyformat.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/CustomAttributes.tjp +14 -0
- data/test/TestSuite/Syntax/Correct/Depends1.tjp +22 -0
- data/test/TestSuite/Syntax/Correct/Durations.tjp +29 -0
- data/test/TestSuite/Syntax/Correct/Efficiency.tjp +19 -0
- data/test/TestSuite/Syntax/Correct/Export.tjp +40 -0
- data/test/TestSuite/Syntax/Correct/Flags.tjp +32 -0
- data/test/TestSuite/Syntax/Correct/Freeze.tjp +28 -0
- data/test/TestSuite/Syntax/Correct/Gap.tjp +15 -0
- data/test/TestSuite/Syntax/Correct/HtmlTaskReport.tjp +33 -0
- data/test/TestSuite/Syntax/Correct/Limits-1.tjp +71 -0
- data/test/TestSuite/Syntax/Correct/LoadUnits.tjp +31 -0
- data/test/TestSuite/Syntax/Correct/Macro-1.tjp +19 -0
- data/test/TestSuite/Syntax/Correct/Mandatory.tjp +17 -0
- data/test/TestSuite/Syntax/Correct/Milestone.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/MinMax.tjp +17 -0
- data/test/TestSuite/Syntax/Correct/Numberformat.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/Period.tjp +16 -0
- data/test/TestSuite/Syntax/Correct/Persistent.tjp +11 -0
- data/test/TestSuite/Syntax/Correct/Precedes1.tjp +17 -0
- data/test/TestSuite/Syntax/Correct/Priority.tjp +30 -0
- data/test/TestSuite/Syntax/Correct/Project.tjp +21 -0
- data/test/TestSuite/Syntax/Correct/ProjectIDs.tjp +23 -0
- data/test/TestSuite/Syntax/Correct/RawHTML.tjp +29 -0
- data/test/TestSuite/Syntax/Correct/Reports.tjp +54 -0
- data/test/TestSuite/Syntax/Correct/Resource.tjp +20 -0
- data/test/TestSuite/Syntax/Correct/Responsible.tjp +16 -0
- data/test/TestSuite/Syntax/Correct/Scenario.tjp +15 -0
- data/test/TestSuite/Syntax/Correct/Scheduling.tjp +26 -0
- data/test/TestSuite/Syntax/Correct/Select.tjp +27 -0
- data/test/TestSuite/Syntax/Correct/Shift.tjp +55 -0
- data/test/TestSuite/Syntax/Correct/Simple.tjp +25 -0
- data/test/TestSuite/Syntax/Correct/String.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/Supplement.tjp +24 -0
- data/test/TestSuite/Syntax/Correct/TaskRoot.tjp +34 -0
- data/test/TestSuite/Syntax/Correct/TimeFrame.tjp +19 -0
- data/test/TestSuite/Syntax/Correct/Timezone.tjp +8 -0
- data/test/TestSuite/Syntax/Correct/Vacation.tjp +33 -0
- data/test/TestSuite/Syntax/Correct/csvtest +16 -0
- data/test/TestSuite/Syntax/Correct/manual2example.rb +24 -0
- data/test/TestSuite/Syntax/Correct/tutorial.tjp +485 -0
- data/test/TestSuite/Syntax/Errors/bad_include.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/booking_group.tjp +14 -0
- data/test/TestSuite/Syntax/Errors/booking_milestone.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/booking_no_leaf.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/chargeset.tjp +14 -0
- data/test/TestSuite/Syntax/Errors/chargeset_master.tjp +15 -0
- data/test/TestSuite/Syntax/Errors/container_attribute.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/cost_acct_no_top.tjp +24 -0
- data/test/TestSuite/Syntax/Errors/cost_rev_same.tjp +24 -0
- data/test/TestSuite/Syntax/Errors/date_in_range.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/effort_zero.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/empty.tjp +1 -0
- data/test/TestSuite/Syntax/Errors/export_bad_extn.tjp +9 -0
- data/test/TestSuite/Syntax/Errors/extend_id_cap.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/interval_end_in_range.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/interval_start_in_range.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/leaf_resource_id_expected.tjp +12 -0
- data/test/TestSuite/Syntax/Errors/misaligned_date.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/no_csv_suffix.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/no_html_suffix.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/operand_attribute.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/operand_unkn_flag.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/operand_unkn_scen.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/overtime_range.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/purge_no_list.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/purge_unknown_id.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/report_end.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/report_redifinition.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/report_start.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/resource_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/resource_id_expected.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/rev_acct_no_top.tjp +24 -0
- data/test/TestSuite/Syntax/Errors/scenario_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/shift_assignment_overlap.tjp +15 -0
- data/test/TestSuite/Syntax/Errors/shift_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/shift_id_expected.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/sloppy_range.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/sort_direction.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sort_unknown_scen.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sorting_crit_exptd1.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sorting_crit_exptd2.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sorting_wbs.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/start_before_end1.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/start_before_end2.tjp +6 -0
- data/test/TestSuite/Syntax/Errors/task_complete.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/task_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/task_priority.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/task_without_chargeset.tjp +9 -0
- data/test/TestSuite/Syntax/Errors/time_interval.tjp +12 -0
- data/test/TestSuite/Syntax/Errors/too_many_bangs.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/undecl_flag.tjp +6 -0
- data/test/TestSuite/Syntax/Errors/unknown_projectid.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/unknown_scenario_id.tjp +6 -0
- data/test/TestSuite/Syntax/Errors/unknown_scenario_idx.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/unknown_task.tjp +10 -0
- data/test/all.rb +31 -0
- data/test/test_BatchProcessor.rb +54 -0
- data/test/test_CSV-Reports.rb +101 -0
- data/test/test_Limits.rb +104 -0
- data/test/test_LogicalExpression.rb +110 -0
- data/test/test_MacroTable.rb +51 -0
- data/test/test_Project.rb +57 -0
- data/test/test_PropertySet.rb +71 -0
- data/test/test_Query.rb +83 -0
- data/test/test_RealFormat.rb +83 -0
- data/test/test_RichText.rb +869 -0
- data/test/test_Scheduler.rb +42 -0
- data/test/test_ShiftAssignments.rb +77 -0
- data/test/test_Syntax.rb +41 -0
- data/test/test_TextScanner.rb +95 -0
- data/test/test_TjTime.rb +114 -0
- data/test/test_TjpExample.rb +169 -0
- data/test/test_UTF8String.rb +84 -0
- data/test/test_WorkingHours.rb +56 -0
- metadata +649 -0
data/lib/TextParser.rb
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
#!/usr/bin/env ruby -w
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
#
|
|
4
|
+
# = TextParser.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 'TextParser/Pattern'
|
|
14
|
+
require 'TextParser/Rule'
|
|
15
|
+
require 'TextParser/StackElement'
|
|
16
|
+
require 'TjException'
|
|
17
|
+
require 'Log'
|
|
18
|
+
|
|
19
|
+
class TaskJuggler
|
|
20
|
+
|
|
21
|
+
# The TextParser implements a regular LALR parser. But it uses a recursive
|
|
22
|
+
# rule traversor instead of the more commonly found state machine generated by
|
|
23
|
+
# yacc-like tools. Since stack depths is not really an issue with a Ruby
|
|
24
|
+
# implementation this approach has one big advantage. The syntax of the parser
|
|
25
|
+
# can be modified during parsing. This allows support for languages that can
|
|
26
|
+
# extend themself. The TaskJuggler syntax is such an beast. Traditional yacc
|
|
27
|
+
# generated parsers would fail with such a syntax.
|
|
28
|
+
#
|
|
29
|
+
# This class is just a base class. A complete parser would derive from this
|
|
30
|
+
# class and implement the rule set and the functions _nextToken()_ and
|
|
31
|
+
# _returnToken()_. It also needs to set the array _variables_ to declare all
|
|
32
|
+
# variables ($SOMENAME) that the scanner may deliver.
|
|
33
|
+
#
|
|
34
|
+
# To describe the syntax the functions TextParser#pattern, TextParser#optional
|
|
35
|
+
# and TextParser#repeatable can be used. When the rule set is changed during
|
|
36
|
+
# parsing, TextParser#updateParserTables must be called to make the changes
|
|
37
|
+
# effective. The parser can also document the syntax automatically. To
|
|
38
|
+
# document a pattern, the functions TextParser#doc, TextParser#descr,
|
|
39
|
+
# TextParser#also and TextParser#arg can be used.
|
|
40
|
+
#
|
|
41
|
+
# To start parsing the input the function TextParser#parse needs to be called
|
|
42
|
+
# with the name of the start rule.
|
|
43
|
+
class TextParser
|
|
44
|
+
|
|
45
|
+
# Utility class so that we can distinguish Array results from the Array
|
|
46
|
+
# containing the results of a repeatable rule.
|
|
47
|
+
class TextParserResultArray < Array
|
|
48
|
+
|
|
49
|
+
def initialize
|
|
50
|
+
super
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# If there is a repeatable rule that contains another repeatable loop, the
|
|
54
|
+
# result of the inner rule is an Array that gets put into another Array by
|
|
55
|
+
# the outer rule. In this case, the inner Array can be merged with the
|
|
56
|
+
# outer Array.
|
|
57
|
+
def <<(arg)
|
|
58
|
+
if arg.is_a?(TextParserResultArray)
|
|
59
|
+
self.concat(arg)
|
|
60
|
+
else
|
|
61
|
+
super
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
attr_reader :rules
|
|
68
|
+
|
|
69
|
+
# Create a new TextParser object.
|
|
70
|
+
def initialize
|
|
71
|
+
@rules = { }
|
|
72
|
+
# Array to hold the token types that the scanner can return.
|
|
73
|
+
@variables = []
|
|
74
|
+
# The currently processed rule.
|
|
75
|
+
@cr = nil
|
|
76
|
+
# If set to a value larger than 0 debug output will be generated.
|
|
77
|
+
@@debug = 30
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Call all methods that start with 'rule_' to initialize the rules.
|
|
81
|
+
def initRules
|
|
82
|
+
methods.each do |m|
|
|
83
|
+
if m[0, 5] == 'rule_'
|
|
84
|
+
# Create a new rule with the suffix of the function name as name.
|
|
85
|
+
newRule(m[5..-1])
|
|
86
|
+
# Call the function.
|
|
87
|
+
send(m)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Add a new rule to the rule set. _name_ must be a unique identifier. The
|
|
93
|
+
# function also sets the class variable @cr to the new rule. Subsequent
|
|
94
|
+
# calls to TextParser#pattern, TextParser#optional or
|
|
95
|
+
# TextParser#repeatable will then implicitely operate on the most recently
|
|
96
|
+
# added rule.
|
|
97
|
+
def newRule(name)
|
|
98
|
+
raise "Fatal Error: Rule #{name} already exists" if @rules.has_key?(name)
|
|
99
|
+
|
|
100
|
+
@rules[name] = @cr = TextParser::Rule.new(name)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Add a new pattern to the most recently added rule. _tokens_ is an array of
|
|
104
|
+
# strings that specify the syntax elements of the pattern. Each token must
|
|
105
|
+
# start with an character that identifies the type of the token. The
|
|
106
|
+
# following types are supported.
|
|
107
|
+
#
|
|
108
|
+
# * ! a reference to another rule
|
|
109
|
+
# * $ a variable token as delivered by the scanner
|
|
110
|
+
# * _ a literal token.
|
|
111
|
+
#
|
|
112
|
+
# _func_ is a Proc object that is called whenever the parser has completed
|
|
113
|
+
# the processing of this rule.
|
|
114
|
+
def pattern(tokens, func = nil)
|
|
115
|
+
@cr.addPattern(TextParser::Pattern.new(tokens, func))
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Identify the patterns of the most recently added rule as optional syntax
|
|
119
|
+
# elements.
|
|
120
|
+
def optional
|
|
121
|
+
@cr.setOptional
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Identify the patterns of the most recently added rule as repeatable syntax
|
|
125
|
+
# elements.
|
|
126
|
+
def repeatable
|
|
127
|
+
@cr.setRepeatable
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# This function needs to be called whenever new rules or patterns have been
|
|
131
|
+
# added and before the next call to TextParser#parse.
|
|
132
|
+
def updateParserTables
|
|
133
|
+
@rules.each_value { |rule| rule.transitions = {} }
|
|
134
|
+
@rules.each_value do |rule|
|
|
135
|
+
getTransitions(rule)
|
|
136
|
+
checkRule(rule)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# To parse the input this function needs to be called with the name of the
|
|
141
|
+
# rule to start with. It returns the result of the processing function of
|
|
142
|
+
# the top-level parser rule that was specified by _ruleName_.
|
|
143
|
+
def parse(ruleName, enforceEndOfFile = true)
|
|
144
|
+
@stack = []
|
|
145
|
+
@@expectedTokens = []
|
|
146
|
+
updateParserTables
|
|
147
|
+
begin
|
|
148
|
+
result = parseRule(@rules[ruleName])
|
|
149
|
+
rescue TjException
|
|
150
|
+
# error('parse_error', $!.message)
|
|
151
|
+
return nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
result
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Return the SourceFileInfo of the TextScanner at the beginning of the
|
|
158
|
+
# currently processed TextParser::Rule. Or return nil if we don't have a
|
|
159
|
+
# current position.
|
|
160
|
+
def sourceFileInfo
|
|
161
|
+
return nil if @stack.empty?
|
|
162
|
+
@stack.last.sourceFileInfo
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def matchingRules(keyword)
|
|
166
|
+
matches = []
|
|
167
|
+
@rules.each do |name, rule|
|
|
168
|
+
patIdx = rule.matchingPatternIndex('_' + keyword)
|
|
169
|
+
matches << [ rule, patIdx ] if patIdx
|
|
170
|
+
end
|
|
171
|
+
matches
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def error(id, text, property = nil)
|
|
175
|
+
@scanner.error(id, text, property)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
# getTransitions recursively determines all possible target tokens
|
|
181
|
+
# that the _rule_ matches. A target token can either be a fixed token
|
|
182
|
+
# (prefixed with _), a variable token (prefixed with $) or an end token
|
|
183
|
+
# (just a .). The list of found target tokens is stored in the _transitions_
|
|
184
|
+
# list of the rule. For each rule pattern we store the transitions for this
|
|
185
|
+
# pattern in a token -> rule hash.
|
|
186
|
+
def getTransitions(rule)
|
|
187
|
+
# If we have processed this rule before we can just return a copy
|
|
188
|
+
# of the transitions of this rule. This avoids endless recursions.
|
|
189
|
+
return rule.transitions.clone unless rule.transitions.empty?
|
|
190
|
+
|
|
191
|
+
rule.transitions = []
|
|
192
|
+
rule.patterns.each do |pat|
|
|
193
|
+
allTokensOptional = true
|
|
194
|
+
transitions = { }
|
|
195
|
+
pat.each do |token|
|
|
196
|
+
tokenId = token[1..-1]
|
|
197
|
+
if token[0] == ?!
|
|
198
|
+
unless @rules.has_key?(tokenId)
|
|
199
|
+
raise "Fatal Error: Unknown reference to #{tokenId} in pattern " +
|
|
200
|
+
"#{pat} + of rule #{rule.name}"
|
|
201
|
+
end
|
|
202
|
+
refRule = @rules[tokenId]
|
|
203
|
+
# If the referenced rule describes optional content, we need to look
|
|
204
|
+
# at the next token as well.
|
|
205
|
+
res = getTransitions(@rules[tokenId])
|
|
206
|
+
allTokensOptional = false unless refRule.optional?(@rules)
|
|
207
|
+
# Combine the hashes for each pattern into a single hash
|
|
208
|
+
res.each do |pat_i|
|
|
209
|
+
pat_i.each { |tok, r| transitions[tok] = r }
|
|
210
|
+
end
|
|
211
|
+
optional = true if refRule.optional
|
|
212
|
+
elsif '_$.'.include?(token[0])
|
|
213
|
+
transitions[token] = rule
|
|
214
|
+
allTokensOptional = false
|
|
215
|
+
else
|
|
216
|
+
raise 'Fatal Error: Illegal token type specifier used for token' +
|
|
217
|
+
": #{tokenId}"
|
|
218
|
+
end
|
|
219
|
+
break unless allTokensOptional
|
|
220
|
+
end
|
|
221
|
+
# Make sure that we only have one possible transition for each
|
|
222
|
+
# target.
|
|
223
|
+
transitions.each do |key, value|
|
|
224
|
+
rule.transitions.each do |trans|
|
|
225
|
+
if trans.has_key?(key)
|
|
226
|
+
raise "Fatal Error: Rule #{rule.name} has ambigeous " +
|
|
227
|
+
"transitions for target #{key}"
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
rule.transitions << transitions
|
|
232
|
+
end
|
|
233
|
+
rule.transitions.clone
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def checkRule(rule)
|
|
237
|
+
if rule.patterns.empty?
|
|
238
|
+
raise "Rule #{rule.name} must have at least one pattern"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
rule.patterns.each do |pat|
|
|
242
|
+
pat.each do |tok|
|
|
243
|
+
type = tok[0]
|
|
244
|
+
token = tok[1..-1]
|
|
245
|
+
if type == ?$
|
|
246
|
+
if @variables.index(token).nil?
|
|
247
|
+
raise "Fatal Error: Illegal variable type #{token} used for " +
|
|
248
|
+
"rule #{rule.name} in pattern '#{pat}'"
|
|
249
|
+
end
|
|
250
|
+
elsif type == ?!
|
|
251
|
+
if @rules[token].nil?
|
|
252
|
+
raise "Fatal Error: Reference to unknown rule #{token} in " +
|
|
253
|
+
"pattern '#{pat}' of rule #{rule.name}"
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# This function processes the input starting with the syntax description of
|
|
261
|
+
# _rule_. It recursively calls this function whenever the syntax description
|
|
262
|
+
# contains the reference to another rule.
|
|
263
|
+
def parseRule(rule)
|
|
264
|
+
Log.enter('parseRule', "Parsing with rule #{rule.name}")
|
|
265
|
+
result = rule.repeatable ? TextParserResultArray.new : nil
|
|
266
|
+
# Rules can be marked 'repeatable'. This flag will be set to true after
|
|
267
|
+
# the first iteration has been completed.
|
|
268
|
+
repeatMode = false
|
|
269
|
+
loop do
|
|
270
|
+
# At the beginning of a rule we need a token from the input to determine
|
|
271
|
+
# which pattern of the rule needs to be processed.
|
|
272
|
+
begin
|
|
273
|
+
token = nextToken
|
|
274
|
+
Log << "Token: [#{token[0]}][#{token[1]}]"
|
|
275
|
+
rescue TjException
|
|
276
|
+
error('parse_rule1', $!.message)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# The scanner cannot differentiate between keywords and identifiers. So
|
|
280
|
+
# whenever an identifier is returned we have to see if we have a
|
|
281
|
+
# matching keyword first. If none is found, then look for normal
|
|
282
|
+
# identifiers.
|
|
283
|
+
if token[0] == 'ID'
|
|
284
|
+
if (patIdx = rule.matchingPatternIndex('_' + token[1])).nil?
|
|
285
|
+
patIdx = rule.matchingPatternIndex("$ID")
|
|
286
|
+
end
|
|
287
|
+
elsif token[0] == 'LITERAL'
|
|
288
|
+
patIdx = rule.matchingPatternIndex('_' + token[1])
|
|
289
|
+
elsif token[0] == false
|
|
290
|
+
patIdx = rule.matchingPatternIndex('.')
|
|
291
|
+
else
|
|
292
|
+
patIdx = rule.matchingPatternIndex('$' + token[0])
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# If no matching pattern is found for the token we have to check if the
|
|
296
|
+
# rule is optional or we are in repeat mode. If this is the case, return
|
|
297
|
+
# the token back to the scanner. Otherwise we have found a token we
|
|
298
|
+
# cannot handle at this point.
|
|
299
|
+
if patIdx.nil?
|
|
300
|
+
# Append the list of expected tokens to the @@expectedToken array.
|
|
301
|
+
# This may be used in a later rule to provide more details when an
|
|
302
|
+
# error occured.
|
|
303
|
+
rule.transitions.each do |transition|
|
|
304
|
+
keys = transition.keys
|
|
305
|
+
keys.collect! { |key| key[1..-1] }
|
|
306
|
+
@@expectedTokens += keys
|
|
307
|
+
@@expectedTokens.sort!
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
unless rule.optional?(@rules) || repeatMode
|
|
311
|
+
error('unexpctd_token',
|
|
312
|
+
(token[0] != false ?
|
|
313
|
+
"Unexpected token '#{token[1]}' of type '#{token[0]}'. " :
|
|
314
|
+
"Unexpected end of file in #{@scanner.fileName}. ") +
|
|
315
|
+
(@@expectedTokens.length > 1 ?
|
|
316
|
+
"Expecting one of #{@@expectedTokens.join(', ')}" :
|
|
317
|
+
"Expecting #{@@expectedTokens[0]}"))
|
|
318
|
+
end
|
|
319
|
+
returnToken(token)
|
|
320
|
+
Log.exit('parseRule', "Finished rule #{rule.name}")
|
|
321
|
+
return result
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
pattern = rule.pattern(patIdx)
|
|
325
|
+
@stack << TextParser::StackElement.new(rule, pattern.function,
|
|
326
|
+
@scanner.sourceFileInfo)
|
|
327
|
+
|
|
328
|
+
pattern.each do |element|
|
|
329
|
+
# Separate the type and token text for pattern element.
|
|
330
|
+
elType = element[0]
|
|
331
|
+
elToken = element[1..-1]
|
|
332
|
+
if elType == ?!
|
|
333
|
+
# The element is a reference to another rule. Return the token if we
|
|
334
|
+
# still have one and continue with the referenced rule.
|
|
335
|
+
unless token.nil?
|
|
336
|
+
returnToken(token)
|
|
337
|
+
token = nil
|
|
338
|
+
end
|
|
339
|
+
@stack.last.store(parseRule(@rules[elToken]))
|
|
340
|
+
else
|
|
341
|
+
# In case the element is a keyword or variable we have to get a new
|
|
342
|
+
# token if we don't have one anymore.
|
|
343
|
+
if token.nil?
|
|
344
|
+
begin
|
|
345
|
+
token = nextToken
|
|
346
|
+
Log << "Token: [#{token[0]}][#{token[1]}]"
|
|
347
|
+
rescue TjException
|
|
348
|
+
error('parse_rule2', $!.message)
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
if elType == ?_
|
|
353
|
+
# If the element requires a keyword the token must match this
|
|
354
|
+
# keyword.
|
|
355
|
+
if elToken != token[1]
|
|
356
|
+
text = "'#{elToken}' expected but found " +
|
|
357
|
+
"'#{token[1]}' (#{token[0]})."
|
|
358
|
+
unless @@expectedTokens.empty?
|
|
359
|
+
text = "#{@@expectedTokens.join(', ')} or " + text
|
|
360
|
+
end
|
|
361
|
+
error('spec_keywork_expctd', text)
|
|
362
|
+
end
|
|
363
|
+
@stack.last.store(elToken)
|
|
364
|
+
elsif elType == ?.
|
|
365
|
+
if token != [ '.', '<END>' ]
|
|
366
|
+
error('end_expected', 'End expected but found ' +
|
|
367
|
+
"'#{token[1]}' (#{token[0]}).")
|
|
368
|
+
end
|
|
369
|
+
else
|
|
370
|
+
# The token must match the expected variable type.
|
|
371
|
+
if token[0] != elToken
|
|
372
|
+
text = "'#{elToken}' expected but found " +
|
|
373
|
+
"'#{token[1]}' (#{token[0]})."
|
|
374
|
+
unless @@expectedTokens.empty?
|
|
375
|
+
text = "#{@@expectedTokens.join(', ')} or " + text
|
|
376
|
+
end
|
|
377
|
+
error('spec_token_expctd', text)
|
|
378
|
+
end
|
|
379
|
+
# If the element is a variable store the value of the token.
|
|
380
|
+
@stack.last.store(token[1])
|
|
381
|
+
end
|
|
382
|
+
# The token has been consumed. Reset the variable.
|
|
383
|
+
token = nil
|
|
384
|
+
@@expectedTokens = []
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# Once the complete pattern has been processed we call the processing
|
|
389
|
+
# function for this pattern to operate on the value array. Then pop the
|
|
390
|
+
# entry for this rule from the stack.
|
|
391
|
+
@val = @stack.last.val
|
|
392
|
+
res = nil
|
|
393
|
+
res = @stack.last.function.call unless @stack.last.function.nil?
|
|
394
|
+
@stack.pop
|
|
395
|
+
|
|
396
|
+
# If the rule is not repeatable we can store the result and break the
|
|
397
|
+
# outer loop to exit the function.
|
|
398
|
+
unless rule.repeatable
|
|
399
|
+
result = res
|
|
400
|
+
break
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Otherwise we append the result to the result array and turn repeat
|
|
404
|
+
# mode on.
|
|
405
|
+
result << res
|
|
406
|
+
repeatMode = true
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
Log.exit('parseRule', "Finished rule #{rule.name}")
|
|
410
|
+
return result
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
end
|
|
416
|
+
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env ruby -w
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
#
|
|
4
|
+
# = TextParser/Pattern.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 'TextParser/TokenDoc'
|
|
14
|
+
|
|
15
|
+
class TaskJuggler::TextParser
|
|
16
|
+
|
|
17
|
+
# This class models the most crutial elements of a syntax description - the
|
|
18
|
+
# pattern. A TextParserPattern primarily consists of a set of tokens. Tokens
|
|
19
|
+
# are Strings where the first character determines the type of the token.
|
|
20
|
+
# There are 4 known types.
|
|
21
|
+
#
|
|
22
|
+
# Terminal token: The terminal token is prefixed by an underscore. Terminal
|
|
23
|
+
# tokens are terminal symbols of the syntax tree. They just represent
|
|
24
|
+
# themselves.
|
|
25
|
+
#
|
|
26
|
+
# Variable token: The variable token describes values of a certain class such
|
|
27
|
+
# as strings or numbers. The token is prefixed by a dollar sign and the text
|
|
28
|
+
# of the token specifies the variable type. See ProjectFileParser for a
|
|
29
|
+
# complete list of variable types.
|
|
30
|
+
#
|
|
31
|
+
# Reference token: The reference token specifies a reference to another parser
|
|
32
|
+
# rule. The token is prefixed by a bang and the text matches the name of the
|
|
33
|
+
# rule. See TextParserRule for details.
|
|
34
|
+
#
|
|
35
|
+
# End token: The . token marks the expected end of the input stream.
|
|
36
|
+
#
|
|
37
|
+
# In addition to the pure syntax tree information the pattern also holds
|
|
38
|
+
# documentary information about the pattern.
|
|
39
|
+
class Pattern
|
|
40
|
+
|
|
41
|
+
attr_reader :keyword, :doc, :seeAlso, :exampleFile, :exampleTag,
|
|
42
|
+
:tokens, :function
|
|
43
|
+
|
|
44
|
+
def initialize(tokens, function = nil)
|
|
45
|
+
# A unique name for the pattern that is used in the documentation.
|
|
46
|
+
@keyword = nil
|
|
47
|
+
# Initialize pattern doc as empty.
|
|
48
|
+
@doc = nil
|
|
49
|
+
# A list of TokenDoc elements that describe the meaning of variable
|
|
50
|
+
# tokens. The order of the tokens and entries in the Array must correlate.
|
|
51
|
+
@args = []
|
|
52
|
+
# A list of references to other patterns that are related to this pattern.
|
|
53
|
+
@seeAlso = []
|
|
54
|
+
# A reference to a file under test/TestSuite/Syntax/Correct and a tag
|
|
55
|
+
# within that file. This identifies example TJP code to be included with
|
|
56
|
+
# the reference manual.
|
|
57
|
+
@exampleFile = nil
|
|
58
|
+
@exampleTag = nil
|
|
59
|
+
|
|
60
|
+
tokens.each do |token|
|
|
61
|
+
unless '!$_.'.include?(token[0])
|
|
62
|
+
raise "Fatal Error: All pattern tokens must start with a type " +
|
|
63
|
+
"identifier [!$_.]: #{tokens.join(', ')}"
|
|
64
|
+
end
|
|
65
|
+
# Initialize pattern argument descriptions as empty.
|
|
66
|
+
@args << nil
|
|
67
|
+
end
|
|
68
|
+
@tokens = tokens
|
|
69
|
+
@function = function
|
|
70
|
+
# In some cases we don't want to show all tokens in the syntax
|
|
71
|
+
# documentation. This value specifies the index of the last shown token.
|
|
72
|
+
@lastSyntaxToken = @tokens.length - 1
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Set the keyword and documentation text for the pattern.
|
|
76
|
+
def setDoc(keyword, doc)
|
|
77
|
+
@keyword = keyword
|
|
78
|
+
@doc = doc
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Set the documentation text and for the idx-th variable.
|
|
82
|
+
def setArg(idx, doc)
|
|
83
|
+
@args[idx] = doc
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Restrict the syntax documentation to the first +idx+ tokens.
|
|
87
|
+
def setLastSyntaxToken(idx)
|
|
88
|
+
@lastSyntaxToken = idx
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Set the references to related patterns.
|
|
92
|
+
def setSeeAlso(also)
|
|
93
|
+
@seeAlso = also
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Set the file and tag for the TJP code example.
|
|
97
|
+
def setExample(file, tag)
|
|
98
|
+
@exampleFile = file
|
|
99
|
+
@exampleTag = tag
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Conveniance function to access individual tokens by index.
|
|
103
|
+
def [](i)
|
|
104
|
+
@tokens[i]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Iterator for tokens.
|
|
108
|
+
def each
|
|
109
|
+
@tokens.each { |tok| yield tok }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns true of the pattern is empty.
|
|
113
|
+
def empty?
|
|
114
|
+
@tokens.empty?
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns the number of tokens in the pattern.
|
|
118
|
+
def length
|
|
119
|
+
@tokens.length
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Return true if all tokens of the pattern are optional. If a token
|
|
123
|
+
# references a rule, this rule is followed for the check.
|
|
124
|
+
def optional?(rules)
|
|
125
|
+
@tokens.each do |token|
|
|
126
|
+
if token[0] == ?_ || token[0] == ?$
|
|
127
|
+
return false
|
|
128
|
+
elsif token[0] == ?!
|
|
129
|
+
token = token[1..-1]
|
|
130
|
+
if !rules[token].optional?(rules)
|
|
131
|
+
return false
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
true
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Returns true if the i-th token is a terminal symbol.
|
|
139
|
+
def terminalSymbol?(i)
|
|
140
|
+
@tokens[i][0] == ?$ || @tokens[i][0] == ?_
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Find recursively the first terminal token of this pattern. If an index is
|
|
144
|
+
# specified start the search at this n-th pattern token instead of the
|
|
145
|
+
# first. The return value is either nil or a [ token, pattern ] tuple.
|
|
146
|
+
def terminalToken(rules, index = 0)
|
|
147
|
+
# Terminal token start with an underscore or dollar character.
|
|
148
|
+
if @tokens[index][0] == ?_ || @tokens[index][0] == ?$
|
|
149
|
+
return [ @tokens[index].slice(1, @tokens[index].length - 1), self ]
|
|
150
|
+
elsif @tokens[index][0] == ?!
|
|
151
|
+
# Token starting with a bang reference another rule. We have to continue
|
|
152
|
+
# the search at this rule. First, we get rid of the bang to get the rule
|
|
153
|
+
# name.
|
|
154
|
+
token = @tokens[index].slice(1, @tokens[index].length - 1)
|
|
155
|
+
# Then find the rule
|
|
156
|
+
rule = rules[token]
|
|
157
|
+
# The rule may only have a single pattern. If not, then this pattern has
|
|
158
|
+
# no terminal token.
|
|
159
|
+
return nil if rule.patterns.length != 1
|
|
160
|
+
return rule.patterns[0].terminalToken(rules)
|
|
161
|
+
end
|
|
162
|
+
nil
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Returns a string that expresses the elements of the pattern in an EBNF
|
|
166
|
+
# like fashion. The resolution of the pattern is done recursively. This is
|
|
167
|
+
# just the wrapper function that sets up the stack.
|
|
168
|
+
def to_syntax(argDocs, rules, skip = 0)
|
|
169
|
+
to_syntax_r({}, argDocs, rules, skip)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def to_syntax_r(stack, argDocs, rules, skip)
|
|
173
|
+
# If we find ourself on the stack we hit a recursive pattern. This is used
|
|
174
|
+
# in repetitions.
|
|
175
|
+
if stack[self]
|
|
176
|
+
return '[, ... ]'
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# "Push" us on the stack.
|
|
180
|
+
stack[self] = true
|
|
181
|
+
|
|
182
|
+
str = ''
|
|
183
|
+
first = true
|
|
184
|
+
# Analyze the tokens of the pattern skipping the first 'skip' tokens.
|
|
185
|
+
skip.upto(@lastSyntaxToken) do |i|
|
|
186
|
+
token = @tokens[i]
|
|
187
|
+
# If the first token is a _{ the pattern describes optional attributes.
|
|
188
|
+
# They are represented by a standard idiom.
|
|
189
|
+
if first
|
|
190
|
+
first = false
|
|
191
|
+
return '{ <attributes> }' if token == '_{'
|
|
192
|
+
else
|
|
193
|
+
# Separate the syntax elemens by a whitespace.
|
|
194
|
+
str << ' '
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
typeId = token[0]
|
|
198
|
+
token = token.slice(1, token.length - 1)
|
|
199
|
+
|
|
200
|
+
if @args[i]
|
|
201
|
+
# The argument is documented in the syntax definition. We copy the
|
|
202
|
+
# entry as we need to modify it.
|
|
203
|
+
argDoc = @args[i].clone
|
|
204
|
+
|
|
205
|
+
# A documented argument without a name is a terminal token. We use the
|
|
206
|
+
# terminal symbol as name.
|
|
207
|
+
if @args[i].name.nil?
|
|
208
|
+
str << "#{token}"
|
|
209
|
+
argDoc.name = token
|
|
210
|
+
else
|
|
211
|
+
str << "<#{@args[i].name}>"
|
|
212
|
+
end
|
|
213
|
+
addArgDoc(argDocs, argDoc)
|
|
214
|
+
|
|
215
|
+
# Documented arguments don't have the type set yet. Use the token
|
|
216
|
+
# value for that.
|
|
217
|
+
if typeId == ?$
|
|
218
|
+
argDoc.typeSpec = "<#{token}>"
|
|
219
|
+
end
|
|
220
|
+
else
|
|
221
|
+
# Undocumented tokens are recursively expanded.
|
|
222
|
+
case typeId
|
|
223
|
+
when ?_
|
|
224
|
+
# Literals are shown as such.
|
|
225
|
+
str << token
|
|
226
|
+
when ?$
|
|
227
|
+
# Variables are enclosed by angle brackets.
|
|
228
|
+
str << '<' + token + '>'
|
|
229
|
+
when ?!
|
|
230
|
+
if rules[token].patterns.length == 1 &&
|
|
231
|
+
!rules[token].patterns[0].doc.nil?
|
|
232
|
+
addArgDoc(argDocs, TokenDoc.new(rules[token].patterns[0].keyword,
|
|
233
|
+
rules[token].patterns[0]))
|
|
234
|
+
str << '<' + rules[token].patterns[0].keyword + '>'
|
|
235
|
+
else
|
|
236
|
+
# References are followed recursively.
|
|
237
|
+
str << rules[token].to_syntax(stack, argDocs, rules, 0)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
# Remove us from the "stack" again.
|
|
243
|
+
stack.delete(self)
|
|
244
|
+
str
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def to_s
|
|
248
|
+
@tokens.join(' ')
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
private
|
|
252
|
+
|
|
253
|
+
def addArgDoc(argDocs, argDoc)
|
|
254
|
+
raise 'Error' if argDoc.name.nil?
|
|
255
|
+
argDocs.each do |ad|
|
|
256
|
+
return if ad.name == argDoc.name
|
|
257
|
+
end
|
|
258
|
+
argDocs << argDoc
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
end
|