### Home Classes Methods

### In Files

- lib/taskjuggler/TjpSyntaxRules.rb

### Methods

- #rule_absoluteTaskId
- #rule_account
- #rule_accountAttributes
- #rule_accountBody
- #rule_accountCredit
- #rule_accountCredits
- #rule_accountHeader
- #rule_accountId
- #rule_accountReport
- #rule_accountReportHeader
- #rule_accountScenarioAttributes
- #rule_aggregate
- #rule_alertLevel
- #rule_alertLevelDefinition
- #rule_alertLevelDefinitions
- #rule_allOrNone
- #rule_allocate
- #rule_allocateShiftAssignments
- #rule_allocateShiftsAssignments
- #rule_allocation
- #rule_allocationAttributes
- #rule_allocationBody
- #rule_allocationHeader
- #rule_allocationSelectionMode
- #rule_allocations
- #rule_argument
- #rule_argumentList
- #rule_argumentListBody
- #rule_author
- #rule_balance
- #rule_balanceAccounts
- #rule_bookingAttributes
- #rule_bookingBody
- #rule_calendarDuration
- #rule_chargeMode
- #rule_chargeSetItem
- #rule_chargeset
- #rule_chartScale
- #rule_color
- #rule_columnBody
- #rule_columnDef
- #rule_columnId
- #rule_columnOptions
- #rule_currencyFormat
- #rule_date
- #rule_dateCalcedOrNot
- #rule_declareFlagList
- #rule_details
- #rule_durationUnit
- #rule_durationUnitOrPercent
- #rule_export
- #rule_exportAttributes
- #rule_exportBody
- #rule_exportFormat
- #rule_exportFormats
- #rule_exportHeader
- #rule_extendAttributes
- #rule_extendBody
- #rule_extendId
- #rule_extendOptions
- #rule_extendOptionsBody
- #rule_extendProperty
- #rule_extendPropertyId
- #rule_fail
- #rule_flag
- #rule_flagList
- #rule_flagLogicalExpression
- #rule_flagOperand
- #rule_flagOperation
- #rule_flagOperationChain
- #rule_flagOperator
- #rule_flagOperatorAndOperand
- #rule_flags
- #rule_formats
- #rule_functionPatterns
- #rule_functions
- #rule_functionsBody
- #rule_hAlignment
- #rule_headline
- #rule_hideaccount
- #rule_hidejournalentry
- #rule_hideresource
- #rule_hidetask
- #rule_iCalReport
- #rule_iCalReportAttributes
- #rule_iCalReportBody
- #rule_iCalReportHeader
- #rule_idOrAbsoluteId
- #rule_includeAttributes
- #rule_includeAttributesBody
- #rule_includeFile
- #rule_includeFileName
- #rule_includeProperties
- #rule_interval
- #rule_intervalDuration
- #rule_intervalEnd
- #rule_intervalOptional
- #rule_intervalOptionalEnd
- #rule_intervalOrDate
- #rule_intervals
- #rule_intervalsOptional
- #rule_journalEntry
- #rule_journalEntryAttributes
- #rule_journalEntryBody
- #rule_journalEntryHeader
- #rule_journalReportAttributes
- #rule_journalReportMode
- #rule_journalSortCriteria
- #rule_journalSortCriterium
- #rule_leafResourceId
- #rule_leave
- #rule_leaveAllowance
- #rule_leaveAllowanceList
- #rule_leaveAllowances
- #rule_leaveList
- #rule_leaveName
- #rule_leaveType
- #rule_leaves
- #rule_limitAttributes
- #rule_limitAttributesBody
- #rule_limitValue
- #rule_limits
- #rule_limitsAttributes
- #rule_limitsBody
- #rule_limitsHeader
- #rule_listOfDays
- #rule_listOfTimes
- #rule_listType
- #rule_loadunit
- #rule_loadunitName
- #rule_logicalExpression
- #rule_macro
- #rule_moreAlternatives
- #rule_moreArguments
- #rule_moreBangs
- #rule_moreChargeSetItems
- #rule_moreColumnDef
- #rule_moreDepTasks
- #rule_moreExportFormats
- #rule_moreJournalSortCriteria
- #rule_moreListOfDays
- #rule_moreOutputFormats
- #rule_morePredTasks
- #rule_moreProjectIDs
- #rule_moreSortCriteria
- #rule_moreTimeIntervals
- #rule_navigator
- #rule_navigatorAttributes
- #rule_navigatorBody
- #rule_navigatorHeader
- #rule_nikuReport
- #rule_nikuReportAttributes
- #rule_nikuReportBody
- #rule_nikuReportHeader
- #rule_nodeId
- #rule_nodeIdList
- #rule_number
- #rule_numberFormat
- #rule_operand
- #rule_operation
- #rule_operationChain
- #rule_operator
- #rule_operatorAndOperand
- #rule_optionalID
- #rule_optionalMinus
- #rule_optionalPercent
- #rule_optionalScenarioIdCol
- #rule_optionalVersion
- #rule_outputFormat
- #rule_outputFormats
- #rule_plusOrMinus
- #rule_project
- #rule_projectBody
- #rule_projectBodyAttributes
- #rule_projectBodyInclude
- #rule_projectDeclaration
- #rule_projectHeader
- #rule_projectIDs
- #rule_projectProlog
- #rule_projectProperties
- #rule_projectPropertiesBody
- #rule_projection
- #rule_projectionAttributes
- #rule_prologInclude
- #rule_properties
- #rule_propertiesBody
- #rule_propertiesFile
- #rule_propertiesInclude
- #rule_purge
- #rule_referenceAttributes
- #rule_referenceBody
- #rule_relativeId
- #rule_reportAttributes
- #rule_reportBody
- #rule_reportEnd
- #rule_reportId
- #rule_reportIdUnverifd
- #rule_reportName
- #rule_reportPeriod
- #rule_reportProperties
- #rule_reportPropertiesBody
- #rule_reportPropertiesFile
- #rule_reportStart
- #rule_reportTitle
- #rule_reportableAttributes
- #rule_reports
- #rule_resource
- #rule_resourceAttributes
- #rule_resourceBody
- #rule_resourceBooking
- #rule_resourceBookingHeader
- #rule_resourceHeader
- #rule_resourceId
- #rule_resourceLeafList
- #rule_resourceList
- #rule_resourceReport
- #rule_resourceReportHeader
- #rule_resourceScenarioAttributes
- #rule_resourceShiftAssignments
- #rule_resourceShiftsAssignments
- #rule_rollupaccount
- #rule_rollupresource
- #rule_rolluptask
- #rule_scenario
- #rule_scenarioAttributes
- #rule_scenarioBody
- #rule_scenarioHeader
- #rule_scenarioId
- #rule_scenarioIdCol
- #rule_scenarioIdList
- #rule_scenarioIdx
- #rule_schedulingDirection
- #rule_shift
- #rule_shiftAssignment
- #rule_shiftAssignments
- #rule_shiftAttributes
- #rule_shiftBody
- #rule_shiftHeader
- #rule_shiftId
- #rule_shiftScenarioAttributes
- #rule_sortAccounts
- #rule_sortCriteria
- #rule_sortCriterium
- #rule_sortJournalEntries
- #rule_sortNonTree
- #rule_sortResources
- #rule_sortTasks
- #rule_sortTree
- #rule_ssReportAttributes
- #rule_ssReportBody
- #rule_ssReportHeader
- #rule_ssStatus
- #rule_ssStatusAttributes
- #rule_ssStatusBody
- #rule_ssStatusHeader
- #rule_statusSheet
- #rule_statusSheetAttributes
- #rule_statusSheetBody
- #rule_statusSheetFile
- #rule_statusSheetHeader
- #rule_statusSheetReport
- #rule_statusSheetTask
- #rule_statusSheetTaskAttributes
- #rule_statusSheetTaskBody
- #rule_statusSheetTaskHeader
- #rule_subNodeId
- #rule_summary
- #rule_supplement
- #rule_supplementAccount
- #rule_supplementReport
- #rule_supplementResource
- #rule_supplementTask
- #rule_tagfile
- #rule_tagfileAttributes
- #rule_tagfileBody
- #rule_tagfileHeader
- #rule_task
- #rule_taskAttributes
- #rule_taskBody
- #rule_taskBooking
- #rule_taskBookingHeader
- #rule_taskDep
- #rule_taskDepAttributes
- #rule_taskDepBody
- #rule_taskDepHeader
- #rule_taskDepId
- #rule_taskDepList
- #rule_taskHeader
- #rule_taskId
- #rule_taskIdUnverifd
- #rule_taskList
- #rule_taskPeriod
- #rule_taskPred
- #rule_taskPredHeader
- #rule_taskPredList
- #rule_taskReport
- #rule_taskReportHeader
- #rule_taskScenarioAttributes
- #rule_taskShiftAssignments
- #rule_taskShiftsAssignments
- #rule_textReport
- #rule_textReportHeader
- #rule_timeInterval
- #rule_timeSheet
- #rule_timeSheetAttributes
- #rule_timeSheetBody
- #rule_timeSheetFile
- #rule_timeSheetHeader
- #rule_timeSheetReport
- #rule_timeformat
- #rule_timezone
- #rule_traceReport
- #rule_traceReportHeader
- #rule_tsNewTaskHeader
- #rule_tsReportAttributes
- #rule_tsReportBody
- #rule_tsReportHeader
- #rule_tsStatus
- #rule_tsStatusAttributes
- #rule_tsStatusBody
- #rule_tsStatusHeader
- #rule_tsTaskAttributes
- #rule_tsTaskBody
- #rule_tsTaskHeader
- #rule_vacationName
- #rule_valDate
- #rule_valInterval
- #rule_valIntervalOrDate
- #rule_valIntervals
- #rule_validTimeZone
- #rule_warn
- #rule_weekDayInterval
- #rule_weekDayIntervalEnd
- #rule_weekday
- #rule_workingDuration
- #rule_workingDurationPercent
- #rule_workinghours
- #rule_workinghoursProject
- #rule_workinghoursResource
- #rule_workinghoursShift
- #rule_yesNo

### Files

- CHANGELOG
- COPYING
- README.rdoc

### Class/Module Index

Quicksearch

- TaskJuggler
- TaskJuggler::Account
- TaskJuggler::AccountAttribute
- TaskJuggler::AccountCredit
- TaskJuggler::AccountCreditListAttribute
- TaskJuggler::AccountListRE
- TaskJuggler::AccountScenario
- TaskJuggler::AlertLevelDefinition
- TaskJuggler::AlertLevelDefinitions
- TaskJuggler::Allocation
- TaskJuggler::AllocationAttribute
- TaskJuggler::AttributeBase
- TaskJuggler::AttributeDefinition
- TaskJuggler::AttributeOverwrite
- TaskJuggler::BatchProcessor
- TaskJuggler::Booking
- TaskJuggler::BookingListAttribute
- TaskJuggler::BooleanAttribute
- TaskJuggler::CSVFile
- TaskJuggler::CellSettingPattern
- TaskJuggler::CellSettingPatternList
- TaskJuggler::Charge
- TaskJuggler::ChargeListAttribute
- TaskJuggler::ChargeSet
- TaskJuggler::ChargeSetListAttribute
- TaskJuggler::ChartPlotter
- TaskJuggler::ChartPlotterError
- TaskJuggler::CollisionDetector
- TaskJuggler::ColumnListAttribute
- TaskJuggler::ColumnTable
- TaskJuggler::Daemon
- TaskJuggler::DaemonConnector
- TaskJuggler::DaemonConnectorMixin
- TaskJuggler::DataCache
- TaskJuggler::DataCacheEntry
- TaskJuggler::DateAttribute
- TaskJuggler::DefinitionListAttribute
- TaskJuggler::DependencyListAttribute
- TaskJuggler::DurationAttribute
- TaskJuggler::ExportRE
- TaskJuggler::FileList
- TaskJuggler::FileRecord
- TaskJuggler::FixnumAttribute
- TaskJuggler::FlagListAttribute
- TaskJuggler::FloatAttribute
- TaskJuggler::FormatListAttribute
- TaskJuggler::GanttChart
- TaskJuggler::GanttContainer
- TaskJuggler::GanttHeader
- TaskJuggler::GanttHeaderScaleItem
- TaskJuggler::GanttLine
- TaskJuggler::GanttLoadStack
- TaskJuggler::GanttMilestone
- TaskJuggler::GanttRouter
- TaskJuggler::GanttTaskBar
- TaskJuggler::HTMLDocument
- TaskJuggler::HTMLElements
- TaskJuggler::HTMLGraphics
- TaskJuggler::ICalReport
- TaskJuggler::ICalendar
- TaskJuggler::ICalendar::Component
- TaskJuggler::ICalendar::Event
- TaskJuggler::ICalendar::Journal
- TaskJuggler::ICalendar::Person
- TaskJuggler::ICalendar::Todo
- TaskJuggler::Interval
- TaskJuggler::IntervalList
- TaskJuggler::JobInfo
- TaskJuggler::Journal
- TaskJuggler::JournalEntry
- TaskJuggler::JournalEntryList
- TaskJuggler::JournalSortListAttribute
- TaskJuggler::KateSyntax
- TaskJuggler::KeywordArray
- TaskJuggler::KeywordDocumentation
- TaskJuggler::Leave
- TaskJuggler::LeaveAllowance
- TaskJuggler::LeaveAllowanceList
- TaskJuggler::LeaveAllowanceListAttribute
- TaskJuggler::LeaveList
- TaskJuggler::LeaveListAttribute
- TaskJuggler::Limits
- TaskJuggler::Limits::Limit
- TaskJuggler::LimitsAttribute
- TaskJuggler::ListAttributeBase
- TaskJuggler::Log
- TaskJuggler::LogicalAttribute
- TaskJuggler::LogicalExpression
- TaskJuggler::LogicalExpressionAttribute
- TaskJuggler::LogicalExpressionListAttribute
- TaskJuggler::LogicalFlag
- TaskJuggler::LogicalFunction
- TaskJuggler::LogicalOperation
- TaskJuggler::ManagerResponsibilities
- TaskJuggler::ManagerStatusRecord
- TaskJuggler::Message
- TaskJuggler::MessageHandler
- TaskJuggler::MessageHandlerInstance
- TaskJuggler::MspXmlRE
- TaskJuggler::Navigator
- TaskJuggler::NavigatorElement
- TaskJuggler::NikuProject
- TaskJuggler::NikuReport
- TaskJuggler::NikuResource
- TaskJuggler::NodeListAttribute
- TaskJuggler::PTNProxy
- TaskJuggler::Painter
- TaskJuggler::Painter::Circle
- TaskJuggler::Painter::Color
- TaskJuggler::Painter::Element
- TaskJuggler::Painter::Ellipse
- TaskJuggler::Painter::FontMetrics
- TaskJuggler::Painter::FontMetricsData
- TaskJuggler::Painter::Group
- TaskJuggler::Painter::Line
- TaskJuggler::Painter::Points
- TaskJuggler::Painter::PolyLine
- TaskJuggler::Painter::Primitives
- TaskJuggler::Painter::Rect
- TaskJuggler::Painter::SVGSupport
- TaskJuggler::Painter::Text
- TaskJuggler::PlaceHolderCell
- TaskJuggler::ProcessIntercom
- TaskJuggler::ProcessIntercomIface
- TaskJuggler::Project
- TaskJuggler::ProjectBroker
- TaskJuggler::ProjectBrokerIface
- TaskJuggler::ProjectFileParser
- TaskJuggler::ProjectFileScanner
- TaskJuggler::ProjectRecord
- TaskJuggler::ProjectServer
- TaskJuggler::ProjectServerIface
- TaskJuggler::PropertyAttribute
- TaskJuggler::PropertyList
- TaskJuggler::PropertySet
- TaskJuggler::PropertyTreeNode
- TaskJuggler::Query
- TaskJuggler::RTFHandlers
- TaskJuggler::RTFNavigator
- TaskJuggler::RTFQuery
- TaskJuggler::RTFReport
- TaskJuggler::RTFReportLink
- TaskJuggler::RTFWithQuerySupport
- TaskJuggler::RealFormat
- TaskJuggler::RealFormatAttribute
- TaskJuggler::ReferenceAttribute
- TaskJuggler::Report
- TaskJuggler::ReportBase
- TaskJuggler::ReportContext
- TaskJuggler::ReportScenario
- TaskJuggler::ReportServer
- TaskJuggler::ReportServerIface
- TaskJuggler::ReportServerRecord
- TaskJuggler::ReportServlet
- TaskJuggler::ReportTable
- TaskJuggler::ReportTableCell
- TaskJuggler::ReportTableColumn
- TaskJuggler::ReportTableLegend
- TaskJuggler::ReportTableLine
- TaskJuggler::Resource
- TaskJuggler::ResourceListAttribute
- TaskJuggler::ResourceListRE
- TaskJuggler::ResourceScenario
- TaskJuggler::RichText
- TaskJuggler::RichTextAttribute
- TaskJuggler::RichTextDocument
- TaskJuggler::RichTextElement
- TaskJuggler::RichTextFunctionExample
- TaskJuggler::RichTextFunctionHandler
- TaskJuggler::RichTextImage
- TaskJuggler::RichTextIntermediate
- TaskJuggler::RichTextParser
- TaskJuggler::RichTextScanner
- TaskJuggler::RichTextSnip
- TaskJuggler::RichTextSyntaxRules
- TaskJuggler::Scenario
- TaskJuggler::ScenarioData
- TaskJuggler::ScenarioListAttribute
- TaskJuggler::Scoreboard
- TaskJuggler::ScoreboardInterval
- TaskJuggler::SheetHandlerBase
- TaskJuggler::SheetReceiver
- TaskJuggler::SheetSender
- TaskJuggler::Shift
- TaskJuggler::ShiftAssignment
- TaskJuggler::ShiftAssignments
- TaskJuggler::ShiftAssignmentsAttribute
- TaskJuggler::ShiftScenario
- TaskJuggler::SimpleQueryExpander
- TaskJuggler::SortListAttribute
- TaskJuggler::StatusSheetReceiver
- TaskJuggler::StatusSheetReport
- TaskJuggler::StatusSheetSender
- TaskJuggler::StdIoWrapper
- TaskJuggler::StringAttribute
- TaskJuggler::SymbolAttribute
- TaskJuggler::SymbolListAttribute
- TaskJuggler::SyntaxReference
- TaskJuggler::TOCEntry
- TaskJuggler::TSResourceRecord
- TaskJuggler::TSTaskRecord
- TaskJuggler::TableColumnDefinition
- TaskJuggler::TableColumnSorter
- TaskJuggler::TableOfContents
- TaskJuggler::TableReport
- TaskJuggler::TableReportColumn
- TaskJuggler::TagFile
- TaskJuggler::TagFile::TagFileEntry
- TaskJuggler::Task
- TaskJuggler::TaskDepListAttribute
- TaskJuggler::TaskDependency
- TaskJuggler::TaskListAttribute
- TaskJuggler::TaskListRE
- TaskJuggler::TaskScenario
- TaskJuggler::TernarySearchTree
- TaskJuggler::TextFormatter
- TaskJuggler::TextParser
- TaskJuggler::TextParser::Macro
- TaskJuggler::TextParser::MacroTable
- TaskJuggler::TextParser::Pattern
- TaskJuggler::TextParser::Rule
- TaskJuggler::TextParser::Scanner
- TaskJuggler::TextParser::Scanner::BufferStreamHandle
- TaskJuggler::TextParser::Scanner::FileStreamHandle
- TaskJuggler::TextParser::Scanner::MacroStackEntry
- TaskJuggler::TextParser::Scanner::StreamHandle
- TaskJuggler::TextParser::SourceFileInfo
- TaskJuggler::TextParser::StackElement
- TaskJuggler::TextParser::State
- TaskJuggler::TextParser::StateTransition
- TaskJuggler::TextParser::TextParserResultArray
- TaskJuggler::TextParser::TokenDoc
- TaskJuggler::TextReport
- TaskJuggler::TimeInterval
- TaskJuggler::TimeIntervalListAttribute
- TaskJuggler::TimeSheet
- TaskJuggler::TimeSheetReceiver
- TaskJuggler::TimeSheetRecord
- TaskJuggler::TimeSheetReport
- TaskJuggler::TimeSheetSender
- TaskJuggler::TimeSheetSummary
- TaskJuggler::TimeSheets
- TaskJuggler::Tj3
- TaskJuggler::Tj3AppBase
- TaskJuggler::Tj3Client
- TaskJuggler::Tj3Daemon
- TaskJuggler::Tj3Man
- TaskJuggler::Tj3SheetAppBase
- TaskJuggler::Tj3SsReceiver
- TaskJuggler::Tj3SsSender
- TaskJuggler::Tj3TsReceiver
- TaskJuggler::Tj3TsSender
- TaskJuggler::Tj3TsSummary
- TaskJuggler::Tj3WebD
- TaskJuggler::TjException
- TaskJuggler::TjRuntimeError
- TaskJuggler::TjTime
- TaskJuggler::TjpExample
- TaskJuggler::TjpExportRE
- TaskJuggler::TjpSyntaxRules
- TaskJuggler::TraceReport
- TaskJuggler::URLParameter
- TaskJuggler::UserManual
- TaskJuggler::VimSyntax
- TaskJuggler::WebServer
- TaskJuggler::WelcomePage
- TaskJuggler::WorkingHours
- TaskJuggler::WorkingHoursAttribute
- TaskJuggler::XMLBlob
- TaskJuggler::XMLComment
- TaskJuggler::XMLDocument
- TaskJuggler::XMLElement
- TaskJuggler::XMLNamedText
- TaskJuggler::XMLText
- Diff
- Diff::Hunk
- AppConfig
- Diffable
- DiffableString
- Object
- RuntimeConfig
- String

No matching classes.

# TaskJuggler::TjpSyntaxRules

This module contains the rule definition for the TJP syntax. Every rule is put in a function who's name must start with rule_. The functions are not necessary but make the file more readable and receptable to syntax folding.

### Public Instance Methods

rule_absoluteTaskId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 19
    def rule_absoluteTaskId
      pattern(%( !taskIdUnverifd ), lambda {
        id = (@taskprefix.empty? ? '' : @taskprefix + '.') + @val[0]
        if (task = @project.task(id)).nil?
          error('unknown_abs_task', "Unknown task #{id}", @sourceFileInfo[0])
        end
        task
      })
    end

rule_account() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 29
    def rule_account
      pattern(%( !accountHeader !accountBody ), lambda {
         @property = @property.parent
      })
      doc('account', Declares an account. Accounts can be used to calculate costs of tasks or thewhole project. Account declaration may be nested, but only leaf accounts maybe used to track turnover. When the cost of a task is split over multipleaccounts they all must have the same top-level group account. Top-levelaccounts can be used for profit/loss calculations. The sub-account structureof a top-level account should be organized accordingly.Accounts have a global name space. All IDs must be unique within the accounts of the project.
         )
      example('Account', '1')
    end

rule_accountAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 47
    def rule_accountAttributes
      repeatable
      optional
      pattern(%( !account))
      pattern(%( !accountScenarioAttributes ))
      pattern(%( !scenarioIdCol !accountScenarioAttributes ), lambda {
        @scenarioIdx = 0
      })
      # Other attributes will be added automatically.
    end

rule_accountBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 58
    def rule_accountBody
      optionsRule('accountAttributes')
    end

rule_accountCredit() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 62
    def rule_accountCredit
      pattern(%( !valDate $STRING !number ), lambda {
        AccountCredit.new(@val[0], @val[1], @val[2])
      })
      arg(1, 'description', 'Short description of the transaction')
      arg(2, 'amount', 'Amount to be booked.')
    end

rule_accountCredits() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 70
    def rule_accountCredits
      listRule('moreAccountCredits', '!accountCredit')
    end

rule_accountHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 74
    def rule_accountHeader
      pattern(%( _account !optionalID $STRING ), lambda {
        if @property.nil? && !@accountprefix.empty?
          @property = @project.accout(@accountprefix)
        end
        if @val[1] && @project.account(@val[1])
          error('account_exists', "Account #{@val[1]} has already been defined.",
                @sourceFileInfo[1], @property)
        end
        @property = Account.new(@project, @val[1], @val[2], @property)
        @property.sourceFileInfo = @sourceFileInfo[0]
        @property.inheritAttributes
        @scenarioIdx = 0
      })
      arg(2, 'name', 'A name or short description of the account')
    end

rule_accountId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 91
    def rule_accountId
      pattern(%( $ID ), lambda {
        id = @val[0]
        id = @accountprefix + '.' + id unless @accountprefix.empty?
        # In case we have a nested supplement, we need to prepend the parent ID.
        id = @property.fullId + '.' + id if @property && @property.is_a?(Account)
        if (account = @project.account(id)).nil?
          error('unknown_account', "Unknown account #{id}", @sourceFileInfo[0])
        end
        account
      })
    end

rule_accountReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 104
    def rule_accountReport
      pattern(%( !accountReportHeader !reportBody ), lambda {
        @property = @property.parent
      })
      level(:beta)
      doc('accountreport', The report lists accounts and their respective values in a table. The reportcan operate in two modes:# Balance mode: If a [[balance]] has been set, the report will include thedefined cost and revenue accounts as well as all their sub accounts. To reducethe list of included accounts, you can use the [[hideaccount]],[[rollupaccount]] or [[accountroot]] attributes. The order of the task canbe controlled with [[sortaccounts]]. If the first sorting criteria is treesorting, the parent accounts will always be included to form the tree.Tree sorting is the default. You need to change it if you do not want certainparent accounts to be included in the report. Additionally, it will contain a line at the end that lists the balance (revenue - cost).# Normal mode: All reports are listed in the order and completeness as definedby the other report attributes. No balance line will be included.
         )
      example('AccountReport')
    end

rule_accountReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 129
    def rule_accountReportHeader
      pattern(%( _accountreport !optionalID !reportName ), lambda {
        newReport(@val[1], @val[2], :accountreport, @sourceFileInfo[0]) do
          unless @property.modified?('columns')
            # Set the default columns for this report.
            %( bsi name monthly ).each do |col|
              @property.get('columns') <<
              TableColumnDefinition.new(col, columnTitle(col))
            end
          end
          # Show all accounts, sorted by tree, seqno-up.
          unless @property.modified?('hideAccount')
            @property.set('hideAccount',
                          LogicalExpression.new(LogicalOperation.new(0)))
          end
          unless @property.modified?('sortAccounts')
            @property.set('sortAccounts',
                          [ [ 'tree', true, -1 ],
                            [ 'seqno', true, -1 ] ])
          end
        end
      })
    end

rule_accountScenarioAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 153
    def rule_accountScenarioAttributes
      pattern(%( _aggregate !aggregate ), lambda {
        @property.set('aggregate', @val[1])
      })
      doc('aggregate', Specifies whether the account is used to track task or resource specificamounts. The default is to track tasks.
         )
      example('AccountReport')

      pattern(%( _credits !accountCredits ), lambda {
        @property['credits', @scenarioIdx] += @val[1]
      })
      doc('credits', Book the specified amounts to the account at the specified date. Thedesciptions are just used for documentary purposes.
         )
      example('Account', '1')

      pattern(%( !flags ))
      doc('flags.account', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
         )

      # Other attributes will be added automatically.
    end

rule_aggregate() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 184
    def rule_aggregate
      pattern(%( _resources ), lambda {
        :resources
      })
      descr('Aggregate resources')

      pattern(%( _tasks ), lambda {
        :tasks
      })
      descr('Aggregate tasks')
    end

rule_alertLevel() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 196
    def rule_alertLevel
      pattern(%( $ID ), lambda {
        level = @project['alertLevels'].indexById(@val[0])
        unless level
          levels = @project['alertLevels'].map { |l| l.id }
          error('bad_alert', "Unknown alert level #{@val[0]}. Must be " +
                "one of #{levels.join(', ')}", @sourceFileInfo[0])
        end
        level
      })
      arg(0, 'alert level', By default supported values are ''''green'''', ''''yellow'''' and ''''red''''.The default value is ''''green''''. You can define your own levels with[[alertlevels]].
         )
    end

rule_alertLevelDefinition() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 214
    def rule_alertLevelDefinition
      pattern(%( $ID $STRING !color ), lambda {
        [ @val[0], @val[1], @val[2] ]
      })
      arg(0, 'ID', "A unique ID for the alert level")
      arg(1, 'color name', 'A unique name of the alert level color')
    end

rule_alertLevelDefinitions() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 222
    def rule_alertLevelDefinitions
      listRule('moreAlertLevelDefinitions', '!alertLevelDefinition')
    end

rule_allOrNone() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 413
    def rule_allOrNone
      pattern(%( _all ), lambda {
        1
      })
      pattern(%( _none ), lambda {
        0
      })
    end

rule_allocate() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 226
    def rule_allocate
      pattern(%( _allocate !allocations ), lambda {
        checkContainer('allocate')
        @property['allocate', @scenarioIdx] += @val[1]
      })
      doc('allocate', Specify which resources should be allocated to the task. Theattributes provide numerous ways to control which resource is used and whenexactly it will be assigned to the task. Shifts and limits can be used torestrict the allocation to certain time intervals or to limit them to acertain maximum per time period. The purge statement can be used to removeinherited allocations or flags.For effort-based tasks the task duration is clipped to only extend from thebegining of the first allocation to the end of the last allocation. This isdone to optimize for an overall minimum project duration as dependent taskscan potentially use the unallocated, clipped slots.
         )
      example('Allocate-1', '1')
    end

rule_allocateShiftAssignments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 401
    def rule_allocateShiftAssignments
      pattern(%( _shift ), lambda {
        @shiftAssignments = @allocate.shifts
      })
    end

rule_allocateShiftsAssignments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 407
    def rule_allocateShiftsAssignments
      pattern(%( _shifts ), lambda {
        @shiftAssignments = @allocate.shifts
      })
    end

rule_allocation() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 248
    def rule_allocation
      pattern(%( !allocationHeader !allocationBody ), lambda {
        @val[0]
      })
    end

rule_allocationAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 254
    def rule_allocationAttributes
      optional
      repeatable

      pattern(%( _alternative !resourceId !moreAlternatives ), lambda {
        ([ @val[1] ] + (@val[2] ? @val[2] : [])).each do |candidate|
          @allocate.addCandidate(candidate)
        end
      })
      doc('alternative', Specify which resources should be allocated to the task. The optionalattributes provide numerous ways to control which resource is used and whenexactly it will be assigned to the task. Shifts and limits can be used torestrict the allocation to certain time intervals or to limit them to acertain maximum per time period.
         )
      example('Alternative', '1')

      pattern(%( !limits ), lambda {
        limits = @property['limits', @scenarioIdx] = @val[0]
        @allocate.candidates.each do |resource|
           limits.limits.each do |l|
             l.resource = resource if resource.leaf?
           end
        end
      })
      level(:removed)
      doc('limits.allocate', '')

      pattern(%( _select !allocationSelectionMode ), lambda {
        @allocate.setSelectionMode(@val[1])
      })
      doc('select', The select functions controls which resource is picked from an allocation andit's alternatives. The selection is re-evaluated each time the resource usedin the previous time slot becomes unavailable.Even for non-persistent allocations a change in the resource selection onlyhappens if the resource used in the previous (or next for ASAP tasks) timeslot has become unavailable.
         )

      pattern(%( _persistent ), lambda {
        @allocate.persistent = true
      })
      doc('persistent', Specifies that once a resource is picked from the list of alternatives thisresource is used for the whole task. This is useful when several alternativeresources have been specified. Normally the selected resource can change aftereach break. A break is an interval of at least one timeslot where no resourceswere available.
         )

      pattern(%( _mandatory ), lambda {
        @allocate.mandatory = true
      })
      doc('mandatory', Makes a resource allocation mandatory. This means, that for each time slotonly then resources are allocated when all mandatory resources are available.So either all mandatory resources can be allocated for the time slot, or noresource will be allocated.
         )
      pattern(%( !allocateShiftAssignments !shiftAssignment ), lambda {
        begin
          @allocate.shifts = @shiftAssignments
        rescue AttributeOverwrite
          # Multiple shift assignments are a common idiom, so don't warn about
          # them.
        end
        @shiftAssignments = nil
      })
      level(:deprecated)
      also('shifts.allocate')
      doc('shift.allocate', Limits the allocations of resources during the specified interval to thespecified shift. Multiple shifts can be defined, but shift intervals may notoverlap. Allocation shifts are an additional restriction to the[[shifts.task|task shifts]] and [[shifts.resource|resource shifts]] or[[workinghours.resource|resource working hours]]. Allocations will only bemade for time slots that are specified as duty time in all relevant shifts.The restriction to the shift is only active during the specified timeinterval. Outside of this interval, no restrictions apply.
         )

      pattern(%( !allocateShiftsAssignments !shiftAssignments ), lambda {
        begin
          @allocate.shifts = @shiftAssignments
        rescue AttributeOverwrite
          # Multiple shift assignments are a common idiom, so don't warn about
          # them.
        end
        @shiftAssignments = nil
      })
      doc('shifts.allocate', Limits the allocations of resources during the specified interval to thespecified shift. Multiple shifts can be defined, but shift intervals may notoverlap. Allocation shifts are an additional restriction to the[[shifts.task|task shifts]] and [[shifts.resource|resource shifts]] or[[workinghours.resource|resource working hours]]. Allocations will only bemade for time slots that are specified as duty time in all relevant shifts.The restriction to the shift is only active during the specified timeinterval. Outside of this interval, no restrictions apply.
         )
    end

rule_allocationBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 365
    def rule_allocationBody
      optionsRule('allocationAttributes')
    end

rule_allocationHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 369
    def rule_allocationHeader
      pattern(%( !resourceId ), lambda {
        @allocate = Allocation.new([ @val[0] ])
      })
    end

rule_allocationSelectionMode() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 379
    def rule_allocationSelectionMode
      singlePattern('_maxloaded')
      descr('Pick the available resource that has been used the most so far.')

      singlePattern('_minloaded')
      descr('Pick the available resource that has been used the least so far.')

      singlePattern('_minallocated')
      descr(Pick the resource that has the smallest allocation factor. Theallocation factor is calculated from the various allocations of the resourceacross the tasks. This is the default setting.)
           )

      singlePattern('_order')
      descr('Pick the first available resource from the list.')

      singlePattern('_random')
      descr('Pick a random resource from the list.')
    end

rule_allocations() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 375
    def rule_allocations
      listRule('moreAllocations', '!allocation')
    end

rule_argument() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 422
    def rule_argument
      singlePattern('$ABSOLUTE_ID')
      singlePattern('!date')
      singlePattern('$ID')
      singlePattern('$INTEGER')
      singlePattern('$FLOAT')
    end

rule_argumentList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 430
    def rule_argumentList
      optional
      pattern(%( _( !argumentListBody _) ), lambda {
        @val[1].nil? ? [] : @val[1]
      })
    end

rule_argumentListBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 437
    def rule_argumentListBody
      optional
      pattern(%( !argument !moreArguments ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_author() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 444
    def rule_author
      pattern(%( _author !resourceId ), lambda {
        @journalEntry.author = @val[1]
      })
      doc('author', This attribute can be used to capture the authorship or source of theinformation.
         )
    end

rule_balance() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 455
    def rule_balance
      pattern(%( _balance !balanceAccounts ), lambda {
        @val[1]
      })
      doc('balance', During report generation, TaskJuggler can consider some accounts to be revenue accounts, while other can be considered cost accounts. By using the balance attribute, two top-level accounts can be designated for a profit-loss-analysis. This analysis includes all sub accounts of these two top-level accounts.To clear a previously set balance, just use a ''''-''''.
         )
      example('AccountReport')
    end

rule_balanceAccounts() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 468
    def rule_balanceAccounts
      pattern(%( !accountId !accountId ), lambda {
        if @val[0].parent
          error('cost_acct_no_top',
                "The cost account #{@val[0].fullId} is not a top-level account.",
                @sourceFileInfo[0])
        end
        if @val[1].parent
          error('rev_acct_no_top',
                "The revenue account #{@val[1].fullId} is not a top-level " +
                "account.", @sourceFileInfo[1])
        end
        if @val[0] == @val[1]
          error('cost_rev_same',
                'The cost and revenue accounts may not be the same.',
                @sourceFileInfo[0])
        end
        [ @val[0], @val[1] ]
      })
      arg(0, 'cost account', The top-level account that is used for all cost related charges.
         )
      arg(2, 'revenue account', The top-level account that is used for all revenue related charges.
         )

      pattern([ '_-' ], lambda {
        [ nil, nil ]
      })
    end

rule_bookingAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 501
    def rule_bookingAttributes
      optional
      repeatable

      pattern(%( _overtime $INTEGER ), lambda {
        if @val[1] < 0 || @val[1] > 2
          error('overtime_range',
                "Overtime value #{@val[1]} out of range (0 - 2).",
                @sourceFileInfo[1], @property)
        end
        @booking.overtime = @val[1]
      })
      doc('overtime.booking', This attribute enables bookings during off-hours and leaves. It implicitlysets the [[sloppy.booking|sloppy]] attribute accordingly.
         )
      arg(1, 'value', * '''0''': You can only book available working time. (Default)* '''1''': You can book off-hours as well.* '''2''': You can book working time, off-hours and vacation time.
         )

      pattern(%( _sloppy $INTEGER ), lambda {
        if @val[1] < 0 || @val[1] > 2
          error('sloppy_range',
                "Sloppyness value #{@val[1]} out of range (0 - 2).",
                @sourceFileInfo[1], @property)
        end
        @booking.sloppy = @val[1]
      })
      doc('sloppy.booking', Controls how strict TaskJuggler checks booking intervals for conflicts withworking periods and leaves. This attribute only affects the check forconflicts. No assignments will be made unless the [[overtime.booking|overtime]] attribute is set accordingly.
         )
      arg(1, 'sloppyness', * '''0''': Period may not contain any off-duty hours, vacation or other taskassignments. (default)* '''1''': Period may contain off-duty hours, but no vacation time or othertask assignments.* '''2''': Period may contain off-duty hours and vacation time, but no othertask assignments.
         )
    end

rule_bookingBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 555
    def rule_bookingBody
      optionsRule('bookingAttributes')
    end

rule_calendarDuration() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 559
    def rule_calendarDuration
      pattern(%( !number !durationUnit ), lambda {
        convFactors = [ 60.0, # minutes
                        60.0 * 60, # hours
                        60.0 * 60 * 24, # days
                        60.0 * 60 * 24 * 7, # weeks
                        60.0 * 60 * 24 * 30.4167, # months
                        60.0 * 60 * 24 * 365 # years
                       ]
        ((@val[0] * convFactors[@val[1]]) / @project['scheduleGranularity']).to_i
      })
      arg(0, 'value', 'A floating point or integer number')
    end

rule_chargeMode() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 612
    def rule_chargeMode
      singlePattern('_onstart')
      descr('Charge the amount on starting the task.')

      singlePattern('_onend')
      descr('Charge the amount on finishing the task.')

      singlePattern('_perhour')
      descr('Charge the amount for every hour the task lasts.')

      singlePattern('_perday')
      descr('Charge the amount for every day the task lasts.')

      singlePattern('_perweek')
      descr('Charge the amount for every week the task lasts.')
    end

rule_chargeSetItem() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 629
    def rule_chargeSetItem
      pattern(%( !accountId !optionalPercent ), lambda {
        if @property.is_a?(Task)
          aggregate = :tasks
        elsif @property.is_a?(Resource)
          aggregate = :resources
        else
          raise "Unknown property type #{@property.class}"
        end

        if @val[0].get('aggregate') != aggregate
          error('account_bad_aggregate',
                "The account #{@val[0].fullId} cannot aggregate amounts " +
                "related to #{aggregate}.")
        end

        [ @val[0], @val[1] ]
      })
      arg(0, 'account', 'The ID of a previously defined leaf account.')
      arg(1, 'share', 'A percentage between 0 and 100%')
    end

rule_chargeset() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 573
    def rule_chargeset
      pattern(%( _chargeset !chargeSetItem !moreChargeSetItems ), lambda {
        checkContainer('chargeset')
        items = [ @val[1] ]
        items += @val[2] if @val[2]
        chargeSet = ChargeSet.new
        begin
          items.each do |item|
            chargeSet.addAccount(item[0], item[1])
          end
          chargeSet.complete
        rescue TjException
          error('chargeset', $!.message, @sourceFileInfo[0], @property)
        end
        masterAccounts = []
        @property['chargeset', @scenarioIdx].each do |set|
          masterAccounts << set.master
        end
        if masterAccounts.include?(chargeSet.master)
          error('chargeset_master',
                "All charge sets for this property must have different " +
                "top-level accounts.", @sourceFileInfo[0], @property)
        end
        @property['chargeset', @scenarioIdx] =
          @property['chargeset', @scenarioIdx] + [ chargeSet ]
      })
      doc('chargeset', A chargeset defines how the turnover associated with the property will becharged to one or more accounts. A property may have any number of charge sets,but each chargeset must deal with a different top-level account. A charge setconsists of one or more accounts. Each account must be a leaf account. Theaccount ID may be followed by a percentage value that determines the share forthis account. The total percentage of all accounts must be exactly 100%. Ifsome accounts don't have a percentage specification, the remainder to 100% isdistributed evenly between them.
         )
    end

rule_chartScale() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 651
    def rule_chartScale
      singlePattern('_hour')
      descr('Set chart resolution to 1 hour.')

      singlePattern('_day')
      descr('Set chart resolution to 1 day.')

      singlePattern('_week')
      descr('Set chart resolution to 1 week.')

      singlePattern('_month')
      descr('Set chart resolution to 1 month.')

      singlePattern('_quarter')
      descr('Set chart resolution to 1 quarter.')

      singlePattern('_year')
      descr('Set chart resolution to 1 year.')
    end

rule_color() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 671
    def rule_color
      pattern(%( $STRING ), lambda {
        col = @val[0]
        unless /#[0-9A-Fa-f]{3}/ =~ col || /#[0-9A-Fa-f]{3}/ =~ col
          error('bad_color',
                "Color values must be specified as '#RGB' or '#RRGGBB' values",
                @sourceFileInfo[0])
        end
        col
      })
      arg(0, 'color', The RGB color values of the color. The following formats are supported: #RGBand #RRGGBB. Where R, G, B are hexadecimal values. See[http://en.wikipedia.org/wiki/Web_colors Wikipedia] for more details.
         )
    end

rule_columnBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 689
    def rule_columnBody
      optionsRule('columnOptions')
    end

rule_columnDef() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 693
    def rule_columnDef
      pattern(%( !columnId !columnBody ), lambda {
        @val[0]
      })
    end

rule_columnId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 699
    def rule_columnId
      pattern(%( !reportableAttributes ), lambda {
        @column = TableColumnDefinition.new(@val[0], columnTitle(@val[0]))
      })
      doc('columnid', This is a comprehensive list of all pre-defined [[columns]]. In addition tothe listed IDs all user defined attributes can be used as column IDs.
         )
    end

rule_columnOptions() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 710
    def rule_columnOptions
      optional
      repeatable

      pattern(%( _celltext !logicalExpression $STRING ), lambda {
        @column.cellText.addPattern(
          CellSettingPattern.new(newRichText(@val[2], @sourceFileInfo[2]),
                                 @val[1]))
      })
      doc('celltext.column', Specifies an alternative content that is used for the cells of the column.Usually such a text contains a query function. Otherwise all cells of thecolumn will have the same fixed value. The logical expression specifies forwhich cells the text should be used. If multiple celltext patterns areprovided for a column, the first matching one is taken for each cell.
          )
      arg(2, 'text',
          'Alterntive cell text specified as [[Rich_Text_Attributes|Rich Text]]')

      pattern(%( _cellcolor !logicalExpression !color ), lambda {
        @column.cellColor.addPattern(
          CellSettingPattern.new(@val[2], @val[1]))
      })
      doc('cellcolor.column', Specifies an alternative background color for the cells of this column. The[[logicalexpression|logical expression]] specifies for which cells the colorshould be used. If multiple cellcolor patterns are provided for a column, thefirst matching one is used for each cell.
         )

      pattern(%( _end !date ), lambda {
        @column.end = @val[1]
      })
      doc('end.column', Normally, columns with calculated values take the specified report period intoaccount when calculating their values. With this attribute, the user canspecify an end date for the period that should be used when calculating thevalues of this column. It does not have an impact on column with timeinvariant values.
         )

      pattern(%( _fontcolor !logicalExpression !color ), lambda {
        @column.fontColor.addPattern(
          CellSettingPattern.new(@val[2], @val[1]))
      })
      doc('fontcolor.column', Specifies an alternative font color for the cells of this column. The[[logicalexpression|logical expression]] specifies for which cells the colorshould be used. If multiple fontcolor patterns are provided for a column, thefirst matching one is used for each cell.
         )

      pattern(%( _halign !logicalExpression !hAlignment ), lambda {
        @column.hAlign.addPattern(
          CellSettingPattern.new(@val[2], @val[1]))
      })
      doc('halign.column', Specifies the horizontal alignment of the cell content. The[[logicalexpression|logical expression]] specifies for which cells the alignmentsetting should be used. If multiple halign patterns are provided for a column,the first matching one is used for each cell.
         )

      pattern(%( _listitem $STRING ), lambda {
        @column.listItem = @val[1]
      })
      doc('listitem.column', Specifies a RichText pattern that is used to generate the text for the listitems. The pattern should contain at least one ''''<nowiki><</nowiki>-queryattribute='XXX'->'''' element that will be replaced with the value ofattribute XXX. For the replacement, the property of the query will be the listitem.
         )

      pattern(%( _listtype !listType ), lambda {
        @column.listType = @val[1]
      })
      also(%( listitem.column ))
      doc('listtype.column', Specifies what type of list should be used. This attribute only affectscolumns that contain a list of items.
         )

      pattern(%( _period !interval ), lambda {
        @column.start = @val[1].start
        @column.end = @val[1].end
      })
      doc('period.column', This property is a shortcut for setting the [[start.column|start]] and[[end.column|end]] property at the same time.
         )

      pattern(%( _scale !chartScale ), lambda {
        @column.scale = @val[1]
      })
      doc('scale.column', Specifies the scale that should be used for a chart column. This value is ignored for all other columns.
         )

      pattern(%( _start !date ), lambda {
        @column.start = @val[1]
      })
      doc('start.column', Normally, columns with calculated values take the specified report period intoaccount when calculating their values. With this attribute, the user canspecify a start date for the period that should be used when calculating thevalues of this column. It does not have an impact on column with timeinvariant values.
         )

      pattern(%( _timeformat1 $STRING ), lambda {
        @column.timeformat1 = @val[1]
      })
      doc('timeformat1', Specify an alternative format for the upper header line of calendar or Ganttchart columns.
         )
      arg(1, 'format', 'See [[timeformat]] for details.')

      pattern(%( _timeformat2 $STRING ), lambda {
        @column.timeformat2 = @val[1]
      })
      doc('timeformat2', Specify an alternative format for the lower header line of calendar or Ganttchart columns.
         )
      arg(1, 'format', 'See [[timeformat]] for details.')

      pattern(%( _title $STRING ), lambda {
        @column.title = @val[1]
      })
      doc('title.column', Specifies an alternative title for a report column.
         )
      arg(1, 'text', 'The new column title.')

      pattern(%( _tooltip !logicalExpression $STRING ), lambda {
        @column.tooltip.addPattern(
          CellSettingPattern.new(newRichText(@val[2], @sourceFileInfo[2]),
                                 @val[1]))
      })
      doc('tooltip.column', Specifies an alternative content for the tooltip. This will replace theoriginal content of the tooltip that would be available for columns with textthat does not fit the column with.  The [[logicalexpression|logical expression]]specifies for which cells the text should be used. If multiple tooltippatterns are provided for a column, the first matching one is taken for eachcell.
         )
      arg(2, 'text', The content of the tooltip. The text is interpreted as [[Rich_Text_Attributes|Rich Text]].
         )

      pattern(%( _width !number ), lambda {
        @column.width = @val[1]
      })
      doc('width.column', Specifies the maximum width of the column in screen pixels. If the content ofthe column does not fit into this width, it will be cut off. In some cases ascrollbar is added or a tooltip window with the complete content is shown whenthe mouse is moved over the column. The latter is only supported ininteractive output formats. The resulting column width may be smaller if thecolumn has a fixed width (e. g. the chart column).
         )
    end

rule_currencyFormat() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 893
    def rule_currencyFormat
      pattern(%( _currencyformat $STRING $STRING $STRING $STRING $INTEGER ),
          lambda {
        RealFormat.new(@val.slice(1, 5))
      })
      doc('currencyformat',
          'These values specify the default format used for all currency ' +
          'values.')
      example('Currencyformat')
      arg(1, 'negativeprefix', 'Prefix for negative numbers')
      arg(2, 'negativesuffix', 'Suffix for negative numbers')
      arg(3, 'thousandsep', 'Separator used for every 3rd digit')
      arg(4, 'fractionsep', 'Separator used to separate the fraction digits')
      arg(5, 'fractiondigits', 'Number of fraction digits to show')
    end

rule_date() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 909
    def rule_date
      pattern(%( !dateCalcedOrNot ), lambda {
        resolution = @project.nil? ? Project.maxScheduleGranularity :
                                     @project['scheduleGranularity']
        if @val[0] % resolution != 0
          error('misaligned_date',
                "The date must be aligned to the timing resolution (" +
                "#{resolution / 60} min) of the project.",
                @sourceFileInfo[0])
        end
        @val[0]
      })
      doc('date', A DATE is date and time specification similar to the ISO 8601 date format.Instead of the hard to read ISO notation with a ''''T'''' between the date andtime sections, we simply use the more intuitive and easier to read dash:''''<nowiki>YYYY-MM-DD[-hh:mm[:ss]][-TIMEZONE]</nowiki>''''. Hour, minutes,seconds, and the ''''TIMEZONE'''' are optional. If not specified, the valuesare set to 0.  ''''TIMEZONE'''' must be an offset to GMT or UTC, specified as''''+HHMM'''' or ''''-HHMM''''. Dates must always be aligned with the[[timingresolution]].TaskJuggler also supports simple date calculations. You can add or substract agiven interval from a fixed date. %{2009-11-01 + 8m}This will result in an actual date of around 2009-07-01. Keep in mind that dueto the varying lengths of months TaskJuggler cannot add exactly 8 calendarmonths. The date calculation functionality makes most sense when used withmacros. %{${now} - 2w}This is result in a date 2 weeks earlier than the current (or specified) date.See [[duration]] for a complete list of supported time intervals. Don't forgetto put at least one space character after the date to prevent TaskJuggler frominterpreting the interval as an hour.Date attributes may be invalid in some cases. This needs special care in[[logicalexpression|logical expressions]].
         )
    end

rule_dateCalcedOrNot() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 954
    def rule_dateCalcedOrNot
      singlePattern('$DATE')
      pattern(%( _% _{ $DATE !plusOrMinus !intervalDuration _} ), lambda {
        @val[2] + ((@val[3] == '+' ? 1 : -1) * @val[4])
      })
    end

rule_declareFlagList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 961
    def rule_declareFlagList
      listRule('moreDeclareFlagList', '$ID')
    end

rule_details() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 965
    def rule_details
      pattern(%( _details $STRING ), lambda {
        return if @val[1].empty?

        rtTokenSetMore =
          [ :LINEBREAK, :SPACE, :WORD, :BOLD, :ITALIC, :CODE, :BOLDITALIC,
            :PRE, :HREF, :HREFEND, :REF, :REFEND, :HLINE, :TITLE2, :TITLE3,
            :TITLE4, :TITLE2END, :TITLE3END, :TITLE4END,
            :BULLET1, :BULLET2, :BULLET3, :BULLET4, :NUMBER1, :NUMBER2, :NUMBER3,
            :NUMBER4 ]
        if @val[1] == "Some more details\n"
          error('ts_default_details',
                "'Some more details' is not a valid value",
                @sourceFileInfo[1])
        end
        @journalEntry.details = newRichText(@val[1], @sourceFileInfo[1],
                                            rtTokenSetMore)
      })
      doc('details', This is a continuation of the [[summary]] of the journal or status entry. Itcan be several paragraphs long.
         )
      arg(1, 'text', The text will be interpreted as [[Rich_Text_Attributes|Rich Text]]. Only asubset of the markup is supported for this attribute. You can use wordformatting, paragraphs, hyperlinks, lists, section and subsectionheaders.
         )
    end

rule_durationUnit() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 997
    def rule_durationUnit
      pattern(%( _min ), lambda { 0 })
      descr('minutes')

      pattern(%( _h ), lambda { 1 })
      descr('hours')

      pattern(%( _d ), lambda { 2 })
      descr('days')

      pattern(%( _w ), lambda { 3 })
      descr('weeks')

      pattern(%( _m ), lambda { 4 })
      descr('months')

      pattern(%( _y ), lambda { 5 })
      descr('years')
    end

rule_durationUnitOrPercent() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1017
    def rule_durationUnitOrPercent
      pattern(%( _% ), lambda { -1 })
      descr('percentage of reported period')

      pattern(%( _min ), lambda { 0 })
      descr('minutes')

      pattern(%( _h ), lambda { 1 })
      descr('hours')

      pattern(%( _d ), lambda { 2 })
      descr('days')
    end

rule_export() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1031
    def rule_export
      pattern(%( !exportHeader !exportBody ), lambda {
        @property = @property.parent
      })
      doc('export', The export report looks like a regular TaskJuggler file with the providedinput data complemented by the results of the scheduling process. The contentof the report can be controlled with the [[definitions]] attribute. In casethe file contains the project header, a ''''.tjp'''' extension is added to thefile name. Otherwise, a ''''.tji'''' extension is used.The [[resourceattributes]] and [[taskattributes]] attributes provide even morecontrol over the content of the file.The export report can be used to share certain tasks or milestones with otherprojects or to save past resource allocations as immutable part for futurescheduling runs. When an export report is included the project IDs of theincluded tasks must be declared first with the project id property.
         )
      example('Export')
    end

rule_exportAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1054
    def rule_exportAttributes
      optional
      repeatable

      pattern(%( _definitions !exportDefinitions ), lambda {
        @property.set('definitions', @val[1])
      })
      doc('definitions', This attributes controls what definitions will be contained in the report. Ifthe list includes ''project'', the generated file will have a ''''.tjp''''extension. Otherwise it will have a ''''.tji'''' extension.By default, the report contains everything and the generated files has a ''''.tjp'''' extension.
         )
      allOrNothingListRule('exportDefinitions',
                           { 'flags' => 'Include flag definitions',
                             'project' => 'Include project header',
                             'projecids' => 'Include project IDs',
                             'tasks' => 'Include task definitions',
                             'resources' => 'Include resource definitions' })

      pattern(%( _formats !exportFormats ), lambda {
        @property.set('formats', @val[1])
      })
      level(:beta)
      doc('formats.export', This attribute defines for which output formats the export report should begenerated. By default, the TJP format will be used.
         )

      pattern(%( !hideresource ))
      pattern(%( !hidetask ))

      pattern(%( !loadunit ))

      pattern(%( !purge ))
      pattern(%( !reportEnd ))
      pattern(%( !reportPeriod ))
      pattern(%( !reports ))
      pattern(%( !reportStart ))

      pattern(%( _resourceattributes !exportableResourceAttributes ), lambda {
        @property.set('resourceAttributes', @val[1])
      })
      doc('resourceattributes', Define a list of resource attributes that should be included in the report.
         )
      allOrNothingListRule('exportableResourceAttributes',
                           { 'booking' => 'Include bookings',
                             'leaves' => 'Include leaves',
                             'workinghours' => 'Include working hours' })

      pattern(%( !rollupresource ))
      pattern(%( !rolluptask ))

      pattern(%( _scenarios !scenarioIdList ), lambda {
        # Don't include disabled scenarios in the report
        @val[1].delete_if { |sc| !@project.scenario(sc).get('active') }
        @property.set('scenarios', @val[1])
      })
      doc('scenarios.export', List of scenarios that should be included in the report. By default, allscenarios will be included. This attribute can be used to limit the includedscenarios to a defined list.
         )

      pattern(%( _taskattributes !exportableTaskAttributes ), lambda {
        @property.set('taskAttributes', @val[1])
      })
      doc('taskattributes', Define a list of task attributes that should be included in the report.
         )
      allOrNothingListRule('exportableTaskAttributes',
                           { 'booking' => 'Include bookings',
                             'complete' => 'Include completion values',
                             'depends' => 'Include dependencies',
                             'flags' => 'Include flags',
                             'maxend' => 'Include maximum end dates',
                             'maxstart' => 'Include maximum start dates',
                             'minend' =>  'Include minimum end dates',
                             'minstart' => 'Include minimum start dates',
                             'note' => 'Include notes',
                             'priority' => 'Include priorities',
                             'responsible' => 'Include responsible resource' })

      pattern(%( _taskroot !taskId), lambda {
        if @val[1].leaf?
          error('taskroot_leaf',
                "#{@val[1].fullId} is not a container task",
                @sourceFileInfo[1])
        end
        @property.set('taskroot', @val[1])
      })
      level(:experimental)
      doc('taskroot.export', Only tasks below the specified root-level tasks are exported. The exportedtasks will have the ID of the root-level task stripped from their ID, so thatthe sub-tasks of the root-level task become top-level tasks in the reportfile.
         )
      example('TaskRoot')

      pattern(%( _timezone !validTimeZone ), lambda {
        @property.set('timezone', @val[1])
      })
      doc('timezone.export',
          "Set the time zone to be used for all dates in the report.")
    end

rule_exportBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1169
    def rule_exportBody
      optionsRule('exportAttributes')
    end

rule_exportFormat() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1173
    def rule_exportFormat
      pattern(%( _tjp ), lambda {
        :tjp
      })
      descr('Export of the scheduled project in TJP syntax.')

      pattern(%( _mspxml ), lambda {
        :mspxml
      })
      descr(Export of the scheduled project in Microsoft Project XML format. This willexport the data of the fully scheduled project. The exported data include thetasks, resources and the assignments of resources to task. This is only asmall subset of the data that TaskJuggler can manage. This export is intendedto share resource assignment data with other teams using Microsoft Project.TaskJuggler manages assignments with a larger accuracy than the MicrosftProject XML format can represent. This will inevitably lead to some roundingerrors and different interpretation of the data. The numbers you will see inProject are not necessarily an exact match of the numbers you see inTaskJuggler.
           )
    end

rule_exportFormats() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1197
    def rule_exportFormats
      pattern(%( !exportFormat !moreExportFormats ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_exportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1203
    def rule_exportHeader
      pattern(%( _export !optionalID $STRING ), lambda {
        newReport(@val[1], @val[2], :export, @sourceFileInfo[0]) do
          unless @property.modified?('formats')
            @property.set('formats', [ :tjp ])
          end

          # By default, we export all scenarios.
          unless @property.modified?('scenarios')
            scenarios = Array.new(@project.scenarios.items) { |i| i }
            scenarios.delete_if { |sc| !@project.scenario(sc).get('active') }
            @property.set('scenarios', scenarios)
          end
          # Show all tasks, sorted by seqno-up.
          unless @property.modified?('hideTask')
            @property.set('hideTask',
                          LogicalExpression.new(LogicalOperation.new(0)))
          end
          unless @property.modified?('sortTasks')
            @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
          end
          # Show all resources, sorted by seqno-up.
          unless @property.modified?('hideResource')
            @property.set('hideResource',
                          LogicalExpression.new(LogicalOperation.new(0)))
          end
          unless @property.modified?('sortResources')
            @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
          end
        end
      })
      arg(2, 'file name', The name of the report file to generate. It must end with a .tjp or .tjiextension, or use . to use the standard output channel.
         )
    end

rule_extendAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1241
    def rule_extendAttributes
      optional
      repeatable

      pattern(%( _date !extendId  $STRING !extendOptionsBody ), lambda {
        # Extend the propertySet definition and parser rules
        if extendPropertySetDefinition(DateAttribute, nil)
          @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '!date' ], lambda {
              @property[@val[0], @scenarioIdx] = @val[1]
            }))
        else
          @ruleToExtend.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '!date' ], lambda {
              @property.set(@val[0], @val[1])
            }))
        end
      })
      doc('date.extend', Extend the property with a new attribute of type date.
         )
      arg(2, 'name', 'The name of the new attribute. It is used as header ' +
                     'in report columns and the like.')

      pattern(%( _number !extendId  $STRING !extendOptionsBody ), lambda {
        # Extend the propertySet definition and parser rules
        if extendPropertySetDefinition(FloatAttribute, nil)
          @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '!number' ], lambda {
              @property[@val[0], @scenarioIdx] = @val[1]
            }))
        else
          @ruleToExtend.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '!number' ], lambda {
              @property.set(@val[0], @val[1])
            }))
        end
      })
      doc('number.extend', Extend the property with a new attribute of type number. Possible values forthis attribute could be integer or floating point numbers.
         )
      arg(2, 'name', 'The name of the new attribute. It is used as header ' +
                     'in report columns and the like.')

      pattern(%( _reference !extendId $STRING !extendOptionsBody ), lambda {
        # Extend the propertySet definition and parser rules
        if extendPropertySetDefinition(ReferenceAttribute, nil)
          @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '$STRING', '!referenceBody' ], lambda {
              @property[@val[0], @scenarioIdx] = [ @val[1], @val[2] ]
            }))
        else
          @ruleToExtend.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '$STRING', '!referenceBody' ], lambda {
              @property.set(@val[0], [ @val[1], @val[2] ])
            }))
        end
      })
      doc('reference.extend', Extend the property with a new attribute of type reference. A reference is aURL and an optional text that will be shown instead of the URL if needed.
         )
      arg(2, 'name', 'The name of the new attribute. It is used as header ' +
                     'in report columns and the like.')

      pattern(%( _richtext !extendId $STRING !extendOptionsBody ), lambda {
        # Extend the propertySet definition and parser rules
        if extendPropertySetDefinition(RichTextAttribute, nil)
          @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '$STRING' ], lambda {
              @property[@val[0], @scenarioIdx] =
                newRichText(@val[1], @sourceFileInfo[1])
            }))
        else
          @ruleToExtend.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '$STRING' ], lambda {
              @property.set(@val[0], newRichText(@val[1], @sourceFileInfo[1]))
            }))
        end
      })
      doc('richtext.extend', Extend the property with a new attribute of type [[Rich_Text_Attributes|RichText]].
         )
      arg(2, 'name', 'The name of the new attribute. It is used as header ' +
                     'in report columns and the like.')

      pattern(%( _text !extendId $STRING !extendOptionsBody ), lambda {
        # Extend the propertySet definition and parser rules
        if extendPropertySetDefinition(StringAttribute, nil)
          @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '$STRING' ], lambda {
              @property[@val[0], @scenarioIdx] = @val[1]
            }))
        else
          @ruleToExtend.addPattern(TextParser::Pattern.new(
            [ '_' + @val[1], '$STRING' ], lambda {
              @property.set(@val[0], @val[1])
            }))
        end
      })
      doc('text.extend', Extend the property with a new attribute of type text. A text is a charactersequence enclosed in single or double quotes.
         )
      arg(2, 'name', 'The name of the new attribute. It is used as header ' +
                     'in report columns and the like.')

    end

rule_extendBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1357
    def rule_extendBody
      optionsRule('extendAttributes')
    end

rule_extendId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1361
    def rule_extendId
      pattern(%( $ID ), lambda {
        unless (AA..ZZ) === @val[0][0]
          error('extend_id_cap',
                "User defined attributes IDs must start with a capital letter",
                @sourceFileInfo[0])
        end
        @val[0]
      })
      arg(0, 'id', 'The ID of the new attribute. It can be used like the ' +
                   'built-in IDs.')
    end

rule_extendOptions() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1374
    def rule_extendOptions
      optional
      repeatable

      singlePattern('_inherit')
      doc('inherit.extend', If the this attribute is used, the property extension will be inherited bychild properties from their parent property.
         )

      singlePattern('_scenariospecific')
      doc('scenariospecific.extend', If this attribute is used, the property extension is scenario specific. Adifferent value can be set for each scenario.
         )
    end

rule_extendOptionsBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1393
    def rule_extendOptionsBody
      optionsRule('extendOptions')
    end

rule_extendProperty() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1397
    def rule_extendProperty
      pattern(%( !extendPropertyId ), lambda {
        case @val[0]
        when 'task'
          @ruleToExtend = @rules[:taskAttributes]
          @ruleToExtendWithScenario = @rules[:taskScenarioAttributes]
          @propertySet = @project.tasks
        when 'resource'
          @ruleToExtend = @rules[:resourceAttributes]
          @ruleToExtendWithScenario = @rules[:resourceScenarioAttributes]
          @propertySet = @project.resources
        end
      })
    end

rule_extendPropertyId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1412
    def rule_extendPropertyId
      singlePattern('_task')
      singlePattern('_resource')
    end

rule_fail() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1417
    def rule_fail
      pattern(%( _fail !logicalExpression ), lambda {
        begin
          @property.set('fail', @property.get('fail') + [ @val[1] ])
        rescue AttributeOverwrite
        end
      })
      doc('fail', The fail attribute adds a [[logicalexpression|logical expression]] to theproperty. The condition described by the logical expression is checked afterthe scheduling and an error is raised if the condition evaluates to true. Thisattribute is primarily intended for testing purposes.
         )
    end

rule_flag() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1433
    def rule_flag
      pattern(%( $ID ), lambda {
        unless @project['flags'].include?(@val[0])
          error('undecl_flag', "Undeclared flag '#{@val[0]}'",
                @sourceFileInfo[0])
        end
        @val[0]
      })
    end

rule_flagList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1547
    def rule_flagList
      listRule('moreFlagList', '!flag')
    end

rule_flagLogicalExpression() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1443
    def rule_flagLogicalExpression
      pattern(%( !flagOperation ), lambda {
        LogicalExpression.new(@val[0], sourceFileInfo)
      })
      doc('logicalflagexpression', A logical flag expression is a combination of operands and mathematicaloperations.  The final result of a logical expression is always true or false.Logical expressions are used the reduce the properties in a report to acertain subset or to select alternatives for the cell content of a table. Whenused with attributes like [[hidejournalentry]] the logical expressionevaluates to true for a certain property, this property is hidden or rolled-upin the report.Operands must be previously declared flags or another logical expression.When you combine logical operations to a more complex expression, theoperators are evaluated from left to right. '''a | b & c''' is identical to'''(a | b) & c'''. It's highly recommended that you always use brackets tocontrol the evaluation sequence. Currently, TaskJuggler does not support theconcept of operator precedence or right-left associativity. This may change inthe future.
         )
      also(%( functions ))
    end

rule_flagOperand() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1468
    def rule_flagOperand
      pattern(%( _( !flagOperation _) ), lambda {
        @val[1]
      })
      pattern(%( _~ !flagOperand ), lambda {
        operation = LogicalOperation.new(@val[1])
        operation.operator = '~'
        operation
      })

      pattern(%( $ID ), lambda {
        unless @project['flags'].include?(@val[0])
          error('operand_unkn_flag', "Undeclared flag '#{@val[0]}'",
                @sourceFileInfo[0])
        end
        LogicalFlag.new(@val[0])
      })
    end

rule_flagOperation() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1487
    def rule_flagOperation
      pattern(%( !flagOperand !flagOperationChain ), lambda {
        operation = LogicalOperation.new(@val[0])
        if @val[1]
          # Further operators/operands create an operation tree.
          @val[1].each do |ops|
            operation = LogicalOperation.new(operation)
            operation.operator = ops[0]
            operation.operand2 = ops[1]
          end
        end
        operation
      })
      arg(0, 'operand', An operand is a declared flag. An operand can be a negated operand byprefixing a ~ charater or it can be another logical expression enclosed inbraces.
          )
    end

rule_flagOperationChain() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1508
    def rule_flagOperationChain
      optional
      repeatable
      pattern(%( !flagOperatorAndOperand), lambda {
        @val[0]
      })
    end

rule_flagOperator() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1528
    def rule_flagOperator
      singlePattern('_|')
      descr('The \or\ operator')

      singlePattern('_&')
      descr('The \and\ operator')
    end

rule_flagOperatorAndOperand() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1516
    def rule_flagOperatorAndOperand
      pattern(%( !flagOperator !flagOperand), lambda{
        [ @val[0], @val[1] ]
      })
      arg(1, 'operand', An operand is a declared flag. An operand can be a negated operand byprefixing a ~ charater or it can be another logical expression enclosed inbraces.
          )
    end

rule_flags() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1537
    def rule_flags
      pattern(%( _flags !flagList ), lambda {
        @val[1].each do |flag|
          next if @property['flags', @scenarioIdx].include?(flag)

          @property['flags', @scenarioIdx] += [ flag ]
        end
      })
    end

rule_formats() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1551
    def rule_formats
      pattern(%( _formats !outputFormats ), lambda {
        @property.set('formats', @val[1])
      })
      doc('formats', This attribute defines for which output formats the report should begenerated. By default, this list is empty. Unless a formats attribute wasadded to a report definition, no output will be generated for this report.As reports are composable, a report may include other report definitions. Aformat definition is only needed for the outermost report that includes theothers.
         )
    end

rule_functionPatterns() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1612
    def rule_functionPatterns
      # This rule is not used by the parser. It's only for the documentation.
      pattern(%( _hasalert _( $INTEGER _, !date _) ))
      doc('hasalert', Will evaluate to true if the current property has a current alert message within the report time frame and with at least the provided alert level.
         )
      arg(2, 'Level', 'The minimum required alert level to be considered.')

      pattern(%( _isactive _( $ID _) ))
      doc('isactive', Will evaluate to true for tasks and resources if they have bookings inthe scenario during the report time frame.
         )
      arg(2, 'ID', 'A scenario ID')

      pattern(%( _ischildof _( $ID _) ))
      doc('ischildof', Will evaluate to true for tasks and resources if current property is a childof the provided parent property.
         )
      arg(2, 'ID', 'The ID of the parent')

      pattern(%( _isdependencyof _( $ID _, $ID _, $INTEGER _) ))
      doc('isdependencyof', Will evaluate to true for tasks that depend on the specified task inthe specified scenario and are no more than distance tasks away. Ifdistance is 0, all dependencies are considered independent of theirdistance.
         )
      arg(2, 'Task ID', 'The ID of a defined task')
      arg(4, 'Scenario ID', 'A scenario ID')
      arg(6, 'Distance', 'The maximum task distance to be considered')

      pattern(%( _isdutyof _( $ID _, $ID _) ))
      doc('isdutyof', Will evaluate to true for tasks that have the specified resourceassigned to it in the specified scenario.
         )
      arg(2, 'Resource ID', 'The ID of a defined resource')
      arg(4, 'Scenario ID', 'A scenario ID')

      pattern(%( _isfeatureof _( $ID _, $ID _) ))
      doc('isfeatureof', If the provided task or any of its sub-tasks depend on this task or any of itssub-tasks, we call this task a feature of the provided task.
         )
      arg(2, 'Task ID', 'The ID of a defined task')
      arg(4, 'Scenario ID', 'A scenario ID')

      pattern(['_isleaf', '_(', '_)' ])
      doc('isleaf', 'The result is true if the property is not a container.')

      pattern(%( _ismilestone _( $ID _) ))
      doc('ismilestone', The result is true if the property is a milestone in the provided scenario.
         )
      arg(2, 'Scenario ID', 'A scenario ID')

      pattern(%( _isongoing _( $ID _) ))
      doc('isongoing', Will evaluate to true for tasks that overlap with the report period in givenscenario.
         )
      arg(2, 'ID', 'A scenario ID')

      pattern(['_isresource', '_(', '_)' ])
      doc('isresource', 'The result is true if the property is a resource.')

      pattern(%( _isresponsibilityof _( $ID _, $ID _) ))
      doc('isresponsibilityof', Will evaluate to true for tasks that have the specified resourceassigned as [[responsible]] in the specified scenario.
         )
      arg(2, 'Resource ID', 'The ID of a defined resource')
      arg(4, 'Scenario ID', 'A scenario ID')

      pattern(['_istask', '_(', '_)' ])
      doc('istask', 'The result is true if the property is a task.')

      pattern(%( _isvalid _( $ID _) ))
      doc('isvalid', 'Returns false if argument is not an assigned or ' +
                     'properly computed value.')

      pattern(%( _treelevel _( _) ))
      doc('treelevel', Returns the nesting level of a property in the property tree.Top level properties have a level of 1, their children 2 and so on.
         )
    end

rule_functions() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1567
    def rule_functions
      # This rule is not used by the parser. It's only for the documentation.
      pattern(%( !functionsBody ))
      doc('functions', The following functions are supported in logical expressions. These functionsare evaluated in logical conditions such as hidetask or rollupresource. Forthe evaluation, implicit and explicit parameters are used.All functions may operate on the current property and the scope property. Thescope property is the enclosing property in reports with nested properties.Imagine e. g a task report with nested resources. When the function is calledfor a task line, the task is the property and we don't have a scope property.When the function is called for a resource line, the resource is the propertyand the enclosing task is the scope property.These number of arguments that are passed in brackets to the function dependson the specific function. See the reference for details on each function.All functions can be suffixed with an underscore character. In that case, thefunction is operating on the scope property as if it were the property. Theoriginal property is ignored in that case. In our task report example fromabove, calling a function with an appended dash would mean that a taskline would be evaluated for the enclosing resource.In the example below you can see how this can be used. To generate a taskreport that lists all assigned leaf resources for leaf task lines only we usethe expression hideresource ~(isleaf() & isleaf_())The tilde in front of the bracketed expression means not that expression. Inother words: show resources that are leaf resources and show them for leaftasks only. The regular form isleaf() (without the appended underscore)operates on the resource. The isleaf_() variant operates on theenclosing task.
         )
      example('LogicalFunction', '1')
    end

rule_functionsBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1607
    def rule_functionsBody
      # This rule is not used by the parser. It's only for the documentation.
      optionsRule('functionPatterns')
    end

rule_hAlignment() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1712
    def rule_hAlignment
      pattern(%( _center ), lambda {
        :center
      })
      doc('halign.center', 'Center the cell content')

      pattern(%( _left ), lambda {
        :left
      })
      doc('halign.left', 'Left align the cell content')

      pattern(%( _right ), lambda {
        :right
      })
      doc('halign.right', 'Right align the cell content')
    end

rule_headline() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1729
    def rule_headline
      pattern(%( _headline $STRING ), lambda {
        @property.set('headline', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('headline', Specifies the headline for a report.
         )
      arg(1, 'text', The text used for the headline. It is interpreted as[[Rich_Text_Attributes|Rich Text]].
         )
    end

rule_hideaccount() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1744
    def rule_hideaccount
      pattern(%( _hideaccount !logicalExpression ), lambda {
        @property.set('hideAccount', @val[1])
      })
      doc('hideaccount', Do not include accounts that match the specified [[logicalexpression|logicalexpression]]. If the report is sorted in ''''tree'''' mode (default) thenenclosing accounts arelisted even if the expression matches the account.
         )
      also(%( sortaccounts ))
    end

rule_hidejournalentry() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1758
    def rule_hidejournalentry
      pattern(%( _hidejournalentry !flagLogicalExpression ), lambda {
        @property.set('hideJournalEntry', @val[1])
      })
      doc('hidejournalentry', Do not include journal entries that match the specified logical expression.
         )
    end

rule_hideresource() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1768
    def rule_hideresource
      pattern(%( _hideresource !logicalExpression ), lambda {
        @property.set('hideResource', @val[1])
      })
      doc('hideresource', Do not include resources that match the specified [[logicalexpression|logicalexpression]]. If the report is sorted in ''''tree'''' mode (default) thenenclosing resources are listed even if the expression matches the resource.
         )
      also(%( sortresources ))
    end

rule_hidetask() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1781
    def rule_hidetask
      pattern(%( _hidetask !logicalExpression ), lambda {
        @property.set('hideTask', @val[1])
      })
      doc('hidetask', Do not include tasks that match the specified [[logicalexpression|logicalexpression]]. If the report is sorted in ''''tree'''' mode (default) thenenclosing tasks are listed even if the expression matches the task.
         )
      also(%( sorttasks ))
    end

rule_iCalReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1793
    def rule_iCalReport
      pattern(%( !iCalReportHeader !iCalReportBody ), lambda {
        @property = nil
      })
      doc('icalreport', Generates an RFC5545 compliant iCalendar file. This file can be used to exporttask information to calendar applications or other tools that read iCalendarfiles.
         )
    end

rule_iCalReportAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1808
    def rule_iCalReportAttributes
      optional
      repeatable

      pattern(%( !hideresource ))
      pattern(%( !hidejournalentry ))
      pattern(%( !hidetask ))
      pattern(%( !reportEnd ))
      pattern(%( !reportPeriod ))
      pattern(%( !reportStart ))
      pattern(%( !rollupresource ))
      pattern(%( !rolluptask ))

      pattern(%( _scenario !scenarioId ), lambda {
        # Don't include disabled scenarios in the report
        sc = @val[1]
        unless @project.scenario(sc).get('active')
          warning('ical_sc_disabled',
                  "Scenario #{sc} has been disabled")
        else
          @property.set('scenarios', [ @val[1] ])
        end
      })
      doc('scenario.ical', Id of the scenario that should be included in the report. By default, thetop-level scenario will be included. This attribute can be used select anotherscenario.
         )
    end

rule_iCalReportBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1804
    def rule_iCalReportBody
      optionsRule('iCalReportAttributes')
    end

rule_iCalReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1839
    def rule_iCalReportHeader
      pattern(%( _icalreport !optionalID $STRING ), lambda {
        newReport(@val[1], @val[2], :iCal, @sourceFileInfo[0]) do
          @property.set('formats', [ :iCal ])

          # By default, we export only the first scenario.
          unless @project.scenario(0).get('active')
            @property.set('scenarios', [ 0 ])
          end
          # Show all tasks, sorted by seqno-up.
          @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
          # Show all resources, sorted by seqno-up.
          @property.set('hideResource',
                        LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
          # Show all journal entries.
          @property.set('hideJournalEntry',
                        LogicalExpression.new(LogicalOperation.new(0)))
        end
      })
      arg(1, 'file name', The name of the report file to generate without an extension.  Use . to usethe standard output channel.
         )
    end

rule_idOrAbsoluteId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1867
    def rule_idOrAbsoluteId
      singlePattern('$ID')
      singlePattern('$ABSOLUTE_ID')
    end

rule_includeAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1872
    def rule_includeAttributes
      optionsRule('includeAttributesBody')
    end

rule_includeAttributesBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1876
    def rule_includeAttributesBody
      optional
      repeatable

      pattern(%( _accountprefix !accountId ), lambda {
        @accountprefix = @val[1].fullId
      })
      doc('accountprefix', This attribute can be used to insert the accounts of the included file assub-account of the account specified by ID. The parent account must already bedefined.
      )
      arg(1, 'account ID', 'The absolute ID of an already defined account')

      pattern(%( _reportprefix !reportId ), lambda {
        @reportprefix = @val[1].fullId
      })
      doc('reportprefix', This attribute can be used to insert the reports of the included file assub-report of the report specified by ID. The parent report must alreadybe defined.
      )
      arg(1, 'report ID', 'The absolute ID of an already defined report.')

      pattern(%( _resourceprefix !resourceId ), lambda {
        @resourceprefix = @val[1].fullId
      })
      doc('resourceprefix', This attribute can be used to insert the resources of the included file assub-resource of the resource specified by ID. The parent resource must alreadybe defined.
      )
      arg(1, 'resource ID', 'The ID of an already defined resource')

      pattern(%( _taskprefix !taskId ), lambda {
        @taskprefix = @val[1].fullId
      })
      doc('taskprefix', This attribute can be used to insert the tasks of the included file assub-task of the task specified by ID. The parent task must already be defined.
      )
      arg(1, 'task ID', 'The absolute ID of an already defined task.')
    end

rule_includeFile() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1924
    def rule_includeFile
      pattern(%( !includeFileName ), lambda {
        unless @project
          error('include_before_project',
                "You must declare the project header before you include other " +
                "files.")
        end
        @project.inputFiles << @scanner.include(@val[0], @sourceFileInfo[0]) do
          popFileStack
        end
      })
    end

rule_includeFileName() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1937
    def rule_includeFileName
      pattern(%( $STRING ), lambda {
        unless @val[0][-4, 4] == '.tji'
          error('bad_include_suffix', "Included files must have a '.tji'" +
                                      "extension: '#{@val[0]}'",
                @sourceFileInfo[0])
        end
        pushFileStack
        @val[0]
      })
      arg(0, 'filename', Name of the file to include. This must have a ''''.tji'''' extension. The namemay have an absolute or relative path. You need to use ''''/'''' characters toseparate directories.
         )
    end

rule_includeProperties() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1955
    def rule_includeProperties
      pattern(%( !includeFileName !includeAttributes ), lambda {
        @project.inputFiles << @scanner.include(@val[0], @sourceFileInfo[0]) do
          popFileStack
        end
      })
    end

rule_interval() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1995
    def rule_interval
      pattern(%( !date !intervalEnd ), lambda {
        mode = @val[1][0]
        endSpec = @val[1][1]
        if mode == 0
          unless @val[0] < endSpec
            error('start_before_end', "The end date (#{endSpec}) must be after " +
                  "the start date (#{@val[0]}).", @sourceFileInfo[0])
          end
          TimeInterval.new(@val[0], endSpec)
        else
          TimeInterval.new(@val[0], @val[0] + endSpec)
        end
      })
      doc('interval2', There are two ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form specifies the start date and an interval duration. Theduration must be prefixed by a plus character.
         )
    end

rule_intervalDuration() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2022
    def rule_intervalDuration
      pattern(%( !number !durationUnit ), lambda {
        convFactors = [ 60, # minutes
                        60 * 60, # hours
                        60 * 60 * 24, # days
                        60 * 60 * 24 * 7, # weeks
                        60 * 60 * 24 * 30.4167, # months
                        60 * 60 * 24 * 365 # years
                       ]
        if @val[0] == 0.0
          error('zero_duration', "The interval duration may not be 0.",
                @sourceFileInfo[1])
        end
        duration = (@val[0] * convFactors[@val[1]]).to_i
        resolution = @project.nil? ? 60 * 60 : @project['scheduleGranularity']
        if @val[1] == 4
          # If the duration unit is months, we have to align the duration with
          # the timing resolution of the project.
          duration = (duration / resolution).to_i * resolution
        end
        # Make sure the interval aligns with the timing resolution.
        if duration % resolution != 0
          error('iv_duration_not_aligned',
                "The interval duration must be a multiple of the specified " +
                "timing resolution (#{resolution / 60} min) of the project.")
        end
        duration
      })
      arg(0, 'duration', 'The duration of the interval. May not be 0 and must ' +
                         'be a multiple of [[timingresolution]].')
    end

rule_intervalEnd() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2054
    def rule_intervalEnd
      pattern([ '_-', '!date' ], lambda {
        [ 0, @val[1] ]
      })

      pattern(%( _+ !intervalDuration ), lambda {
        [ 1, @val[1] ]
      })
    end

rule_intervalOptional() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2079
    def rule_intervalOptional
      optional
      singlePattern('!interval')
    end

rule_intervalOptionalEnd() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2064
    def rule_intervalOptionalEnd
      optional
      pattern([ '_-', '!date' ], lambda {
        [ 0, @val[1] ]
      })

      pattern(%( _+ !intervalDuration ), lambda {
        [ 1, @val[1] ]
      })
    end

rule_intervalOrDate() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 1963
    def rule_intervalOrDate
      pattern(%( !date !intervalOptionalEnd ), lambda {
        if @val[1]
          mode = @val[1][0]
          endSpec = @val[1][1]
          if mode == 0
            unless @val[0] < endSpec
              error('start_before_end', "The end date (#{endSpec}) must be " +
                    "after the start date (#{@val[0]}).", @sourceFileInfo[0])
            end
            TimeInterval.new(@val[0], endSpec)
          else
            TimeInterval.new(@val[0], @val[0] + endSpec)
          end
        else
          TimeInterval.new(@val[0], @val[0].sameTimeNextDay)
        end
      })
      doc('interval3', There are three ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form, the end date is omitted. A 24 hour interval is assumed.The third form specifies the start date and an interval duration. The duration must be prefixed by a plus character.
         )
    end

rule_intervals() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2075
    def rule_intervals
      listRule('moreIntervals', '!intervalOrDate')
    end

rule_intervalsOptional() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2084
    def rule_intervalsOptional
      optional
      singlePattern('!intervals')
    end

rule_journalEntry() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2175
    def rule_journalEntry
      pattern(%( !journalEntryHeader !journalEntryBody ), lambda {
        @val[0]
      })
      doc('journalentry', This attribute adds an entry to the journal of the project. A journal can beused to record events, decisions or news that happened at a particular momentduring the project. Depending on the context, a journal entry may or may notbe associated with a specific property or author.A journal entry can consists of up to three parts. The headline is mandatoryand should be only 5 to 10 words long. The introduction is optional and shouldbe only one or two sentences long. All other details should be put into thethird part.Depending on the context, journal entries are listed with headlines only, asheadlines plus introduction or in full.
         )
    end

rule_journalEntryAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2196
    def rule_journalEntryAttributes
      optional
      repeatable

      pattern(%( _alert !alertLevel ), lambda {
        @journalEntry.alertLevel = @val[1]
      })
      doc('alert', Specify the alert level for this entry. This attribute is inteded to be used forstatus reporting. When used for a journal entry that is associated with aproperty, the value can be reported in the alert column. When multiple entrieshave been specified for the property, the entry with the date closest to thereport end date will be used. Container properties will inherit the highestalert level of all its sub properties unless it has an own journal entry datedcloser to the report end than all of its sub properties.
         )

      pattern(%( !author ))

      pattern(%( _flags !flagList ), lambda {
        @val[1].each do |flag|
          next if @journalEntry.flags.include?(flag)

          @journalEntry.flags << flag
        end
      })
      doc('flags.journalentry', Journal entries can have flags attached to them. These can be used toinclude only entries in a report that have a certain flag.
         )

      pattern(%( !summary ))

      pattern(%( !details ))
    end

rule_journalEntryBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2234
    def rule_journalEntryBody
      optionsRule('journalEntryAttributes')
    end

rule_journalEntryHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2238
    def rule_journalEntryHeader
      pattern(%( _journalentry !valDate $STRING ), lambda {
        @journalEntry = JournalEntry.new(@project['journal'], @val[1], @val[2],
                                         @property, @sourceFileInfo[0])
      })
      arg(2, 'headline', The headline of the journal entry. It will be interpreted as[[Rich_Text_Attributes|Rich Text]].
         )
    end

rule_journalReportAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2089
    def rule_journalReportAttributes
      pattern(%( _journalattributes !journalReportAttributesList ), lambda {
        @property.set('journalAttributes', @val[1])
      })
      doc('journalattributes', A list that determines which of the journal attributes should be included inthe journal report.
         )
      allOrNothingListRule('journalReportAttributesList',
                           { 'alert' => 'Include the alert status',
                             'author' => 'Include the author if known',
                             'date' => 'Include the date',
                             'details' => 'Include the details',
                             'flags' => 'Include the flags',
                             'headline' => 'Include the headline',
                             'property' => 'Include the task or resource name',
                             'propertyid' => 'Include the property ID. ' +
                                             'Requires \property\.',
                             'summary' => 'Include the summary',
                             'timesheet' => 'Include the timesheet information.' +
                                            ' Requires \property\.'})
    end

rule_journalReportMode() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2113
    def rule_journalReportMode
      pattern(%( _journal ), lambda { :journal })
      descr(This is the regular journal. It contains all journal entries that are dated inthe query interval. If a property is given, only entries of this property areincluded. Without a property context, all the project entries are includedunless hidden by other attributes like [[hidejournalentry]].
         )
      pattern(%( _journal_sub ), lambda { :journal_sub })
      descr(This mode only yields entries if used in the context of a task. It containsall journal entries that are dated in the query interval for the task and allits sub tasks.
         )
      pattern(%( _status_dep ), lambda { :status_dep })
      descr(In this mode only the last entries before the report end date for eachproperty and all its sub-properties and their dependencies are included. Ifthere are multiple entries at the exact same date, then all these entries areincluded.
         )
      pattern(%( _status_down ), lambda { :status_down })
      descr(In this mode only the last entries before the report end date for eachproperty and all its sub-properties are included. If there are multiple entriesat the exact same date, then all these entries are included.
         )
      pattern(%( _status_up ), lambda { :status_up })
      descr(In this mode only the last entries before the report end date for eachproperty are included. If there are multiple entries at the exact same date,then all these entries are included. If any of the parent properties has amore recent entry that is still before the report end date, no entries will beincluded.
         )
      pattern(%( _alerts_dep ), lambda { :alerts_dep })
      descr(In this mode only the last entries before the report end date for the contextproperty and all its sub-properties and their dependencies is included. Ifthere are multiple entries at the exact same date, then all these entries areincluded. In contrast to the ''''status_down'''' mode, only entries with analert level above the default level, and only those with the highest overallalert level are included.
         )
      pattern(%( _alerts_down ), lambda { :alerts_down })
      descr(In this mode only the last entries before the report end date for the contextproperty and all its sub-properties is included. If there are multiple entriesat the exact same date, then all these entries are included. In contrast tothe ''''status_down'''' mode, only entries with an alert level above thedefault level, and only those with the highest overall alert level areincluded.
         )
    end

rule_journalSortCriteria() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2250
    def rule_journalSortCriteria
      pattern(%( !journalSortCriterium !moreJournalSortCriteria ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_journalSortCriterium() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2256
    def rule_journalSortCriterium
      pattern(%( $ABSOLUTE_ID ), lambda {
        supported = []
        JournalEntryList::SortingAttributes.each do |attr|
          supported << "#{attr}.up"
          supported << "#{attr}.down"
        end
        unless supported.include?(@val[0])
          error('bad_journal_sort_criterium',
                "Unsupported sorting criterium #{@val[0]}. Must be one of " +
                "#{supported.join(', ')}.")
        end
        attr, direction = @val[0].split('.')
        [ attr.intern, direction == 'up' ? 1 : -1 ]
      })
    end

rule_leafResourceId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2273
    def rule_leafResourceId
      pattern(%( !resourceId ), lambda {
        resource = @val[0]
        unless resource.leaf?
          error('leaf_resource_id_expected',
                "#{resource.id} is not a leaf resource.", @sourceFileInfo[0])
        end
        resource
      })
      arg(0, 'resource', 'The ID of a leaf resource')
    end

rule_leave() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2285
    def rule_leave
      pattern(%( !leaveType !vacationName !intervalOrDate ), lambda {
        Leave.new(@val[0].intern, @val[2], @val[1])
      })
    end

rule_leaveAllowance() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2303
    def rule_leaveAllowance
      pattern(%( _annual !valDate !optionalMinus !workingDuration ), lambda {
        LeaveAllowance.new(:annual, @val[1], (@val[2] ? -1 : 1) * @val[3])
      })
    end

rule_leaveAllowanceList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2309
    def rule_leaveAllowanceList
      listRule('moreLeaveAllowanceList', '!leaveAllowance')
    end

rule_leaveAllowances() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2313
    def rule_leaveAllowances
      pattern(%( _leaveallowances !leaveAllowanceList ), lambda {
        appendScListAttribute('leaveallowances', @val[1])
      })
      doc('leaveallowance', Add or subtract leave allowances. Currently, only allowances for the annualleaves are supported. Allowances can be negative to deal with expiredallowances. The ''''leaveallowancebalance'''' report [[columns|column]] can beused to report the current annual leave balance.Leaves outside of the project period are silently ignored and will not beconsidered in the leave balance calculation. Therefor, leave allowances areonly allowed within the project period.
        )
      level(:beta)
      example('Leave')
    end

rule_leaveList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2291
    def rule_leaveList
      listRule('moreLeaveList', '!leave')
    end

rule_leaveName() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2295
    def rule_leaveName
      optional
      pattern(%( $STRING ), lambda {
        @val[0]
      })
      arg(0, 'name', 'An optional name or reason for the leave')
    end

rule_leaveType() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2356
    def rule_leaveType
      singlePattern('_project')
      descr('Assignment to another project (lowest priority)')

      singlePattern('_annual')
      descr('Personal leave based on annual allowance')

      singlePattern('_special')
      descr('Personal leave based on a special occasion')

      singlePattern('_sick')
      descr('Sick leave')

      singlePattern('_unpaid')
      descr('Unpaid leave')

      singlePattern('_holiday')
      descr('Public or bank holiday (highest priority)')
    end

rule_leaves() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2332
    def rule_leaves
      pattern(%( _leaves !leaveList ), lambda {
        LeaveList.new(@val[1])
      })
      doc('leaves', Describe a list of leave periods. A leave can be due to a public holiday,personal or sick leave. At global scope, the leaves determine which day isconsidered a working day. Subsequent resource definitions will inherit theleave list.Leaves can be defined at global level, at resource level and at shift leveland intervals may overlap. The leave types have different priorities. A higherpriority leave type can overwrite a lower priority type. This means thatresource level leaves can overwrite global leaves when they have a higherpriority. A sub resource can overwrite a leave of a enclosing resource.Leave periods outside of the project interval are silently ignored. For leaveperiods that are partially outside of the project period only the part insidethe project period will be considered.
         )
      example('Leave')
    end

rule_limitAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2376
    def rule_limitAttributes
      optionsRule('limitAttributesBody')
    end

rule_limitAttributesBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2380
    def rule_limitAttributesBody
      optional
      repeatable

      pattern(%( _end !valDate ), lambda {
        @limitInterval.end = @val[1]
      })
      doc('end.limit', The end date of the limit interval. It must be within the project time frame.
      )

      pattern(%( _period !valInterval ), lambda {
        @limitInterval = ScoreboardInterval.new(@project['start'],
                                                @project['scheduleGranularity'],
                                                @val[1].start, @val[1].end)
      })
      doc('period.limit', This property is a shortcut for setting the start and end dates of the limitinterval. Both dates must be within the project time frame.
         )

      pattern(%( _resources !resourceLeafList ), lambda {
        @limitResources = @val[1]
      })
      doc('resources.limit', When [[limits]] are used in a [[task]] context, the limits can be restrictedto a list of resources that are allocated to the task. In that case eachlisted resource will not be allocated more than the specified upper limit.Lower limits have no impact on the scheduler but do generate a warning whennot met.  All specified resources must be leaf resources.
         )
      example('Limits-1', '5')

      pattern(%( _start !valDate ), lambda {
        @limitInterval.start = @val[1]
      })
      doc('start.limit', The start date of the limit interval. It must be within the project time frame.
      )
    end

rule_limitValue() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2425
    def rule_limitValue
      pattern([ '!workingDuration' ], lambda {
        @limitInterval = ScoreboardInterval.new(@project['start'],
                                                @project['scheduleGranularity'],
                                                @project['start'], @project['end'])
        @limitResources = []
        @val[0]
      })
    end

rule_limits() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2435
    def rule_limits
      pattern(%( !limitsHeader !limitsBody ), lambda {
        @val[0]
      })
    end

rule_limitsAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2441
    def rule_limitsAttributes
      optional
      repeatable

      pattern(%( _dailymax !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('dailymax', Set a maximum limit for each calendar day.
         )
      example('Limits-1', '1')

      pattern(%( _dailymin !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('dailymin', Minimum required effort for any calendar day. This value cannot be guaranteed bythe scheduler. It is only checked after the schedule is complete. In case theminium required amount has not been reached, a warning will be generated.
         )
      example('Limits-1', '4')

      pattern(%( _maximum !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('maximum', Set a maximum limit for the specified period. You must ensure that the overalleffort can be achieved!
         )

      pattern(%( _minimum !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('minimum', Set a minim limit for each calendar month. This will only result in a warningif not met.
         )

      pattern(%( _monthlymax !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('monthlymax', Set a maximum limit for each calendar month.
         )

      pattern(%( _monthlymin !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('monthlymin', Minimum required effort for any calendar month. This value cannot beguaranteed by the scheduler. It is only checked after the schedule iscomplete. In case the minium required amount has not been reached, a warningwill be generated.
         )

      pattern(%( _weeklymax !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('weeklymax', Set a maximum limit for each calendar week.
         )

      pattern(%( _weeklymin !limitValue !limitAttributes), lambda {
        setLimit(@val[0], @val[1], @limitInterval)
      })
      doc('weeklymin', Minimum required effort for any calendar week. This value cannot be guaranteed bythe scheduler. It is only checked after the schedule is complete. In case theminium required amount has not been reached, a warning will be generated.
         )
    end

rule_limitsBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2521
    def rule_limitsBody
      optionsRule('limitsAttributes')
    end

rule_limitsHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2525
    def rule_limitsHeader
      pattern(%( _limits ), lambda {
        @limits = Limits.new
        @limits.setProject(@project)
        @limits
      })
    end

rule_listOfDays() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2533
    def rule_listOfDays
      pattern(%( !weekDayInterval !moreListOfDays), lambda {
        weekDays = Array.new(7, false)
        ([ @val[0] ] + (@val[1] ? @val[1] : [])).each do |dayList|
          7.times { |i| weekDays[i] = true if dayList[i] }
        end
        weekDays
      })
    end

rule_listOfTimes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2543
    def rule_listOfTimes
      pattern(%( _off ), lambda {
        [ ]
      })
      pattern(%( !timeInterval !moreTimeIntervals ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_listType() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2552
    def rule_listType
      pattern([ '_bullets' ], lambda { :bullets })
      descr('List items as bullet list')

      pattern([ '_comma' ], lambda { :comma })
      descr('List items as comma separated list')

      pattern([ '_numbered' ], lambda { :numbered })
      descr('List items as numbered list')
    end

rule_loadunit() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2563
    def rule_loadunit
      pattern(%( _loadunit !loadunitName ), lambda {
        @property.set('loadUnit', @val[1])
      })
      doc('loadunit', Determines what unit should be used to display all load values in this report.
         )
    end

rule_loadunitName() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2573
    def rule_loadunitName
      pattern([ '_days' ], lambda { :days })
      descr('Display all load and duration values as days.')

      pattern([ '_hours' ], lambda { :hours })
      descr('Display all load and duration values as hours.')

      pattern([ '_longauto'] , lambda { :longauto })
      descr(Automatically select the unit that produces the shortest and most readablevalue. The unit name will not be abbreviated. It will not use quarters sinceit is not common.
           )

      pattern([ '_minutes' ], lambda { :minutes })
      descr('Display all load and duration values as minutes.')

      pattern([ '_months' ], lambda { :months })
      descr('Display all load and duration values as months.')

      pattern([ '_quarters' ], lambda { :quarters })
      descr('Display all load and duration values as quarters.')

      pattern([ '_shortauto' ], lambda { :shortauto })
      descr(Automatically select the unit that produces the shortest and most readablevalue. The unit name will be abbreviated. It will not use quarters since it isnot common.
           )

      pattern([ '_weeks' ], lambda { :weeks })
      descr('Display all load and duration values as weeks.')

      pattern([ '_years' ], lambda { :years })
      descr('Display all load and duration values as years.')
    end

rule_logicalExpression() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2612
    def rule_logicalExpression
      pattern(%( !operation ), lambda {
        LogicalExpression.new(@val[0], sourceFileInfo)
      })
      pattern(%( _@ !allOrNone ), lambda {
        LogicalExpression.new(LogicalOperation.new(@val[1]), sourceFileInfo)
      })
      doc('logicalexpression', A logical expression is a combination of operands and mathematical operations.The final result of a logical expression is always true or false. Logicalexpressions are used the reduce the properties in a report to a certain subsetor to select alternatives for the cell content of a table. When used withattributes like [[hidetask]] or [[hideresource]] the logical expressionevaluates to true for a certain property, this property is hidden or rolled-upin the report.Operands can be previously declared flags, built-in [[functions]], propertyattributes (specified as scenario.attribute) or another logical expression.When you combine logical operations to a more complex expression, theoperators are evaluated from left to right. ''''a | b & c'''' is identical to''''(a | b) & c''''. It's highly recommended that you always use brackets tocontrol the evaluation sequence. Currently, TaskJuggler does not support theconcept of operator precedence or right-left associativity. This may change inthe future.An operand can also be just a number. 0 evaluates to false, all other numbersto true. The logical expression can also be the special constants ''''@all''''or ''''@none''''. The first always evaluates to true, the latter to false.Date attributes needs special attention. Attributes like [[maxend]] canbe undefined. To use such an attribute in a comparison, you need to test forthe validity first. E. g. to compare the end date of the ''''plan''''scenario with the ''''maxend'''' value use ''''isvalid(plan.maxend) &(plan.end > plan.maxend)''''. The ''''&'''' and ''''|'''' operators are lazy.If the result is already known after evaluation the first operand, the secondoperand will not be evaluated any more.
         )
      also(%( functions ))
      example('LogicalExpression', '1')
    end

rule_macro() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2654
    def rule_macro
      pattern(%( _macro $ID $MACRO ), lambda {
        if @scanner.macroDefined?(@val[1])
          warning('marco_redefinition', "Redefining macro #{@val[1]}")
        end
        @scanner.addMacro(TextParser::Macro.new(@val[1], @val[2],
                                                @sourceFileInfo[0]))
      })
      doc('macro', Defines a text fragment that can later be inserted by using the specified ID.To insert the text fragment anywhere in the text you need to write ${ID}.Thebody is not optional. It must be enclosed in square brackets. Macros can bedeclared like this: macro FOO [ This text ]If later ''''${FOO}'''' is found in the project file, it is expanded to''''This text''''.Macros may have arguments. Arguments are accessed with special macros withnumbers as names.  The number specifies the index of the argument. macro FOO [ This ${1} text ]will expand to ''''This stupid text'''' if called as ''''${FOO "stupid"}''''.Macros may call other macros. All macro arguments must be enclosed by doublequotes. In case the argument contains a double quote, it must be escaped by aslash (''''/'''').User defined macro IDs must have at least one uppercase letter as alllowercase letter IDs are reserved for built-in macros.To terminate the macro definition, the ''''<nowiki>]</nowiki>'''' must be thelast character in the line. If there are any other characters trailing it(even spaces or comments) the ''''<nowiki>]</nowiki>'''' will not beconsidered the end of the macro definition.In macro calls the macro names can be prefixed by a question mark. In thiscase the macro will expand to nothing if the macro is not defined. Otherwisethe undefined macro would be flagged with an error message.The macro call ${?foo}will expand to nothing if foo is undefined.
         )
      example('Macro-1')
    end

rule_moreAlternatives() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2711
    def rule_moreAlternatives
      commaListRule('!resourceId')
    end

rule_moreArguments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2715
    def rule_moreArguments
      commaListRule('!argument')
    end

rule_moreBangs() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2705
    def rule_moreBangs
      optional
      repeatable
      singlePattern('_!')
    end

rule_moreChargeSetItems() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2719
    def rule_moreChargeSetItems
      commaListRule('!chargeSetItem')
    end

rule_moreColumnDef() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2723
    def rule_moreColumnDef
      commaListRule('!columnDef')
    end

rule_moreDepTasks() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2727
    def rule_moreDepTasks
      commaListRule('!taskDep')
    end

rule_moreExportFormats() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2731
    def rule_moreExportFormats
      commaListRule('!exportFormat')
    end

rule_moreJournalSortCriteria() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2735
    def rule_moreJournalSortCriteria
      commaListRule('!journalSortCriterium')
    end

rule_moreListOfDays() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2739
    def rule_moreListOfDays
      commaListRule('!weekDayInterval')
    end

rule_moreOutputFormats() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2743
    def rule_moreOutputFormats
      commaListRule('!outputFormat')
    end

rule_morePredTasks() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2751
    def rule_morePredTasks
      commaListRule('!taskPred')
    end

rule_moreProjectIDs() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2747
    def rule_moreProjectIDs
      commaListRule('$ID')
    end

rule_moreSortCriteria() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2755
    def rule_moreSortCriteria
      commaListRule('!sortNonTree')
    end

rule_moreTimeIntervals() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2759
    def rule_moreTimeIntervals
      commaListRule('!timeInterval')
    end

rule_navigator() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2763
    def rule_navigator
      pattern(%( !navigatorHeader !navigatorBody ), lambda {
        @project['navigators'][@navigator.id] = @navigator
      })
      doc('navigator', Defines a navigator object with the specified ID. This object can be used inreports to include a navigation bar with references to other reports.
            )
      example('navigator')
    end

rule_navigatorAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2775
    def rule_navigatorAttributes
      optional
      repeatable
      pattern(%( _hidereport !logicalExpression ), lambda {
        @navigator.hideReport = @val[1]
      })
      doc('hidereport', This attribute can be used to exclude the reports that match the specified[[logicalexpression|logical expression]] from the navigation bar.
            )
    end

rule_navigatorBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2788
    def rule_navigatorBody
      optional
      pattern(%( _{ !navigatorAttributes _} ))
    end

rule_navigatorHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2793
    def rule_navigatorHeader
      pattern(%( _navigator $ID ), lambda {
        if @project['navigators'][@val[1]]
          error('navigator_exists',
                "The navigator #{@val[1]} has already been defined.",
                @sourceFileInfo[0])
        end
        @navigator = Navigator.new(@val[1], @project)
      })
    end

rule_nikuReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2853
    def rule_nikuReport
      pattern(%( !nikuReportHeader !nikuReportBody ), lambda {
        @property = nil
      })
      doc('nikureport', This report generates an XML file to be imported into the enterprise resourcemanagement software Clarity(R) from Computer Associates(R). The files containsallocation curves for the specified resources. All tasks with identical userdefined attributes ''''ClarityPID'''' and ''''ClarityPNAME'''' are bundledinto a Clarity project. The resulting XML file can be imported into Claritywith the xog-in tool.
         )
      example('Niku')
    end

rule_nikuReportAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2804
    def rule_nikuReportAttributes
      optional
      repeatable

      pattern(%( !formats ))
      pattern(%( !headline ))
      pattern(%( !hideresource ))
      pattern(%( !hidetask ))

      pattern(%( !numberFormat ), lambda {
        @property.set('numberFormat', @val[0])
      })

      pattern(%( !reportEnd ))
      pattern(%( !reportPeriod ))
      pattern(%( !reportStart ))
      pattern(%( !reportTitle ))

      pattern(%( _timeoff $STRING $STRING ), lambda {
        @property.set('timeOffId', @val[1])
        @property.set('timeOffName', @val[2])
      })
      doc('timeoff.nikureport', Set the Clarity project ID and name that the vacation time will be reported to.
         )
      arg(1, 'ID', 'The Clarity project ID')
      arg(2, 'Name', 'The Clarity project name')
    end

rule_nikuReportBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2834
    def rule_nikuReportBody
      pattern(%( _{ !nikuReportAttributes _} ), lambda {

      })
    end

rule_nikuReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2840
    def rule_nikuReportHeader
      pattern(%( _nikureport !optionalID $STRING ), lambda {
        newReport(@val[1], @val[2], :niku, @sourceFileInfo[0]) do
          @property.set('numberFormat', RealFormat.new(['-', '', '', '.', 2]))
        end
      })
      arg(1, 'file name', The name of the time sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel.
         )
    end

rule_nodeId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2869
    def rule_nodeId
      pattern(%( !idOrAbsoluteId !subNodeId ), lambda {
        case @property.typeSpec
        when :taskreport
          if (p1 = @project.task(@val[0])).nil?
            error('unknown_main_node',
                  "Unknown task ID #{@val[0]}", @sourceFileInfo[0])
          end
          if @val[1]
            if (p2 = @project.resource(@val[1])).nil?
              error('unknown_sub_node',
                    "Unknown resource ID #{@val[0]}", @sourceFileInfo[0])
            end
            return [ p2, p1 ]
          end
          return [ p1, nil ]
        when :resourcereport
          if (p1 = @project.task(@val[0])).nil?
            error('unknown_main_node',
                  "Unknown task ID #{@val[0]}", @sourceFileInfo[0])
          end
          if @val[1]
            if (p2 = @project.resource(@val[1])).nil?
              error('unknown_sub_node',
                    "Unknown resource ID #{@val[0]}", @sourceFileInfo[0])
            end
            return [ p2, p1 ]
          end
          return [ p1, nil ]
        end

        raise "Node list is not supported for this report type: " +
              "#{@property.typeSpec}"
      })
    end

rule_nodeIdList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2905
    def rule_nodeIdList
      listRule('moreNodeIdList', '!nodeId')
      pattern([ '_-' ], lambda {
        []
      })
    end

rule_number() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2912
    def rule_number
      singlePattern('$INTEGER')
      singlePattern('$FLOAT')
    end

rule_numberFormat() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2917
    def rule_numberFormat
      pattern(%( _numberformat $STRING $STRING $STRING $STRING $INTEGER ),
          lambda {
        RealFormat.new(@val.slice(1, 5))
      })
      doc('numberformat',
          'These values specify the default format used for all numerical ' +
          'real values.')
      arg(1, 'negativeprefix', 'Prefix for negative numbers')
      arg(2, 'negativesuffix', 'Suffix for negative numbers')
      arg(3, 'thousandsep', 'Separator used for every 3rd digit')
      arg(4, 'fractionsep', 'Separator used to separate the fraction digits')
      arg(5, 'fractiondigits', 'Number of fraction digits to show')
    end

rule_operand() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2932
    def rule_operand
      pattern(%( _( !operation _) ), lambda {
        @val[1]
      })
      pattern(%( _~ !operand ), lambda {
        operation = LogicalOperation.new(@val[1])
        operation.operator = '~'
        operation
      })

      pattern(%( $ABSOLUTE_ID ), lambda {
        if @val[0].count('.') > 1
          error('operand_attribute',
                'Attributes must be specified as <scenarioID>.<attribute>',
                @sourceFileInfo[0])
        end
        scenario, attribute = @val[0].split('.')
        if (scenarioIdx = @project.scenarioIdx(scenario)).nil?
          error('operand_unkn_scen', "Unknown scenario ID #{scenario}",
                @sourceFileInfo[0])
        end
        # TODO: Do at least some basic sanity checks of the attribute is valid.
        LogicalAttribute.new(attribute, @project.scenario(scenarioIdx))
      })
      pattern(%( !date ), lambda {
        LogicalOperation.new(@val[0])
      })
      pattern(%( $ID !argumentList ), lambda {
        if @val[1].nil?
          unless @project['flags'].include?(@val[0])
            error('operand_unkn_flag', "Undeclared flag '#{@val[0]}'",
                  @sourceFileInfo[0])
          end
          LogicalFlag.new(@val[0])
        else
          func = LogicalFunction.new(@val[0])
          res = func.setArgumentsAndCheck(@val[1])
          unless res.nil?
            error(*res)
          end
          func
        end
      })
      pattern(%( $INTEGER ), lambda {
        LogicalOperation.new(@val[0])
      })
      pattern(%( $FLOAT ), lambda {
        LogicalOperation.new(@val[0])
      })
      pattern(%( $STRING ), lambda {
        LogicalOperation.new(@val[0])
      })
    end

rule_operation() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 2986
    def rule_operation
      pattern(%( !operand !operationChain ), lambda {
        operation = LogicalOperation.new(@val[0])
        if @val[1]
          # Further operators/operands create an operation tree.
          @val[1].each do |ops|
            operation = LogicalOperation.new(operation)
            operation.operator = ops[0]
            operation.operand2 = ops[1]
          end
        end
        operation
      })
      arg(0, 'operand', An operand can consist of a date, a text string, a [[functions|function]], aproperty attribute or a numerical value. It can also be the name of a declaredflag.  Use the ''''scenario_id.attribute'''' notation to use an attribute ofthe currently evaluated property. The scenario ID always has to be specified,also for non-scenario specific attributes. This is necessary to distinguishthem from flags. See [[columnid]] for a list of available attributes. The useof list attributes is not recommended. User defined attributes are availableas well.An operand can be a negated operand by prefixing a ~ charater or it can beanother logical expression enclosed in braces.
          )
    end

rule_operationChain() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3015
    def rule_operationChain
      optional
      repeatable
      pattern(%( !operatorAndOperand), lambda {
        @val[0]
      })
    end

rule_operator() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3033
    def rule_operator
      singlePattern('_|')
      descr('The \or\ operator')

      singlePattern('_&')
      descr('The \and\ operator')

      singlePattern('_>')
      descr('The \greater than\ operator')

      singlePattern('_<')
      descr('The \smaller than\ operator')

      singlePattern('_=')
      descr('The \equal\ operator')

      singlePattern('_>=')
      descr('The \greater-or-equal\ operator')

      singlePattern('_<=')
      descr('The \smaller-or-equal\ operator')

      singlePattern('_!=')
      descr('The \not-equal\ operator')
    end

rule_operatorAndOperand() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3023
    def rule_operatorAndOperand
      pattern(%( !operator !operand), lambda{
        [ @val[0], @val[1] ]
      })
      arg(1, 'operand', An operand can consist of a date, a text string or a numerical value. It can also be the name of a declared flag. Finally, an operand can be a negated operand by prefixing a ~ charater or it can be another operation enclosed in braces.
          )
    end

rule_optionalID() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3059
    def rule_optionalID
      optional
      pattern(%( $ID ), lambda {
        @val[0]
      })
      arg(0, 'id', An optional ID. If you ever want to reference this property, you must specifyyour own unique ID. If no ID is specified one will be automatically generated.These IDs may become visible in reports, but may change at any time. You maynever rely on automatically generated IDs.
         )
    end

rule_optionalMinus() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3073
    def rule_optionalMinus
      optional
      pattern(%( _- ), lambda {
        true
      })
    end

rule_optionalPercent() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3080
    def rule_optionalPercent
      optional
      pattern(%( !number _% ), lambda {
        @val[0] / 100.0
      })
    end

rule_optionalScenarioIdCol() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3086
    def rule_optionalScenarioIdCol
      optional
      pattern(%( $ID_WITH_COLON ), lambda {
        if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
          error('unknown_scenario_id', "Unknown scenario: #{@val[0]}",
                @sourceFileInfo[0])
        end
        @scenarioIdx
      })
    end

rule_optionalVersion() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3098
    def rule_optionalVersion
      optional
      pattern(%( $STRING ), lambda {
        @val[0]
      })
      arg(0, 'version', An optional version ID. This can be something simple as "4.2" or an ID tag ofa revision control system. If not specified, it defaults to "1.0".
         )
    end

rule_outputFormat() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3110
    def rule_outputFormat
      pattern(%( _csv ), lambda {
        :csv
      })
      descr(The report lists the resources and their respective values ascolon-separated-value (CSV) format. Due to the very simple nature of the CSVformat, only a small subset of features will be supported for CSV output.Including tasks or listing multiple scenarios will result in very difficult toread reports.
           )

      pattern(%( _html ), lambda {
        :html
      })
      descr('Generate a web page (HTML file)')

      pattern(%( _niku ), lambda {
        :niku
      })
      descr('Generate a XOG XML file to be used with Clarity.')
    end

rule_outputFormats() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3134
    def rule_outputFormats
      pattern(%( !outputFormat !moreOutputFormats ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_plusOrMinus() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3140
    def rule_plusOrMinus
      singlePattern('_+')
      singlePattern('_-')
    end

rule_project() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3145
    def rule_project
      pattern(%( !projectProlog !projectDeclaration !properties . ), lambda {
        @val[1]
      })
    end

rule_projectBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3151
    def rule_projectBody
      optionsRule('projectBodyAttributes')
    end

rule_projectBodyAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3155
    def rule_projectBodyAttributes
      repeatable
      optional

      pattern(%( _alertlevels !alertLevelDefinitions ), lambda {
        if @val[1].length < 2
          error('too_few_alert_levels',
                'You must specify at least 2 different alert levels.',
                @sourceFileInfo[1])
        end
        levels = @project['alertLevels']
        levels.clear
        @val[1].each do |level|
          if levels.indexById(level[0])
            error('alert_level_redef',
                  "Alert level '#{level[0]}' has been defined multiple times.",
                  @sourceFileInfo[1])
          end

          if levels.indexByName(level[1])
            error('alert_name_redef',
                  "Alert level name '#{level[1]}' has been defined multiple " +
                  "times.", @sourceFileInfo[1])
          end

          @project['alertLevels'].add(AlertLevelDefinition.new(*level))
        end
      })
      level(:beta)
      doc('alertlevels', By default TaskJuggler supports the pre-defined alert levels: green, yellowand red. This attribute can be used to replace them with your own set of alertlevels. You can define any number of levels, but you need to define at leasttwo and they must be specified in ascending order from the least severity tohighest severity. Additionally, you need to provide a 15x15 pixel image filewith the name ''''flag-X.png'''' for each level where ''''X'''' matches the IDof the alert level. These files need to be in the ''''icons'''' directory tobe found by the browser when showing HTML reports.
         )
      example('AlertLevels')

      pattern(%( !currencyFormat ), lambda {
        @project['currencyFormat'] = @val[0]
      })

      pattern(%( _currency $STRING ), lambda {
        @project['currency'] = @val[1]
      })
      doc('currency', 'The default currency unit.')
      example('Account')
      arg(1, 'symbol', 'Currency symbol')

      pattern(%( _dailyworkinghours !number ), lambda {
        @project['dailyworkinghours'] = @val[1]
      })
      doc('dailyworkinghours', Set the average number of working hours per day. This is used asthe base to convert working hours into working days. This affectsfor example the length task attribute. The default value is 8 hoursand should work for most Western countries. The value you specify should matchthe settings you specified as your default [[workinghours.project|workinghours]].
         )
      example('Project')
      arg(1, 'hours', 'Average number of working hours per working day')

      pattern(%( _extend !extendProperty !extendBody ), lambda {
        updateParserTables
      })
      doc('extend', Often it is desirable to collect more information in the project file than isnecessary for task scheduling and resource allocation. To add such informationto tasks, resources or accounts the user can extend these properties withuser-defined attributes. The new attributes can be of various types such astext, date or reference to capture various types of data. Optionally the usercan specify if the attribute value should be inherited from the enclosingproperty.
         )
      example('CustomAttributes')

      pattern(%( !projectBodyInclude ))

      pattern(%( !journalEntry ))

      pattern(%( _now !date ), lambda {
        @project['now'] = @val[1]
        @scanner.addMacro(TextParser::Macro.new('now', @val[1].to_s,
                                                @sourceFileInfo[0]))
        @scanner.addMacro(TextParser::Macro.new(
          'today', @val[1].to_s(@project['timeFormat']), @sourceFileInfo[0]))
      })
      doc('now', Specify the date that TaskJuggler uses for calculation as currentdate. If no value is specified, the current value of the systemclock is used.
         )
      arg(1, 'date', 'Alternative date to be used as current date for all ' +
          'computations')

      pattern(%( !numberFormat ), lambda {
        @project['numberFormat'] = @val[0]
      })

      pattern(%( _outputdir $STRING ), lambda {
        # Directory name must be terminated by a slash.
        if @val[1].empty?
          error('outdir_empty', 'Output directory may not be empty.')
        end
        if !File.directory?(@val[1])
          error('outdir_missing',
                "Output directory '#{@val[1]}' does not exist or is not " +
                "a directory!")
        end
        @project.outputDir = @val[1] + (@val[1][-1] == // ? '' : '/')
      })
      doc('outputdir',
          'Specifies the directory into which the reports should be generated. ' +
          'This will not affect reports whos name start with a slash. This ' +
          'setting can be overwritten by the command line option.')
      arg(1, 'directory', 'Path to an existing directory')

      pattern(%( !scenario ))
      pattern(%( _shorttimeformat $STRING ), lambda {
        @project['shortTimeFormat'] = @val[1]
      })
      doc('shorttimeformat',
          'Specifies time format for time short specifications. This is normal' +
          'just the hour and minutes.')
      arg(1, 'format', 'strftime like format string')

      pattern(%( !timeformat ), lambda {
        @project['timeFormat'] = @val[0]
      })

      pattern(%( !timezone ), lambda {
        @val[0]
      })

      pattern(%( _timingresolution $INTEGER _min ), lambda {
        goodValues = [ 5, 10, 15, 20, 30, 60 ]
        unless goodValues.include?(@val[1])
          error('bad_timing_res',
                "Timing resolution must be one of #{goodValues.join(', ')} min.",
                @sourceFileInfo[1])
        end
        if @val[1] > (Project.maxScheduleGranularity / 60)
          error('too_large_timing_res',
                'The maximum allowed timing resolution for the timezone is ' +
                "#{Project.maxScheduleGranularity / 60} minutes.",
                @sourceFileInfo[1])
        end
        @project['scheduleGranularity'] = @val[1] * 60
      })
      doc('timingresolution', Sets the minimum timing resolution. The smaller the value, the longer thescheduling process lasts and the more memory the application needs. Thedefault and maximum value is 1 hour. The smallest value is 5 min.This value is a pretty fundamental setting of TaskJuggler. It has a severeimpact on memory usage and scheduling performance. You should set this valueto the minimum required resolution. Make sure that all values that you specifyare aligned with the resolution.Changing the timing resolution will reset the [[workinghours.project|workinghours]] to the default times. It's recommended that this is the very firstoption in the project header section.Do not use this option after you've set the time zone!
          )

      pattern(%( _trackingscenario !scenarioId ), lambda {
        @project['trackingScenarioIdx'] = @val[1]
        # The tracking scenario and all child scenarios will always be scheduled
        # in projection mode.
        @project.scenario(@val[1]).all.each do |scenario|
          scenario.set('projection', true)
        end
      })
      doc('trackingscenario', Specifies which scenario is used to capture what actually has happened withthe project. All sub-scenarios of this scenario inherit the bookings of thetracking scenario and may not have any bookings of their own. The trackingscenario must also be specified to use time and status sheet reports.The tracking scenario must be defined after all scenario have been defined.The tracking scenario and all scenarios derived from it will be scheduled inprojection mode. This means that the scheduler will only add bookings afterthe current date or the date specified by [[now]]. It is assumed that allallocations prior to this date have been provided as [[booking.task|task bookings]] or [[booking.resource|resource bookings]].
         )
      example('TimeSheet1', '2')

      pattern(%( _weekstartsmonday ), lambda {
        @project['weekStartsMonday'] = true
      })
      doc('weekstartsmonday',
          'Specify that you want to base all week calculation on weeks ' +
          'starting on Monday. This is common in many European countries.')

      pattern(%( _weekstartssunday ), lambda {
        @project['weekStartsMonday'] = false
      })
      doc('weekstartssunday',
          'Specify that you want to base all week calculation on weeks ' +
          'starting on Sunday. This is common in the United States of America.')

      pattern(%( !workinghoursProject ))
      pattern(%( _yearlyworkingdays !number ), lambda {
        @project['yearlyworkingdays'] = @val[1]
      })
      doc('yearlyworkingdays', Specifies the number of average working days per year. This should correlateto the specified workinghours and vacation. It affects the conversion ofworking hours, working days, working weeks, working months and working yearsinto each other.When public holidays and leaves are disregarded, this value should be equalto the number of working days per week times 52.1428 (the average number ofweeks per year). E. g. for a culture with 5 working days it is 260.714 (thedefault), for 6 working days it is 312.8568 and for 7 working days it is365.
         )
      arg(1, 'days', 'Number of average working days for a year')
    end

rule_projectBodyInclude() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3474
    def rule_projectBodyInclude
      pattern(%( _include !includeFile !projectBodyAttributes . ))
      lastSyntaxToken(1)
      doc('include.project', Includes the specified file name as if its contents would be writteninstead of the include property. When the included files contains otherinclude statements or report definitions, the filenames are relative to filewhere they are defined in.This version of the include directive may only be used inside the [[project]]header section. The included files must only contain content that may bepresent in a project header section.
         )
    end

rule_projectDeclaration() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3388
    def rule_projectDeclaration
      pattern(%( !projectHeader !projectBody ), lambda {
        # If the user has specified a tracking scenario, we mark all children of
        # that scenario to disallow own bookings. These scenarios will inherit
        # their bookings from the tracking scenario.
        if (idx = @project['trackingScenarioIdx'])
          @project.scenario(idx).allLeaves(true).each do |scenario|
            scenario.set('ownbookings', false)
          end
        end
        @val[0]
      })
      doc('project', The project property is mandatory and should be the first propertyin a project file. It is used to capture basic attributes such asthe project id, name and the expected time frame.Be aware that the dates for the project period default to UTC times. See [[interval2]] for details.
         )
    end

rule_projectHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3410
    def rule_projectHeader
      pattern(%( _project !optionalID $STRING !optionalVersion !interval ), lambda {
        @project = Project.new(@val[1], @val[2], @val[3])
        @project['start'] = @val[4].start
        @project['end'] = @val[4].end
        @projectId = @val[1]
        setGlobalMacros
        @property = nil
        @reportCounter = 0
        @project
      })
      arg(2, 'name', 'The name of the project')
    end

rule_projectIDs() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3424
    def rule_projectIDs
      pattern(%( $ID !moreProjectIDs ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_projectProlog() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3451
    def rule_projectProlog
      optional
      repeatable
      pattern(%( !prologInclude ))
      pattern(%( !macro ))
    end

rule_projectProperties() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3458
    def rule_projectProperties
      # This rule is not defining actual syntax. It's only used for the
      # documentation.
      pattern(%( !projectPropertiesBody ))
      doc('properties', The project properties. Every project must consists of at least one task. The other properties are optional. To save the scheduled data at least one output generating property should be used.
         )
    end

rule_projectPropertiesBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3468
    def rule_projectPropertiesBody
      # This rule is not defining actual syntax. It's only used for the
      # documentation.
      optionsRule('properties')
    end

rule_projection() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3430
    def rule_projection
      optionsRule('projectionAttributes')
    end

rule_projectionAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3434
    def rule_projectionAttributes
      optional
      repeatable
      pattern(%( _sloppy ))
      level(:deprecated)
      also('trackingscenario')
      doc('sloppy.projection', '')

      pattern(%( _strict ), lambda {
        warning('projection_strict',
                'The strict mode is now always used.')
      })
      level(:deprecated)
      also('trackingscenario')
      doc('strict.projection', '')
    end

rule_prologInclude() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3490
    def rule_prologInclude
      pattern(%( _include !includeFile !projectProlog . ))
      lastSyntaxToken(1)
      doc('include.macro', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in.The included file may only contain macro definitions. This version of theinclude directive can only be used before the [[project]] header.
         )
    end

rule_properties() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3506
    def rule_properties
      pattern(%( !propertiesBody ))
    end

rule_propertiesBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3510
    def rule_propertiesBody
      repeatable
      optional

      pattern(%( !account ))

      pattern(%( _auxdir $STRING ), lambda {
        auxdir = @val[1]
        # Ensure that the directory always ends with a '/'.
        auxdir += '/' unless auxdir[-1] == //
        @project['auxdir'] = auxdir
      })
      level(:beta)
      doc('auxdir', Specifies an alternative directory for the auxiliary report files such as CSS,JavaScript and icon files. This setting will affect all subsequent reportdefinitions unless it gets overridden. If this attribute is not set, thedirectory and its contents will be generated automatically. If this attributeis provided, the user has to ensure that the directory exists and is filledwith the proper data. The specified path can be absolute or relative to thegenerated report file.
         )

      pattern(%( _copyright $STRING ), lambda {
        @project['copyright'] = @val[1]
      })
      doc('copyright', Set a copyright notice for the project file and its content. This copyright notice will be added to all reports that can support it.
         )
      example('Caption', '2')

      pattern(%( !balance ), lambda {
        @project['costaccount'] = @val[0][0]
        @project['revenueaccount'] = @val[0][1]
      })

      pattern(%( _flags !declareFlagList ), lambda {
        unless @project['flags'].include?(@val[1])
          @project['flags'] += @val[1]
        end
      })
      doc('flags', Declare one or more flag for later use. Flags can be used to mark tasks, resources or other properties to filter them in reports.
         )

      pattern(%( !propertiesInclude ))

      pattern(%( !leaves ), lambda {
        @val[0].each do |v|
          @project['leaves'] << v
        end
      })

      pattern(%( !limits ), lambda {
        @project['limits'] = @val[0]
      })
      doc('limits', Set per-interval allocation limits for the following resource definitions.The limits can be overwritten in each resource definition and the globallimits can be changed later.
         )

      pattern(%( !macro ))

      pattern(%( !navigator ))

      pattern(%( _projectid $ID ), lambda {
        @project['projectids'] << @val[1]
        @project['projectids'].uniq!
        @project['projectid'] = @projectId = @val[1]
      })
      doc('projectid', This declares a new project id and activates it. All subsequenttask definitions will inherit this ID. The tasks of a project can havedifferent IDs.  This is particularly helpful if the project is merged fromseveral sub projects that each have their own ID.
         )

      pattern(%( _projectids !projectIDs ), lambda {
        @project['projectids'] += @val[1]
        @project['projectids'].uniq!
      })
      doc('projectids', Declares a list of project IDs. When an include file that was generated from another project brings different project IDs, these need to be declared first.
          )

      pattern(%( _rate !number ), lambda {
        @project['rate'] = @val[1].to_f
      })
      doc('rate', Set the default rate for all subsequently defined resources. The rate describes the daily cost of a resource.
          )

      pattern(%( !reportProperties ))
      pattern(%( !resource ))
      pattern(%( !shift ))
      pattern(%( !statusSheet ))

      pattern(%( _supplement !supplement ))
      doc('supplement', The supplement keyword provides a mechanism to add more attributes to alreadydefined accounts, tasks or resources. The additional attributes must obey thesame rules as in regular task or resource definitions and must be enclosed bycurly braces.This construct is primarily meant for situations where the information about atask or resource is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool.
         )
      example('Supplement')

      pattern(%( !task ))
      pattern(%( !timeSheet ))
      pattern(%( _vacation !vacationName !intervals ), lambda {
        @val[2].each do |interval|
          @project['leaves'] << Leave.new(:holiday, interval)
        end
      })
      doc('vacation', Specify a global vacation period for all subsequently defined resources. Avacation can also be used to block out the time before a resource joined orafter it left. For employees changing their work schedule from full-time topart-time, or vice versa, please refer to the 'Shift' property.
         )
      arg(1, 'name', 'Name or purpose of the vacation')
    end

rule_propertiesFile() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3646
    def rule_propertiesFile
      pattern(%( !propertiesBody . ))
    end

rule_propertiesInclude() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3650
    def rule_propertiesInclude
      pattern(%( _include !includeProperties !properties . ), lambda {
      })
      lastSyntaxToken(1)
      doc('include.properties', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in. include commands can be used in the projectheader, at global scope or between property declarations of tasks,resources, and accounts.For technical reasons you have to supply the optional pair of curlybrackets if the include is followed immediately by a macro call thatis defined within the included file.
         )
    end

rule_purge() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3670
    def rule_purge
      pattern(%( _purge !optionalScenarioIdCol $ID ), lambda {
        attrId = @val[2]
        if (attributeDefinition = @property.attributeDefinition(attrId)).nil?
          error('purge_unknown_id',
                "#{attrId} is not a known attribute for this property",
                @sourceFileInfo[2])
        end
        if attributeDefinition.scenarioSpecific
          @scenarioIdx = 0 unless @val[1]
          attr = @property[attrId, 0]
        else
          if @val[1]
            error('purge_non_sc_spec_attr',
                  'Scenario specified for a non-scenario specific attribute')
          end
          attr = @property.get(attrId)
        end
        if @property.attributeDefinition(attrId).scenarioSpecific
          @property.getAttribute(attrId, @scenarioIdx).reset
        else
          @property.getAttribute(attrId).reset
        end
      })
      doc('purge', Many attributes inherit their values from the enclosing property or the globalscope. In certain circumstances, this is not desirable, e. g. for listattributes. A list attribute is any attribute that takes a comma separatedlist of values as argument. [[allocate]] and [[flags.task]] aregood examples of commonly used list attributes. By defining values forsuch a list attribute in a nested property, the new values will be appended tothe list that was inherited from the enclosing property. The purgeattribute resets any attribute to its default value. A subsequent definitionfor the attribute within the property will then add their values to an emptylist. The value of the enclosing property is not affected by purge.For scenario specific attributes, an optional scenario ID can be specifiedbefore the attribute ID. If it's missing, the default (first) scenario will beused.
         )
      arg(1, 'attribute', 'Any name of a list attribute')
    end

rule_referenceAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3714
    def rule_referenceAttributes
      optional
      repeatable
      pattern(%( _label $STRING ), lambda {
        @val[1]
      })
    end

rule_referenceBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3722
    def rule_referenceBody
      optionsRule('referenceAttributes')
    end

rule_relativeId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3726
    def rule_relativeId
      pattern(%( _! !moreBangs !idOrAbsoluteId ), lambda {
        str = '!'
        if @val[1]
          @val[1].each { |bang| str += bang }
        end
        str += @val[2]
        str
      })
    end

rule_reportAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4197
    def rule_reportAttributes
      optional
      repeatable

      pattern(%( _accountroot !accountId), lambda {
        if @val[1].leaf?
          error('accountroot_leaf',
                "#{@val[1].fullId} is not a container account",
                @sourceFileInfo[1])
        end
        @property.set('accountroot', @val[1])
      })
      doc('accountroot', Only accounts below the specified root-level accounts are exported. The exportedaccounts will have the ID of the root-level account stripped from their ID, so thatthe sub-accounts of the root-level account become top-level accounts in the reportfile.
         )
      example('AccountReport')

      pattern(%( _auxdir $STRING ), lambda {
        auxdir = @val[1]
        # Ensure that the directory always ends with a '/'.
        auxdir += '/' unless auxdir[-1] == //
        @property.set('auxdir', auxdir)
      })
      level(:beta)
      doc('auxdir.report', Specifies an alternative directory for the auxiliary report files such as CSS,JavaScript and icon files. If this attribute is not set, the directory will begenerated automatically. If this attribute is provided, the user has to ensurethat the directory exists and is filled with the proper data. The specifiedpath can be absolute or relative to the generated report file.
         )

      pattern(%( !balance ), lambda {
        @property.set('costaccount', @val[0][0])
        @property.set('revenueaccount', @val[0][1])
      })

      pattern(%( _caption $STRING ), lambda {
        @property.set('caption', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('caption', The caption will be embedded in the footer of the table or data segment. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
         )
      arg(1, 'text', 'The caption text.')
      example('Caption', '1')

      pattern(%( _center $STRING ), lambda {
        @property.set('center', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('center', This attribute defines the center section of the [[textreport]]. The text willbe interpreted as [[Rich_Text_Attributes|Rich Text]].
         )
      arg(1, 'text', 'The text')
      example('textreport')

      pattern(%( _columns !columnDef !moreColumnDef ), lambda {
        columns = [ @val[1] ]
        columns += @val[2] if @val[2]
        @property.set('columns', columns)
      })
      doc('columns', Specifies which columns shall be included in a report. Some columns showvalues that are constant over the course of the project. Other columns showcalculated values that depend on the time period that was chosen for thereport.
         )

      pattern(%( !currencyFormat ), lambda {
        @property.set('currencyFormat', @val[0])
      })

      pattern(%( !reportEnd ))

      pattern(%( _epilog $STRING ), lambda {
        @property.set('epilog', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('epilog', Define a text section that is printed right after the actual report data. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
         )
      also(%( footer header prolog ))

      pattern(%( !flags ))
      doc('flags.report', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
         )

      pattern(%( _footer $STRING ), lambda {
        @property.set('footer', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('footer', Define a text section that is put at the bottom of the report. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
         )
      example('textreport')
      also(%( epilog header prolog ))

      pattern(%( !formats ))

      pattern(%( _header $STRING ), lambda {
        @property.set('header', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('header', Define a text section that is put at the top of the report. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
         )
      example('textreport')
      also(%( epilog footer prolog ))

      pattern(%( !headline ))
      pattern(%( !hidejournalentry ))
      pattern(%( !hideaccount ))
      pattern(%( !hideresource ))
      pattern(%( !hidetask ))

      pattern(%( _height $INTEGER ), lambda {
        if @val[1] < 200
          error('min_report_height',
                "The report must have a minimum height of 200 pixels.")
        end
        @property.set('height', @val[1])
      })
      doc('height', Set the height of the report in pixels. This attribute is only used forreports that cannot determine the height based on the content. Such report canbe freely resized to fit in. The vast majority of reports can determine theirheight based on the provided content. These reports will simply ignore thissetting.
         )
      also('width')

      pattern(%( !journalReportAttributes ))
      pattern(%( _journalmode !journalReportMode ), lambda {
        @property.set('journalMode', @val[1])
      })
      doc('journalmode', This attribute controls what journal entries are aggregated into the report.
         )

      pattern(%( _left $STRING ), lambda {
        @property.set('left', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('left', This attribute defines the left margin section of the [[textreport]]. The textwill be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will notspan the [[header]] or [[footer]] sections.
         )
      example('textreport')

      pattern(%( !loadunit ))

      pattern(%( !numberFormat ), lambda {
        @property.set('numberFormat', @val[0])
      })

      pattern(%( _opennodes !nodeIdList ), lambda {
        @property.set('openNodes', @val[1])
      })
      doc('opennodes', 'For internal use only!')

      pattern(%( !reportPeriod ))

      pattern(%( _prolog $STRING ), lambda {
        @property.set('prolog', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('prolog', Define a text section that is printed right before the actual report data. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
         )
      also(%( epilog footer header ))

      pattern(%( !purge ))

      pattern(%( _rawhtmlhead $STRING ), lambda {
        @property.set('rawHtmlHead', @val[1])
      })
      doc('rawhtmlhead', Define a HTML fragment that will be inserted at the end of the HTML headsection.
         )

      pattern(%( !reports ))

      pattern(%( _right $STRING ), lambda {
        @property.set('right', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('right', This attribute defines the right margin section of the [[textreport]]. The textwill be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will notspan the [[header]] or [[footer]] sections.
         )
      example('textreport')

      pattern(%( !rollupaccount ))
      pattern(%( !rollupresource ))
      pattern(%( !rolluptask ))

      pattern(%( _scenarios !scenarioIdList ), lambda {
        # Don't include disabled scenarios in the report
        @val[1].delete_if { |sc| !@project.scenario(sc).get('active') }
        @property.set('scenarios', @val[1])
      })
      doc('scenarios', List of scenarios that should be included in the report. By default, only thetop-level scenario will be included. You can use this attribute to includedata from the defined set of scenarios. Not all reports support reporting datafrom multiple scenarios. They will only include data from the first one in thelist.
         )

      pattern(%( _selfcontained !yesNo ), lambda {
        @property.set('selfcontained', @val[1])
      })
      doc('selfcontained', Try to generate selfcontained output files when the format supports this. E.g. for HTML reports, the style sheet will be included and no icons will beused.
         )

      pattern(%( !sortAccounts ))
      pattern(%( !sortJournalEntries ))
      pattern(%( !sortResources ))
      pattern(%( !sortTasks ))

      pattern(%( !reportStart ))

      pattern(%( _resourceroot !resourceId), lambda {
        if @val[1].leaf?
          error('resourceroot_leaf',
                "#{@val[1].fullId} is not a group resource",
                @sourceFileInfo[1])
        end
        @property.set('resourceroot', @val[1])
      })
      doc('resourceroot', Only resources below the specified root-level resources are exported. Theexported resources will have the ID of the root-level resource stripped fromtheir ID, so that the sub-resourcess of the root-level resource becometop-level resources in the report file.
         )
      example('ResourceRoot')

      pattern(%( _taskroot !taskId), lambda {
        if @val[1].leaf?
          error('taskroot_leaf',
                "#{@val[1].fullId} is not a container task",
                @sourceFileInfo[1])
        end
        @property.set('taskroot', @val[1])
      })
      doc('taskroot', Only tasks below the specified root-level tasks are exported. The exportedtasks will have the ID of the root-level task stripped from their ID, so thatthe sub-tasks of the root-level task become top-level tasks in the reportfile.
         )
      example('TaskRoot')

      pattern(%( !timeformat ), lambda {
        @property.set('timeFormat', @val[0])
      })

      pattern(%( _timezone !validTimeZone ), lambda {
        @property.set('timezone', @val[1])
      })
      doc('timezone.report', Sets the time zone used for all dates in the report. This setting is ignoredif the report is embedded into another report. Embedded in this context meansthe report is part of another generated report. It does not mean that thereport definition is a sub report of another report definition.
         )

      pattern(%( !reportTitle ))

      pattern(%( _width $INTEGER ), lambda {
        if @val[1] < 400
          error('min_report_width',
                "The report must have a minimum width of 400 pixels.")
        end
        @property.set('width', @val[1])
      })
      doc('width', Set the width of the report in pixels. This attribute is only used forreports that cannot determine the width based on the content. Such report canbe freely resized to fit in. The vast majority of reports can determine theirwidth based on the provided content. These reports will simply ignore thissetting.
         )
      also('height')
    end

rule_reportBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4628
    def rule_reportBody
      optionsRule('reportAttributes')
    end

rule_reportEnd() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4515
    def rule_reportEnd
      pattern(%( _end !date ), lambda {
        if @val[1] < @property.get('start')
          error('report_end',
                "End date must be before start date #{@property.get('start')}",
                @sourceFileInfo[1])
        end
        @property.set('end', @val[1])
      })
      doc('end.report', Specifies the end date of the report. In task reports only tasks that startbefore this end date are listed.
         )
      example('Export', '2')
    end

rule_reportId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4531
    def rule_reportId
      pattern(%( !reportIdUnverifd ), lambda {
        id = @val[0]
        if @property && @property.is_a?(Report)
          id = @property.fullId + '.' + id
        else
          id = @reportprefix + '.' + id unless @reportprefix.empty?
        end
        # In case we have a nested supplement, we need to prepend the parent ID.
        if (report = @project.report(id)).nil?
          error('report_id_expected', "#{id} is not a defined report.",
                @sourceFileInfo[0])
        end
        report
      })
      arg(0, 'report', 'The ID of a defined report')
    end

rule_reportIdUnverifd() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4549
    def rule_reportIdUnverifd
      singlePattern('$ABSOLUTE_ID')
      singlePattern('$ID')
    end

rule_reportName() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4554
    def rule_reportName
      pattern(%( $STRING ), lambda {
        @val[0]
      })
      arg(0, 'name', The name of the report. This will be the base name for generated output files.The suffix will depend on the specified [[formats]]. It will also be used innavigation bars.By default, report definitions do not generate any files. With more complexprojects, most report definitions will be used to describe elements ofcomposed reports. If you want to generate a file from this report, you mustspecify the list of [[formats]] that you want to generate. The report namewill then be used as a base name to create the file. The suffix will beappended based on the generated format.Reports have a local name space. All IDs and file names must be unique withinthe reports that belong to the same enclosing report. To reference a reportfor inclusion into another report, you need to specify the full report ID.This is composed of the report ID, prefixed by a dot-separated list of allparent report IDs.
         )
    end

rule_reportPeriod() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4579
    def rule_reportPeriod
      pattern(%( _period !interval ), lambda {
        @property.set('start', @val[1].start)
        @property.set('end', @val[1].end)
      })
      doc('period.report', This property is a shortcut for setting the start and end property at thesame time.
         )
    end

rule_reportProperties() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4591
    def rule_reportProperties
      pattern(%( !iCalReport ))
      pattern(%( !nikuReport ))
      pattern(%( !reports ))
      pattern(%( !tagfile ))
      pattern(%( !statusSheetReport ))
      pattern(%( !timeSheetReport ))
    end

rule_reportPropertiesBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4600
    def rule_reportPropertiesBody
      optional
      repeatable

      pattern(%( !macro ))
      pattern(%( !reportProperties ))
    end

rule_reportPropertiesFile() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4608
    def rule_reportPropertiesFile
      pattern(%( !reportPropertiesBody . ))
    end

rule_reportStart() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4612
    def rule_reportStart
      pattern(%( _start !date ), lambda {
        if @val[1] > @property.get('end')
          error('report_start',
                "Start date must be before end date #{@property.get('end')}",
                @sourceFileInfo[1])
        end
        @property.set('start', @val[1])
      })
      doc('start.report', Specifies the start date of the report. In task reports only tasks that endafter this end date are listed.
         )
    end

rule_reportTitle() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4632
    def rule_reportTitle
      pattern(%( _title $STRING ), lambda {
        @property.set('title', @val[1])
      })
      doc('title', The title of the report will be used in external references to the report. Itwill not show up in the reports directly. It's used e. g. by [[navigator]].
         )
    end

rule_reportableAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3747
    def rule_reportableAttributes
      singlePattern('_activetasks')
      descr(The number of sub-tasks (including the current task) that are active in thereported time period. Active means that they are ongoing at the current timeor [[now]] date.
           )

      singlePattern('_annualleave')
      descr(The number of annual leave units within the reported time period. The unitcan be adjusted with [[loadunit]].
           )

      singlePattern('_annualleavebalance')
      descr(The balance of the annual leave at the end of the reporting interval. The unitcan be adjusted with [[loadunit]].
           )

      singlePattern('_alert')
      descr(The alert level of the property that was reported with the date closest to theend date of the report. Container properties that don't have their own alertlevel reported with a date equal or newer than the alert levels of all theirsub properties will get the highest alert level of their direct subproperties.
           )

      singlePattern('_alertmessages')
      level(:deprecated)
      also('journal')
      descr('Deprecated. Please use ''''journal'''' instead')

      singlePattern('_alertsummaries')
      level(:deprecated)
      also('journal')
      descr('Deprecated. Please use ''''journal'''' instead')

      singlePattern('_alerttrend')
      descr(Shows how the alert level at the end of the report period compares to thealert level at the begining of the report period. Possible values are''''Up'''', ''''Down'''' or ''''Flat''''.
           )

      singlePattern('_balance')
      descr(The account balance at the beginning of the reported period. This is thebalance before any transactions of the reported period have been credited.
           )

      singlePattern('_bsi')
      descr('The hierarchical or work breakdown structure index (i. e. 1.2.3)')

      singlePattern('_chart')
      descr(A Gantt chart. This column type requires all lines to have the same fixedheight. This does not work well with rich text columns in some browsers. Someshow a scrollbar for the compressed table cells, others don't. It isrecommended, that you don't use rich text columns in conjuction with the chartcolumn.
           )

      singlePattern('_closedtasks')
      descr(The number of sub-tasks (including the current task) that have been closedduring the reported time period.  Closed means that they have and end datebefore the current time or [[now]] date.
           )

      singlePattern('_competitorcount')
      descr(The number of tasks that have successfully competed for the same resources andhave potentially delayed the completion of this task.
           )
      singlePattern('_competitors')
      descr(A list of tasks that have successfully competed for the same resources andhave potentially delayed the completion of this task.
           )

      singlePattern('_complete')
      descr(The completion degree of a task. Unless a completion degree is manuallyprovided, this is a computed value relative the [[now]] date of the project. Atask that has ended before the now date is always 100% complete. A task thatstarts at or after the now date is always 0%. For [[effort]] based task thecomputation degree is the percentage of done effort of the overall effort. Forother leaf task, the completion degree is the percentage of the already passedduration of the overall task duration. For container task, it's always theaverage of the direct sub tasks. If the sub tasks consist of a mixture ofeffort and non-effort tasks, the completion value is only of limited value.
           )

      pattern([ '_completed' ], lambda {
        'complete'
      })
      level(:deprecated)
      also('complete')
      descr('Deprecated alias for complete')

      singlePattern('_criticalness')
      descr('A measure for how much effort the resource is allocated for, or' +
            'how strained the allocated resources of a task are')

      singlePattern('_cost')
      descr(The cost of the task or resource. The use of this column requires that a costaccount has been set for the report using the [[balance]] attribute.
           )

      singlePattern('_daily')
      descr('A group of columns with one column for each day')

      singlePattern('_directreports')
      descr(The resources that have this resource assigned as manager.The list can be customized by the [[listitem.column|listitem]] attribute.
           )

      singlePattern('_duration')
      descr('The duration of a task')

      singlePattern('_duties')
      descr('List of tasks that the resource is allocated to')

      singlePattern('_efficiency')
      descr('Measure for how efficient a resource can perform tasks')

      singlePattern('_effort')
      descr('The allocated effort during the reporting period')

      singlePattern('_effortdone')
      descr('The already completed effort as of now')

      singlePattern('_effortleft')
      descr('The remaining allocated effort as of now')

      singlePattern('_email')
      descr('The email address of a resource')

      singlePattern('_end')
      descr('The end date of a task')

      singlePattern('_flags')
      descr('List of attached flags')

      singlePattern('_followers')
      descr(A list of tasks that depend on the current task. The list contains the names,the IDs, the date and the type of dependency. For the type the followingsymbols are used for <nowiki><dep></nowiki>.* '''<nowiki>]->[</nowiki>''': End-to-Start dependency* '''<nowiki>[->[</nowiki>''': Start-to-Start dependency* '''<nowiki>]->]</nowiki>''': End-to-End dependency* '''<nowiki>[->]</nowiki>''': Start-to-End dependencyThe list can be customized by the [[listitem.column|listitem]] attribute.The dependency symbol can be generated via the ''''dependency'''' attributeinthe query, the target date via the ''''date'''' attribute.
           )

      singlePattern('_freetime')
      descr(The amount of unallocated work time of a resource during the reporting period.
           )

      singlePattern('_freework')
      descr(The amount of unallocated work capacity of a resource during the reportingperiod. This is the product of unallocated work time times the efficiency ofthe resource.
           )

      singlePattern('_fte')
      descr(The Full-Time-Equivalent of a resource or group. This is the ratio of theresource working time and the global working time. Working time is defined byworking hours and leaves. The FTE value can vary over time and iscalculated for the report interval or the user specified interval.
           )

      singlePattern('_gauge')
      descr(When [[complete]] values have been provided to capture the actual progress ontasks, the gauge column will list whether the task is ahead of, behind or onschedule.
           )

      singlePattern('_headcount')
      descr(For resources this is the headcount number of the resource or resource group.For a single resource this is the [[efficiency]] rounded to the next integer.For a group it is the sum of the sub resources headcount.For tasks it's the number of different resources allocated to the task duringthe report interval. Resources are weighted with their rounded efficiencies.
           )

      pattern([ '_hierarchindex' ], lambda {
        'bsi'
      })
      level(:deprecated)
      also('bsi')
      descr('Deprecated alias for bsi')

      singlePattern('_hourly')
      descr('A group of columns with one column for each hour')

      singlePattern('_id')
      descr('The id of the item')

      singlePattern('_index')
      descr('The index of the item based on the nesting hierachy')

      singlePattern('_inputs')
      descr(A list of milestones that are a prerequiste for the current task. Forcontainer tasks it will also include the inputs of the child tasks. Inputs maynot have any predecessors.The list can be customized by the [[listitem.column|listitem]] attribute.
           )

      singlePattern('_journal')
      descr(The journal entries for the task or resource for the reported interval. Thegenerated text can be customized with the [[journalmode]],[[journalattributes]], [[hidejournalentry]] and [[sortjournalentries]]. Ifused in queries without a property context, the journal for the completeproject is generated.
           )

      singlePattern('_journal_sub')
      level(:deprecated)
      also('journal')
      descr('Deprecated. Please use ''''journal'''' instead')

      singlePattern('_journalmessages')
      level(:deprecated)
      also('journal')
      descr('Deprecated. Please use ''''journal'''' instead')

      singlePattern('_journalsummaries')
      level(:deprecated)
      also('journal')
      descr('Deprecated. Please use ''''journal'''' instead')

      singlePattern('_line')
      descr('The line number in the report')

      singlePattern('_managers')
      descr(A list of managers that the resource reports to.The list can be customized by the [[listitem.column|listitem]] attribute.
          )

      singlePattern('_maxend')
      descr('The latest allowed end of a task')

      singlePattern('_maxstart')
      descr('The lastest allowed start of a task')

      singlePattern('_minend')
      descr('The earliest allowed end of a task')

      singlePattern('_minstart')
      descr('The earliest allowed start of a task')

      singlePattern('_monthly')
      descr('A group of columns with one column for each month')

      singlePattern('_no')
      descr('The object line number in the report (Cannot be used for sorting!)')

      singlePattern('_name')
      descr('The name or description of the item')

      singlePattern('_note')
      descr('The note attached to a task')

      singlePattern('_opentasks')
      descr(The number of sub-tasks (including the current task) that have not yet beenclosed during the reported time period. Closed means that they have and enddate before the current time or [[now]] date.
           )

      singlePattern('_pathcriticalness')
      descr('The criticalness of the task with respect to all the paths that ' +
            'it is a part of.')

      singlePattern('_precursors')
      descr(A list of tasks the current task depends on. The list contains the names, theIDs, the date and the type of dependency. For the type the following symbolsare used* '''<nowiki>]->[</nowiki>''': End-to-Start dependency* '''<nowiki>[->[</nowiki>''': Start-to-Start dependency* '''<nowiki>]->]</nowiki>''': End-to-End dependency* '''<nowiki>[->]</nowiki>''': Start-to-End dependencyThe list can be customized by the [[listitem.column|listitem]] attribute.The dependency symbol can be generated via the ''''dependency'''' attributeinthe query, the target date via the ''''date'''' attribute.
           )

      singlePattern('_priority')
      descr('The priority of a task')

      singlePattern('_quarterly')
      descr('A group of columns with one column for each quarter')

      singlePattern('_rate')
      descr('The daily cost of a resource.')

      singlePattern('_reports')
      descr(All resources that have this resource assigned as a direct or indirect manager.The list can be customized by the [[listitem.column|listitem]] attribute.
           )

      singlePattern('_resources')
      descr(A list of resources that are assigned to the task in the report time frame.The list can be customized by the [[listitem.column|listitem]] attribute.
           )

      singlePattern('_responsible')
      descr(The responsible people for this task.The list can be customized by the [[listitem.column|listitem]] attribute.
           )

      singlePattern('_revenue')
      descr(The revenue of the task or resource. The use of this column requires that arevenue account has been set for the report using the [[balance]] attribute.
           )

      singlePattern('_scenario')
      descr('The name of the scenario')

      singlePattern('_scheduling')
      descr(The scheduling mode of the leaf tasks. ASAP tasks are scheduled start to end while ALAP tasks are scheduled end to start.
           )

      singlePattern('_seqno')
      descr('The index of the item based on the declaration order')

      singlePattern('_sickleave')
      descr(The number of sick leave units within the reported time period. The unit canbe adjusted with [[loadunit]].
           )

      singlePattern('_specialleave')
      descr(The number of special leave units within the reported time period. The unitcan be adjusted with [[loadunit]].
           )

      singlePattern('_start')
      descr('The start date of the task')

      singlePattern('_status')
      descr(The status of a task. It is determined based on the current date or the datespecified by [[now]].
           )

      singlePattern('_targets')
      descr(A list of milestones that depend on the current task. For container tasks itwill also include the targets of the child tasks. Targets may not have anyfollower tasks.The list can be customized by the [[listitem.column|listitem]] attribute.
           )

      singlePattern('_turnover')
      descr(The financial turnover of an account during the reporting interval.
           )

      pattern([ '_wbs' ], lambda {
        'bsi'
      })
      level(:deprecated)
      also('bsi')
      descr('Deprecated alias for bsi.')

      singlePattern('_unpaidleave')
      descr(The number of unpaid leave units within the reported time period. The unitcan be adjusted with [[loadunit]].
           )

      singlePattern('_weekly')
      descr('A group of columns with one column for each week')

      singlePattern('_yearly')
      descr('A group of columns with one column for each year')

    end

rule_reports() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 3738
    def rule_reports
      pattern(%( !accountReport ))
      pattern(%( !export ))
      pattern(%( !resourceReport ))
      pattern(%( !taskReport ))
      pattern(%( !textReport ))
      pattern(%( !traceReport ))
    end

rule_resource() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4643
    def rule_resource
      pattern(%( !resourceHeader !resourceBody ), lambda {
         @property = @property.parent
      })
      doc('resource', Tasks that have an effort specification need to have at least one resourceassigned to do the work. Use this property to define resources or groups ofresources.Resources have a global name space. All IDs must be unique within the resourcesof the project.
         )
    end

rule_resourceAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4658
    def rule_resourceAttributes
      repeatable
      optional
      pattern(%( _email $STRING ), lambda {
        @property.set('email', @val[1])
      })
      doc('email',
          'The email address of the resource.')

      pattern(%( !journalEntry ))
      pattern(%( !purge ))
      pattern(%( !resource ))
      pattern(%( !resourceScenarioAttributes ))
      pattern(%( !scenarioIdCol !resourceScenarioAttributes ), lambda {
        @scenarioIdx = 0
      })

      pattern(%( _supplement !resourceId !resourceBody ), lambda {
        @property = @idStack.pop
      })
      doc('supplement.resource', The supplement keyword provides a mechanism to add more attributes to alreadydefined resources. The additional attributes must obey the same rules as inregular resource definitions and must be enclosed by curly braces.This construct is primarily meant for situations where the information about aresource is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool.
         )
      example('Supplement', 'resource')

      # Other attributes will be added automatically.
    end

rule_resourceBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4693
    def rule_resourceBody
      optionsRule('resourceAttributes')
    end

rule_resourceBooking() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4697
    def rule_resourceBooking
      pattern(%( !resourceBookingHeader !bookingBody ), lambda {
        unless @project.scenario(@scenarioIdx).get('ownbookings')
          error('no_own_resource_booking',
                "The scenario #{@project.scenario(@scenarioIdx).fullId} " +
                'inherits its bookings from the tracking ' +
                'scenario. You cannot specificy additional bookings for it.')
        end
        @val[0].task.addBooking(@scenarioIdx, @val[0])
      })
    end

rule_resourceBookingHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4709
    def rule_resourceBookingHeader
      pattern(%( !taskId !valIntervals ), lambda {
        checkBooking(@val[0], @property)
        @booking = Booking.new(@property, @val[0], @val[1])
        @booking.sourceFileInfo = @sourceFileInfo[0]
        @booking
      })
      arg(0, 'id', 'Absolute ID of a defined task')
    end

rule_resourceHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4731
      def rule_resourceHeader
        pattern(%( _resource !optionalID $STRING ), lambda {
          if @property.nil? && !@resourceprefix.empty?
            @property = @project.resource(@resourceprefix)
          end
          if @val[1] && @project.resource(@val[1])
            error('resource_exists',
                  "Resource #{@val[1]} has already been defined.",
                  @sourceFileInfo[1], @property)
          end
          @property = Resource.new(@project, @val[1], @val[2], @property)
          @property.sourceFileInfo = @sourceFileInfo[0]
          @property.inheritAttributes
          @scenarioIdx = 0
        })
    #    arg(1, 'id', <<'EOT'
    #The ID of the resource. Resources have a global name space. The ID must be
    #unique within the whole project.
    #EOT
    #       )
        arg(2, 'name', 'The name of the resource')
      end

rule_resourceId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4719
    def rule_resourceId
      pattern(%( $ID ), lambda {
        id = (@resourceprefix.empty? ? '' : @resourceprefix + '.') + @val[0]
        if (resource = @project.resource(id)).nil?
          error('resource_id_expected', "#{id} is not a defined resource.",
                @sourceFileInfo[0])
        end
        resource
      })
      arg(0, 'resource', 'The ID of a defined resource')
    end

rule_resourceLeafList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4754
    def rule_resourceLeafList
      listRule('moreResourceLeafList', '!leafResourceId')
    end

rule_resourceList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4758
    def rule_resourceList
      listRule('moreResources', '!resourceId')
    end

rule_resourceReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4762
    def rule_resourceReport
      pattern(%( !resourceReportHeader !reportBody ), lambda {
        @property = @property.parent
      })
      doc('resourcereport', The report lists resources and their respective values in a table. The taskthat are the resources are allocated to can be listed as well. To reduce thelist of included resources, you can use the [[hideresource]],[[rollupresource]] or [[resourceroot]] attributes. The order of the task canbe controlled with [[sortresources]]. If the first sorting criteria is treesorting, the parent resources will always be included to form the tree.Tree sorting is the default. You need to change it if you do not want certainparent resources to be included in the report.By default, all the tasks that the resources are allocated to are hidden, butthey can be listed as well. Use the [[hidetask]] attribute to select whichtasks should be included.
         )
    end

rule_resourceReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4783
    def rule_resourceReportHeader
      pattern(%( _resourcereport !optionalID !reportName ), lambda {
        newReport(@val[1], @val[2], :resourcereport, @sourceFileInfo[0]) do
          unless @property.modified?('columns')
            # Set the default columns for this report.
            %( no name ).each do |col|
              @property.get('columns') <<
              TableColumnDefinition.new(col, columnTitle(col))
            end
          end
          # Show all resources, sorted by tree and id-up.
          unless @property.modified?('hideResource')
            @property.set('hideResource',
                          LogicalExpression.new(LogicalOperation.new(0)))
          end
          unless @property.modified?('sortResources')
            @property.set('sortResources', [ [ 'tree', true, -1 ],
                          [ 'id', true, -1 ] ])
          end
          # Hide all resources, but set sorting to tree, start-up, seqno-up.
          unless @property.modified?('hideTask')
            @property.set('hideTask',
                          LogicalExpression.new(LogicalOperation.new(1)))
          end
          unless @property.modified?('sortTasks')
            @property.set('sortTasks',
                          [ [ 'tree', true, -1 ],
                            [ 'start', true, 0 ],
                            [ 'seqno', true, -1 ] ])
          end
        end
      })
    end

rule_resourceScenarioAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4817
    def rule_resourceScenarioAttributes
      pattern(%( !chargeset ))

      pattern(%( _efficiency !number ), lambda {
        @property['efficiency', @scenarioIdx] = @val[1]
      })
      doc('efficiency', The efficiency of a resource can be used for two purposes. First you can useit as a crude way to model a team. A team of 5 people should have anefficiency of 5.0. Keep in mind that you cannot track the members of the teamindividually if you use this feature. They always act as a group.The other use is to model performance variations between your resources. Again, this is a fairly crude mechanism and should be used with care. A resource that isn't every good at some task might be pretty good at another. This can't be taken into account as the resource efficiency can only set globally for all tasks.All resources that do not contribute effort to the task, should have anefficiency of 0.0. A typical example would be a conference room. It's necessary for a meeting, but it does not contribute any work.
         )
      example('Efficiency')
      pattern(%( !flags ))
      doc('flags.resource', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
         )

      pattern(%( _booking !resourceBooking ))
      doc('booking.resource', The booking attribute can be used to report actually completed work.  A taskwith bookings must be [[scheduling|scheduled]] in ''''asap'''' mode.  If thescenario is not the [[trackingscenario|tracking scenario]] or derived from it,the scheduler will not allocate resources prior to the current date or thedate specified with [[now]] when a task has at least one booking.Bookings are only valid in the scenario they have been defined in. They willin general not be passed to any other scenario. If you have defined a[[trackingscenario|tracking scenario]], the bookings of this scenario will bepassed to all the derived scenarios of the tracking scenario.The sloppy attribute can be used when you want to skip non-working time orother allocations automatically. If it's not given, all bookings must onlycover working time for the resource.The booking attributes is designed to capture the exact amount of completedwork. This attribute is not really intended to specify completed effort byhand. Usually, booking statements are generated by [[export]] reports. The[[sloppy.booking|sloppy]] and [[overtime.booking|overtime]] attributes areonly kludge for users who want to write them manually.Bookings can be used to report already completed work by specifying the exacttime intervals a certain resource has worked on this task.Bookings can be defined in the task or resource context. If you move tasksaround very often, put your bookings in the task context.
         )
      also(%( scheduling booking.task ))
      example('Booking')

      pattern(%( !fail ))

      pattern(%( !leaveAllowances ))

      pattern(%( !leaves ), lambda {
        @property['leaves', @scenarioIdx] += @val[0]
      })

      pattern(%( !limits ), lambda {
        @property['limits', @scenarioIdx] = @val[0]
      })
      doc('limits.resource', Set per-interval usage limits for the resource.
         )
      example('Limits-1', '6')

      pattern(%( _managers !resourceList ), lambda {
        @property['managers', @scenarioIdx] =
          @property['managers', @scenarioIdx] + @val[1]
      })
      doc('managers', Defines one or more resources to be the manager who is responsible for thisresource. Managers must be leaf resources. This attribute does not impact thescheduling. It can only be used for documentation purposes.You must only specify direct managers here. Do not list higher level managershere. If necessary, use the [[purge]] attribute to clearinherited managers. For most use cases, there should be only one manager. ButTaskJuggler is not limited to just one manager. Dotted reporting lines can becaptured as well as long as the managers are not reporting to each other.
         )
      also(%( statussheet ))
      example('Manager')

      pattern(%( _rate !number ), lambda {
        @property['rate', @scenarioIdx] = @val[1]
      })
      doc('rate.resource', The rate specifies the daily cost of the resource.
         )

      pattern(%( !resourceShiftAssignments !shiftAssignments ), lambda {
        checkContainer('shifts')
        # Set same value again to set the 'provided' state for the attribute.
        begin
          @property['shifts', @scenarioIdx] = @shiftAssignments
        rescue AttributeOverwrite
          # Multiple shift assignments are a common idiom, so don't warn about
          # them.
        end
        @shiftAssignments = nil
      })
      level(:deprecated)
      also('shift.resource')
      doc('shift.resource', This keyword has been deprecated. Please use [[shifts.resource|shifts(resource)]] instead.
         )

      pattern(%( !resourceShiftsAssignments !shiftAssignments ), lambda {
        checkContainer('shifts')
        # Set same value again to set the 'provided' state for the attribute.
        begin
          @property['shifts', @scenarioIdx] = @shiftAssignments
        rescue AttributeOverwrite
          # Multiple shift assignments are a common idiom, so don't warn about
          # them.
        end
        @shiftAssignments = nil
      })
      doc('shifts.resource', Limits the working time of a resource to a defined shift during the specifiedinterval. Multiple shifts can be defined, but shift intervals may not overlap.In case a shift is defined for a certain interval, the shift working hoursreplace the standard resource working hours for this interval.
          )

      pattern(%( _vacation !vacationName !intervals ), lambda {
        @val[2].each do |interval|
          # We map the old 'vacation' attribute to public holidays.
          @property['leaves', @scenarioIdx] += [ Leave.new(:holiday, interval) ]
        end
      })
      doc('vacation.resource', Specify a vacation period for the resource. It can also be used to block outthe time before a resource joined or after it left. For employees changingtheir work schedule from full-time to part-time, or vice versa, please referto the 'Shift' property.
         )

      pattern(%( !warn ))

      pattern(%( !workinghoursResource ))
      # Other attributes will be added automatically.
    end

rule_resourceShiftAssignments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4978
    def rule_resourceShiftAssignments
      pattern(%( _shift ), lambda {
        @shiftAssignments = @property['shifts', @scenarioIdx]
      })
    end

rule_resourceShiftsAssignments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4984
    def rule_resourceShiftsAssignments
      pattern(%( _shifts ), lambda {
        @shiftAssignments = @property['shifts', @scenarioIdx]
      })
    end

rule_rollupaccount() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 4990
    def rule_rollupaccount
      pattern(%( _rollupaccount !logicalExpression ), lambda {
        @property.set('rollupAccount', @val[1])
      })
      doc('rollupaccount', Do not show sub-accounts of accounts that match the specified[[logicalexpression|logical expression]].
         )
    end

rule_rollupresource() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5001
    def rule_rollupresource
      pattern(%( _rollupresource !logicalExpression ), lambda {
        @property.set('rollupResource', @val[1])
      })
      doc('rollupresource', Do not show sub-resources of resources that match the specified[[logicalexpression|logical expression]].
         )
      example('RollupResource')
    end

rule_rolluptask() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5013
    def rule_rolluptask
      pattern(%( _rolluptask !logicalExpression ), lambda {
        @property.set('rollupTask', @val[1])
      })
      doc('rolluptask', Do not show sub-tasks of tasks that match the specified[[logicalexpression|logical expression]].
         )
    end

rule_scenario() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5025
    def rule_scenario
      pattern(%( !scenarioHeader !scenarioBody ), lambda {
        @property = @property.parent
      })
      doc('scenario', Defines a new project scenario. By default, the project has only one scenariocalled ''''plan''''. To do plan vs. actual comparisons or to do awhat-if-analysis, you can define a set of scenarios. There can only be onetop-level scenario. Additional scenarios are either derived from thistop-level scenario or other scenarios.Each nested scenario is a variation of the enclosing scenario. All scenariosshare the same set of properties (task, resources, etc.) but the attributesthat are listed as scenario specific may differ between the variousscenarios. A nested scenario uses all attributes from the enclosing scenariounless the user has specified a different value for this attribute.By default, the scheduler assigns resources to task beginning with the projectstart date. If the scenario is switched to projection mode, no assignmentswill be made prior to the current date or the date specified by [[now]]. Inthis case, TaskJuggler assumes, that all assignements prior to thecurrent date have been provided by [[booking.task]] statements.
         )
    end

rule_scenarioAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5051
    def rule_scenarioAttributes
      optional
      repeatable

      pattern(%( _active !yesNo), lambda {
        @property.set('active', @val[1])
      })
      doc('active', Enable the scenario to be scheduled or not. By default, all scenarios will bescheduled. If a scenario is marked as inactive, it not be scheduled and willbe ignored in the reports.
         )
      pattern(%( _disabled ), lambda {
        @property.set('active', false)
      })
      level(:deprecated)
      also('active')
      doc('disabled', This attribute is deprecated. Please use [active] instead.Disable the scenario for scheduling. The default for the top-levelscenario is to be enabled.
         )
      example('Scenario')
      pattern(%( _enabled ), lambda {
        @property.set('active', true)
      })
      level(:deprecated)
      also('active')
      doc('enabled', This attribute is deprecated. Please use [active] instead.Enable the scenario for scheduling. This is the default for the top-levelscenario.
         )

      pattern(%( _projection !projection ))
      level(:deprecated)
      also('booking.task')
      doc('projection', This keyword has been deprecated! Don't use it anymore!Projection mode is now automatically enabled as soon as a scenario hasbookings.
         )

      pattern(%( !scenario ))
    end

rule_scenarioBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5104
    def rule_scenarioBody
      optionsRule('scenarioAttributes')
    end

rule_scenarioHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5108
    def rule_scenarioHeader

      pattern(%( _scenario $ID $STRING ), lambda {
        # If this is the top-level scenario, we must delete the default scenario
        # first.
        @project.scenarios.each do |scenario|
          if scenario.get('projection')
            error('scenario_after_tracking',
                  'Scenarios must be defined before a tracking scenario is set.')
          end
        end
        @project.scenarios.clearProperties if @property.nil?
        if @project.scenario(@val[1])
          error('scenario_exists',
                "Scenario #{@val[1]} has already been defined.",
                @sourceFileInfo[1])
        end
        @property = Scenario.new(@project, @val[1], @val[2], @property)
        @property.inheritAttributes

        if @project.scenarios.length > 1
          MessageHandlerInstance.instance.hideScenario = false
        end
      })
      arg(1, 'id', 'The ID of the scenario')
      arg(2, 'name', 'The name of the scenario')
    end

rule_scenarioId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5136
    def rule_scenarioId
      pattern(%( $ID ), lambda {
        if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
          error('unknown_scenario_id', "Unknown scenario: #{@val[0]}",
                @sourceFileInfo[0])
        end
        @scenarioIdx
      })
      arg(0, 'scenario', 'ID of a defined scenario')
    end

rule_scenarioIdCol() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5147
    def rule_scenarioIdCol
      pattern(%( $ID_WITH_COLON ), lambda {
        if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
          error('unknown_scenario_id', "Unknown scenario: #{@val[0]}",
                @sourceFileInfo[0])
        end
      })
    end

rule_scenarioIdList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5156
    def rule_scenarioIdList
      listRule('moreScnarioIdList', '!scenarioIdx')
    end

rule_scenarioIdx() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5160
    def rule_scenarioIdx
      pattern(%( $ID ), lambda {
        if (scenarioIdx = @project.scenarioIdx(@val[0])).nil?
          error('unknown_scenario_idx', "Unknown scenario #{@val[0]}",
                @sourceFileInfo[0])
        end
        scenarioIdx
      })
    end

rule_schedulingDirection() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5170
    def rule_schedulingDirection
      singlePattern('_alap')
      singlePattern('_asap')
    end

rule_shift() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5175
    def rule_shift
      pattern(%( !shiftHeader !shiftBody ), lambda {
        @property = @property.parent
      })
      doc('shift', A shift combines several workhours related settings in a reusable entity.Besides the weekly working hours it can also hold information such as leavesand a time zone. It lets you create a work time calendar that can be used tolimit the working time for resources or tasks.Shifts have a global name space. All IDs must be unique within the shifts ofthe project.
         )
      also(%( shifts.task shifts.resource ))
    end

rule_shiftAssignment() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5192
    def rule_shiftAssignment
      pattern(%( !shiftId !intervalOptional ), lambda {
        # Make sure we have a ShiftAssignment for the property.
        unless @shiftAssignments
          @shiftAssignments = ShiftAssignments.new
          @shiftAssignments.project = @project
        end

        if @val[1].nil?
          interval = TimeInterval.new(@project['start'], @project['end'])
        else
          interval = @val[1]
        end
        if !@shiftAssignments.addAssignment(
           ShiftAssignment.new(@val[0].scenario(@scenarioIdx), interval))
          error('shift_assignment_overlap',
                'Shifts may not overlap each other.',
                @sourceFileInfo[0], @property)
        end
        @shiftAssignments.assignments.last
      })
    end

rule_shiftAssignments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5215
    def rule_shiftAssignments
      listRule('moreShiftAssignments', '!shiftAssignment')
    end

rule_shiftAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5219
    def rule_shiftAttributes
      optional
      repeatable

      pattern(%( !shift ))
      pattern(%( !shiftScenarioAttributes ))
      pattern(%( !scenarioIdCol !shiftScenarioAttributes ), lambda {
        @scenarioIdx = 0
      })
    end

rule_shiftBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5230
    def rule_shiftBody
      optionsRule('shiftAttributes')
    end

rule_shiftHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5234
    def rule_shiftHeader
      pattern(%( _shift !optionalID $STRING ), lambda {
        if @val[1] && @project.shift(@val[1])
          error('shift_exists', "Shift #{@val[1]} has already been defined.",
                @sourceFileInfo[1])
        end
        @property = Shift.new(@project, @val[1], @val[2], @property)
        @property.sourceFileInfo = @sourceFileInfo[0]
        @property.inheritAttributes
        @scenarioIdx = 0
      })
      arg(2, 'name', 'The name of the shift')
    end

rule_shiftId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5248
    def rule_shiftId
      pattern(%( $ID ), lambda {
        if (shift = @project.shift(@val[0])).nil?
          error('shift_id_expected', "#{@val[0]} is not a defined shift.",
                @sourceFileInfo[0])
        end
        shift
      })
      arg(0, 'shift', 'The ID of a defined shift')
    end

rule_shiftScenarioAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5259
    def rule_shiftScenarioAttributes
      pattern(%( !leaves ), lambda {
        @property['leaves', @scenarioIdx] += @val[0]
      })

      pattern(%( _replace ), lambda {
        @property['replace', @scenarioIdx] = true
      })
      doc('replace', This replace mode is only effective for shifts that are assigned to resourcesdirectly. When replace mode is activated the leave definitions of the shiftwill replace all the leave definitions of the resource for the given period.The mode is not effective for shifts that are assigned to tasks or allocations.
         )

      pattern(%( _timezone !validTimeZone ), lambda {
        @property['timezone', @scenarioIdx] = @val[1]
      })
      doc('timezone.shift', Sets the time zone of the shift. The working hours of the shift are assumed tobe within the specified time zone. The time zone does not effect the vactioninterval. The latter is assumed to be within the project time zone.TaskJuggler stores all dates internally as UTC. Since all events must alignwith the [[timingresolution|timing resolution]] for time zones you may have tochange the timing resolution appropriately. The time zone difference comparedto UTC must be a multiple of the used timing resolution.
          )
      arg(1, 'zone', Time zone to use. E. g. 'Europe/Berlin' or 'America/Denver'. Don't use the 3letter acronyms. See[http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones Wikipedia] forpossible values.
         )

      pattern(%( _vacation !vacationName !intervalsOptional ), lambda {
        @val[2].each do |interval|
          # We map the old 'vacation' attribute to public holidays.
          @property['leaves', @scenarioIdx] += [ Leave.new(:holiday, interval) ]
        end
      })
      doc('vacation.shift', Specify a vacation period associated with this shift.
         )

      pattern(%( !workinghoursShift ))
    end

rule_sortAccounts() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5397
    def rule_sortAccounts
      pattern(%( _sortaccounts !sortCriteria ), lambda {
        @property.set('sortAccounts', @val[1])
      })
      doc('sortaccounts', Determines how the accounts are sorted in the report. Multiple criteria can bespecified as a comma separated list. If one criteria is not sufficient to sorta group of accounts, the next criteria will be used to sort the accounts inthis group.
         )
    end

rule_sortCriteria() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5312
    def rule_sortCriteria
      pattern([ "!sortCriterium", "!moreSortCriteria" ], lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_sortCriterium() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5318
    def rule_sortCriterium
      pattern(%( !sortTree ), lambda {
        @val[0]
      })
      pattern(%( !sortNonTree ), lambda {
        @val[0]
      })
    end

rule_sortJournalEntries() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5372
    def rule_sortJournalEntries
      pattern(%( _sortjournalentries !journalSortCriteria ), lambda {
        @property.set('sortJournalEntries', @val[1])
      })
      doc('sortjournalentries', Determines how the entries in a journal are sorted. Multiple criteria can bespecified as a comma separated list. If one criteria is not sufficient to sorta group of journal entries, the next criteria will be used to sort the entriesin this group.The following values are supported:* ''''date.down'''': Sort descending order by the date of the journal entry* ''''date.up'''': Sort ascending order by the date of the journal entry* ''''alert.down'''': Sort in descending order by the alert level of thejournal entry* ''''alert.up'''': Sort in ascending order by the alert level of thejournal entry ''''property.down'''': Sort in descending order by the task or resourcethe journal entry is associated with* ''''property.up'''': Sort in ascending order by the task or resource thejournal entry is associated with
          )
    end

rule_sortNonTree() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5327
    def rule_sortNonTree
      pattern(%( $ABSOLUTE_ID ), lambda {
        args = @val[0].split('.')
        case args.length
        when 2
          # <attribute>.<up|down>
          scenario = -1
          direction = args[1] == 'up'
          attribute = args[0]
        when 3
          # <scenario>.<attribute>.<up|down>
          if (scenario = @project.scenarioIdx(args[0])).nil?
            error('sort_unknown_scen',
                  "Unknown scenario #{args[0]} in sorting criterium",
                  @sourceFileInfo[0])
          end
          attribute = args[1]
          if args[2] != 'up' && args[2] != 'down'
            error('sort_direction', "Sorting direction must be 'up' or 'down'",
                  @sourceFileInfo[0])
          end
          direction = args[2] == 'up'
        else
          error('sorting_crit_exptd1',
                "Sorting criterium expected (e.g. tree, start.up or " +
                "plan.end.down).", @sourceFileInfo[0])
        end
        if attribute == 'bsi'
          error('sorting_bsi',
                "Sorting by bsi is not supported. Please use 'tree' " +
                '(without appended .up or .down) instead.',
                @sourceFileInfo[0])
        end
        [ attribute, direction, scenario ]
      })
      arg(0, 'criteria', The sorting criteria must consist of a property attribute ID. See [[columnid]]for a complete list of available attributes. The ID must be suffixed by '.up'or '.down' to determine the sorting direction. Optionally the ID may beprefixed with a scenario ID and a dot to determine the scenario that should beused for sorting. So, possible values are 'plan.start.up' or 'priority.down'.
           )
    end

rule_sortResources() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5410
    def rule_sortResources
      pattern(%( _sortresources !sortCriteria ), lambda {
        @property.set('sortResources', @val[1])
      })
      doc('sortresources', Determines how the resources are sorted in the report. Multiple criteria can bespecified as a comma separated list. If one criteria is not sufficient to sorta group of resources, the next criteria will be used to sort the resources inthis group.
         )
    end

rule_sortTasks() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5423
    def rule_sortTasks
      pattern(%( _sorttasks !sortCriteria ), lambda {
        @property.set('sortTasks', @val[1])
      })
      doc('sorttasks', Determines how the tasks are sorted in the report. Multiple criteria can bespecified as comma separated list. If one criteria is not sufficient to sort agroup of tasks, the next criteria will be used to sort the tasks withinthis group.
         )
    end

rule_sortTree() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5436
    def rule_sortTree
      pattern(%( $ID ), lambda {
        if @val[0] != 'tree'
          error('sorting_crit_exptd2',
                "Sorting criterium expected (e.g. tree, start.up or " +
                "plan.end.down).", @sourceFileInfo[0])
        end
        [ 'tree', true, -1 ]
      })
      arg(0, 'tree',
          'Use \tree\ as first criteria to keep the breakdown structure.')
    end

rule_ssReportAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5475
    def rule_ssReportAttributes
      optional
      repeatable

      pattern(%( !hideresource ))
      pattern(%( !hidetask ))
      pattern(%( !reportEnd ))
      pattern(%( !reportPeriod ))
      pattern(%( !reportStart ))
      pattern(%( !sortResources ))
      pattern(%( !sortTasks ))
    end

rule_ssReportBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5488
    def rule_ssReportBody
      optionsRule('ssReportAttributes')
    end

rule_ssReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5448
    def rule_ssReportHeader
      pattern(%( _statussheetreport !optionalID $STRING ), lambda {
        newReport(@val[1], @val[2], :statusSheet, @sourceFileInfo[0]) do
          @property.set('formats', [ :tjp ])

          unless (@project['trackingScenarioIdx'])
            error('ss_no_tracking_scenario',
                  'You must have a tracking scenario defined to use status sheets.')
          end
          # Show all tasks, sorted by id-up.
          @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortTasks', [ [ 'id', true, -1 ] ])
          # Show all resources, sorted by seqno-up.
          @property.set('hideResource',
                        LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
          @property.set('loadUnit', :hours)
          @property.set('definitions', [])
        end
      })
      arg(2, 'file name', The name of the status sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel.
         )
    end

rule_ssStatus() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5531
    def rule_ssStatus
      pattern(%( !ssStatusHeader !ssStatusBody ))
      doc('status.statussheet', The status attribute can be used to describe the current status of the task orresource. The content of the status messages is added to the project journal.
         )
    end

rule_ssStatusAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5492
    def rule_ssStatusAttributes
      optional
      repeatable

      pattern(%( !author ))
      pattern(%( !details ))

      pattern(%( _flags !flagList ), lambda {
        @val[1].each do |flag|
          next if @journalEntry.flags.include?(flag)

          @journalEntry.flags << flag
        end
      })
      doc('flags.statussheet', Status sheet entries can have flags attached to them. These can be used toinclude only entries in a report that have a certain flag.
         )

      pattern(%( !summary ))
    end

rule_ssStatusBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5515
    def rule_ssStatusBody
      optional
      pattern(%( _{ !ssStatusAttributes _} ))
    end

rule_ssStatusHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5520
    def rule_ssStatusHeader
      pattern(%( _status !alertLevel $STRING ), lambda {
        @journalEntry = JournalEntry.new(@project['journal'], @sheetEnd,
                                         @val[2], @property,
                                         @sourceFileInfo[0])
        @journalEntry.alertLevel = @val[1]
        @journalEntry.author = @sheetAuthor
        @journalEntry.moderators << @sheetModerator
      })
    end

rule_statusSheet() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5540
    def rule_statusSheet
      pattern(%( !statusSheetHeader !statusSheetBody ), lambda {
        [ @sheetAuthor, @sheetStart, @sheetEnd ]
      })
      doc('statussheet', A status sheet can be used to capture the status of various tasks outside ofthe regular task tree definition. It is intended for use by managers thatdon't directly work with the full project plan, but need to report the currentstatus of each task or task-tree that they are responsible for.
         )
      example('StatusSheet')
    end

rule_statusSheetAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5554
    def rule_statusSheetAttributes
      optional
      repeatable

      pattern(%( !statusSheetTask ))
    end

rule_statusSheetBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5561
    def rule_statusSheetBody
      optionsRule('statusSheetAttributes')
    end

rule_statusSheetFile() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5565
    def rule_statusSheetFile
      pattern(%( !statusSheet . ), lambda {
        @val[0]
      })
      lastSyntaxToken(1)
    end

rule_statusSheetHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5573
    def rule_statusSheetHeader
      pattern(%( _statussheet !resourceId !valIntervalOrDate ), lambda {
        unless @project['trackingScenarioIdx']
          error('ss_no_tracking_scenario',
                'No trackingscenario defined.')
        end
        @sheetAuthor = @val[1]
        @sheetModerator = @val[1]
        @sheetStart = @val[2].start
        @sheetEnd = @val[2].end
        # Make sure that we don't have any status sheet entries from the same
        # author for the same report period. There may have been a previous
        # submission of the same report and this is an update to it. All old
        # entries must be removed before we process the sheet.
        @project['journal'].delete_if do |e|
          # Journal entries from status sheets have the sheet end date as entry
          # date.
          e.moderators.include?(@sheetModerator) && e.date == @sheetEnd
        end
      })
      arg(1, 'reporter', The ID of a defined resource. This identifies the status reporter. Unless thestatus entries provide a different author, the sheet author will be used asstatus entry author.
         )
    end

rule_statusSheetReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5601
    def rule_statusSheetReport
      pattern(%( !ssReportHeader !ssReportBody ), lambda {
        @property = nil
      })
      doc('statussheetreport', A status sheet report is a template for a status sheet. It collects all thestatus information of the top-level task that a resource is responsible for.This report is typically used by managers or team leads to review the timesheet status information and destill it down to a summary that can beforwarded to the next person in the reporting chain. The report will be forthe specified [trackingscenario].
         )
    end

rule_statusSheetTask() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5616
    def rule_statusSheetTask
      pattern(%( !statusSheetTaskHeader !statusSheetTaskBody), lambda {
        @property = @propertyStack.pop
      })
      doc('task.statussheet', Opens the task with the specified ID to add a status report. Child task can beopened inside this context by specifying their relative ID to this parent.
         )
    end

rule_statusSheetTaskAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5627
    def rule_statusSheetTaskAttributes
      optional
      repeatable
      pattern(%( !ssStatus ))
      pattern(%( !statusSheetTask ), lambda {
      })
    end

rule_statusSheetTaskBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5635
    def rule_statusSheetTaskBody
      optionsRule('statusSheetTaskAttributes')
    end

rule_statusSheetTaskHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5639
    def rule_statusSheetTaskHeader
      pattern(%( _task !taskId ), lambda {
        if @property
          @propertyStack.push(@property)
        else
          @propertyStack = []
        end
        @property = @val[1]
      })
    end

rule_subNodeId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5650
    def rule_subNodeId
      optional
      pattern(%( _: !idOrAbsoluteId ), lambda {
        @val[1]
      })
    end

rule_summary() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5657
    def rule_summary
      pattern(%( _summary $STRING ), lambda {
        return if @val[1].empty?

        if @val[1].length > 480
          error('ts_summary_too_long',
                "The summary text must be 480 characters long or shorter. " +
                "This text has #{@val[1].length} characters.",
                @sourceFileInfo[1])
        end
        if @val[1] == "A summary text\n"
            error('ts_default_summary',
                  "'A summary text' is not a valid summary",
                  @sourceFileInfo[1])
        end
        rtTokenSetIntro =
          [ :LINEBREAK, :SPACE, :WORD, :BOLD, :ITALIC, :CODE, :BOLDITALIC,
            :HREF, :HREFEND ]
        @journalEntry.summary = newRichText(@val[1], @sourceFileInfo[1],
                                            rtTokenSetIntro)
      })
      doc('summary', This is the introductory part of the journal or status entry. It shouldonly summarize the full entry but should contain more details than theheadline. The text including formatting characters must be 240 characters longor less.
         )
      arg(1, 'text', The text will be interpreted as [[Rich_Text_Attributes|Rich Text]]. Only asmall subset of the markup is supported for this attribute. You can use wordformatting, hyperlinks and paragraphs.
         )
    end

rule_supplement() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5693
    def rule_supplement
      pattern(%( !supplementAccount !accountBody ), lambda {
        @property = @idStack.pop
      })
      pattern(%( !supplementReport !reportBody ), lambda {
        @property = @idStack.pop
      })
      pattern(%( !supplementResource !resourceBody ), lambda {
        @property = @idStack.pop
      })
      pattern(%( !supplementTask !taskBody ), lambda {
        @property = @idStack.pop
      })
    end

rule_supplementAccount() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5708
    def rule_supplementAccount
      pattern(%( _account !accountId ), lambda {
        @idStack.push(@property)
        @property = @val[1]
      })
      arg(1, 'account ID', 'The ID of an already defined account.')
    end

rule_supplementReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5716
    def rule_supplementReport
      pattern(%( _report !reportId ), lambda {
        @idStack.push(@property)
        @property = @val[1]
      })
      arg(1, 'report ID', 'The absolute ID of an already defined report.')
    end

rule_supplementResource() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5724
    def rule_supplementResource
      pattern(%( _resource !resourceId ), lambda {
        @idStack.push(@property)
        @property = @val[1]
      })
      arg(1, 'resource ID', 'The ID of an already defined resource.')
    end

rule_supplementTask() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5732
    def rule_supplementTask
      pattern(%( _task !taskId ), lambda {
        @idStack.push(@property)
        @property = @val[1]
      })
      arg(1, 'task ID', 'The absolute ID of an already defined task.')
    end

rule_tagfile() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5740
    def rule_tagfile
      pattern(%( !tagfileHeader !tagfileBody ), lambda {
        @property = nil
      })
      doc('tagfile', The tagfile report generates a file that maps properties to source filelocations. This can be used by editors to quickly jump to a certain task orresource definition. Currently only the ctags format is supported that is usedby editors like [http://www.vim.org|vim].
         )
    end

rule_tagfileAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5774
    def rule_tagfileAttributes
      optional
      repeatable

      pattern(%( !hideresource ))
      pattern(%( !hidetask ))
      pattern(%( !rollupresource ))
      pattern(%( !rolluptask ))
    end

rule_tagfileBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5784
    def rule_tagfileBody
      optionsRule('tagfileAttributes')
    end

rule_tagfileHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5753
    def rule_tagfileHeader
      pattern(%( _tagfile !optionalID $STRING ), lambda {
        newReport(@val[1], @val[2], :tagfile, @sourceFileInfo[0]) do
          @property.set('formats', [ :ctags ])

          # Include all tasks.
          @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
          # Include all resources.
          @property.set('hideResource',
                        LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
        end
      })
      arg(2, 'file name', The name of the tagfile to generate. Use ''''tags'''' if you want vim andother tools to find it automatically.
         )
    end

rule_task() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5789
    def rule_task
      pattern(%( !taskHeader !taskBody ), lambda {
        @property = @property.parent
      })
      doc('task', Tasks are the central elements of a project plan. Use a task to specify thevarious steps and phases of the project. Depending on the attributes of thattask, a task can be a container task, a milestone or a regular leaf task. Thelatter may have resources assigned. By specifying dependencies the user canforce a certain sequence of tasks.Tasks have a local name space. All IDs must be unique within the tasksthat belong to the same enclosing task.
         )
    end

rule_taskAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5806
    def rule_taskAttributes
      repeatable
      optional

      pattern(%( _adopt !taskList ), lambda {
        @val[1].each do |task|
          @property.adopt(task)
        end
      })
      level(:experimental)
      doc('adopt.task', Add a previously defined task and its sub-tasks to this task. This can be usedto create virtual projects that contain task (sub-)trees that are originallydefined in another task context. Adopted tasks don't inherit anything fromtheir step parents. However, the adopting task is scheduled to fit all adoptedsub-tasks.A top-level task and all its sub-tasks must never contain the same task morethan once. All reports must use appropriate filters by setting [[taskroot]],[[hidetask]] or [[rolluptask]] to ensure that no tasks are contained more thanonce in the report.
         )

      pattern(%( !journalEntry ))

      pattern(%( _note $STRING ), lambda {
        @property.set('note', newRichText(@val[1], @sourceFileInfo[1]))
      })
      doc('note.task', Attach a note to the task. This is usually a more detailed specification ofwhat the task is about.
         )

      pattern(%( !purge ))

      pattern(%( _supplement !supplementTask !taskBody ), lambda {
        @property = @idStack.pop
      })
      doc('supplement.task', The supplement keyword provides a mechanism to add more attributes to alreadydefined tasks. The additional attributes must obey the same rules as inregular task definitions and must be enclosed by curly braces.This construct is primarily meant for situations where the information about atask is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool.
         )
      example('Supplement', 'task')

      pattern(%( !task ))
      pattern(%( !taskScenarioAttributes ))
      pattern(%( !scenarioIdCol !taskScenarioAttributes ), lambda {
        @scenarioIdx = 0
      })
      # Other attributes will be added automatically.
    end

rule_taskBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5866
    def rule_taskBody
      optionsRule('taskAttributes')
    end

rule_taskBooking() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5870
    def rule_taskBooking
      pattern(%( !taskBookingHeader !bookingBody ), lambda {
        unless @project.scenario(@scenarioIdx).get('ownbookings')
          error('no_own_task_booking',
                "The scenario #{@project.scenario(@scenarioIdx).fullId} " +
                'inherits its bookings from the tracking ' +
                'scenario. You cannot specificy additional bookings for it.')
        end
        @val[0].task.addBooking(@scenarioIdx, @val[0])
      })
    end

rule_taskBookingHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5882
    def rule_taskBookingHeader
      pattern(%( !resourceId !valIntervals ), lambda {
        checkBooking(@property, @val[0])
        @booking = Booking.new(@val[0], @property, @val[1])
        @booking.sourceFileInfo = @sourceFileInfo[0]
        @booking
      })
    end

rule_taskDep() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5891
    def rule_taskDep
      pattern(%( !taskDepHeader !taskDepBody ), lambda {
        @val[0]
      })
    end

rule_taskDepAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5897
    def rule_taskDepAttributes
      optional
      repeatable

      pattern(%( _gapduration !intervalDuration ), lambda {
        @taskDependency.gapDuration = @val[1]
      })
      doc('gapduration', Specifies the minimum required gap between the end of a preceding task and thestart of this task, or the start of a following task and the end of this task.This is calendar time, not working time. 7d means one week.
         )

      pattern(%( _gaplength !workingDuration ), lambda {
        @taskDependency.gapLength = @val[1]
      })
      doc('gaplength', Specifies the minimum required gap between the end of a preceding task and thestart of this task, or the start of a following task and the end of this task.This is working time, not calendar time. 7d means 7 working days, not oneweek. Whether a day is considered a working day or not depends on the definedworking hours and global leaves.
         )

      pattern(%( _onend ), lambda {
        @taskDependency.onEnd = true
      })
      doc('onend', The target of the dependency is the end of the task.
         )

      pattern(%( _onstart ), lambda {
        @taskDependency.onEnd = false
      })
      doc('onstart', The target of the dependency is the start of the task.
         )
    end

rule_taskDepBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5940
    def rule_taskDepBody
      optionsRule('taskDepAttributes')
    end

rule_taskDepHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5944
    def rule_taskDepHeader
      pattern(%( !taskDepId ), lambda {
        @taskDependency = TaskDependency.new(@val[0], true)
      })
    end

rule_taskDepId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5950
    def rule_taskDepId
      singlePattern('$ABSOLUTE_ID')
      arg(0, 'ABSOLUTE ID', A reference using the full qualified ID of a task. The IDs of all enclosingparent tasks must be prepended to the task ID and separated with a dot, e.g.''''proj.plan.doc''''.
           )

      singlePattern('$ID')
      arg(0, 'ID', 'Just the ID of the task without and parent IDs.')

      pattern(%( !relativeId ), lambda {
        task = @property
        id = @val[0]
        while task && id[0] == !!
          id = id.slice(1, id.length)
          task = task.parent
        end
        error('too_many_bangs',
              "Too many '!' for relative task in this context.",
              @sourceFileInfo[0], @property) if id[0] == !!
        if task
          task.fullId + '.' + id
        else
          id
        end
      })
      arg(0, 'RELATIVE ID', A relative task ID always starts with one or more exclamation marks and isfollowed by a task ID. Each exclamation mark lifts the scope where the ID islooked for to the enclosing task. The ID may contain some of the parent IDsseparated by dots, e. g. ''''!!plan.doc''''.
           )
    end

rule_taskDepList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5987
    def rule_taskDepList
      pattern(%( !taskDep !moreDepTasks ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_taskHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 5993
    def rule_taskHeader
      pattern(%( _task !optionalID $STRING ), lambda {
        if @property.nil? && !@taskprefix.empty?
          @property = @project.task(@taskprefix)
        end
        if @val[1]
          id = (@property ? @property.fullId + '.' : '') + @val[1]
          if @project.task(id)
            error('task_exists', "Task #{id} has already been defined.",
                  @sourceFileInfo[0])
          end
        end
        @property = Task.new(@project, @val[1], @val[2], @property)
        @property['projectid', 0] = @projectId
        @property.sourceFileInfo = @sourceFileInfo[0]
        @property.inheritAttributes
        @scenarioIdx = 0
      })
      arg(2, 'name', 'The name of the task')
    end

rule_taskId() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6014
    def rule_taskId
      pattern(%( !taskIdUnverifd ), lambda {
        id = @val[0]
        if @property && @property.is_a?(Task)
          # In case we have a nested supplement, we need to prepend the parent ID.
          id = @property.fullId + '.' + id
        else
          id = @taskprefix + '.' + id unless @taskprefix.empty?
        end
        if (task = @project.task(id)).nil?
          error('unknown_task', "Unknown task #{id}", @sourceFileInfo[0])
        end
        task
      })
    end

rule_taskIdUnverifd() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6030
    def rule_taskIdUnverifd
      singlePattern('$ABSOLUTE_ID')
      singlePattern('$ID')
    end

rule_taskList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6035
    def rule_taskList
      listRule('moreTasks', '!absoluteTaskId')
    end

rule_taskPeriod() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6039
    def rule_taskPeriod
      pattern(%( _period !valInterval), lambda {
        @property['start', @scenarioIdx] = @val[1].start
        @property['end', @scenarioIdx] = @val[1].end
      })
      doc('period.task', This property is a shortcut for setting the start and end property at the sametime. In contrast to using these, it does not change the scheduling direction.
         )
    end

rule_taskPred() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6051
    def rule_taskPred
      pattern(%( !taskPredHeader !taskDepBody ), lambda {
        @val[0]
      })
    end

rule_taskPredHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6057
    def rule_taskPredHeader
      pattern(%( !taskDepId ), lambda {
        @taskDependency = TaskDependency.new(@val[0], false)
      })
    end

rule_taskPredList() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6063
    def rule_taskPredList
      pattern(%( !taskPred !morePredTasks ), lambda {
        [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
      })
    end

rule_taskReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6069
    def rule_taskReport
      pattern(%( !taskReportHeader !reportBody ), lambda {
        @property = @property.parent
      })
      doc('taskreport', The report lists tasks and their respective values in a table. To reduce thelist of included tasks, you can use the [[hidetask]], [[rolluptask]] or[[taskroot]] attributes. The order of the task can be controlled with[[sorttasks]]. If the first sorting criteria is tree sorting, the parent taskswill always be included to form the tree. Tree sorting is the default. Youneed to change it if you do not want certain parent tasks to be included inthe report.By default, all the resources that are allocated to each task are hidden, butthey can be listed as well. Use the [[hideresource]] attribute to select whichresources should be included.
         )
      example('HtmlTaskReport')
    end

rule_taskReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6090
    def rule_taskReportHeader
      pattern(%( _taskreport !optionalID !reportName ), lambda {
        newReport(@val[1], @val[2], :taskreport, @sourceFileInfo[0]) do
          unless @property.modified?('columns')
            # Set the default columns for this report.
            %( bsi name start end effort chart ).each do |col|
              @property.get('columns') <<
              TableColumnDefinition.new(col, columnTitle(col))
            end
          end
          # Show all tasks, sorted by tree, start-up, seqno-up.
          unless @property.modified?('hideTask')
            @property.set('hideTask',
                          LogicalExpression.new(LogicalOperation.new(0)))
          end
          unless @property.modified?('sortTasks')
            @property.set('sortTasks',
                          [ [ 'tree', true, -1 ],
                            [ 'start', true, 0 ],
                            [ 'seqno', true, -1 ] ])
          end
          # Show no resources, but set sorting to id-up.
          unless @property.modified?('hideResource')
            @property.set('hideResource',
                          LogicalExpression.new(LogicalOperation.new(1)))
          end
          unless @property.modified?('sortResources')
            @property.set('sortResources', [ [ 'id', true, -1 ] ])
          end
        end
      })
    end

rule_taskScenarioAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6123
    def rule_taskScenarioAttributes

      pattern(%( _account $ID ))
      level(:removed)
      also('chargeset')
      doc('account.task', '')

      pattern(%( !allocate ))

      pattern(%( _booking !taskBooking ))
      doc('booking.task', The booking attribute can be used to report actually completed work.  A taskwith bookings must be [[scheduling|scheduled]] in ''''asap'''' mode.  If thescenario is not the [[trackingscenario|tracking scenario]] or derived from it,the scheduler will not allocate resources prior to the current date or thedate specified with [[now]] when a task has at least one booking.Bookings are only valid in the scenario they have been defined in. They willin general not be passed to any other scenario. If you have defined a[[trackingscenario|tracking scenario]], the bookings of this scenario will bepassed to all the derived scenarios of the tracking scenario.The sloppy attribute can be used when you want to skip non-working time orother allocations automatically. If it's not given, all bookings must onlycover working time for the resource.The booking attributes is designed to capture the exact amount of completedwork. This attribute is not really intended to specify completed effort byhand. Usually, booking statements are generated by [[export]] reports. The[[sloppy.booking|sloppy]] and [[overtime.booking|overtime]] attributes areonly kludge for users who want to write them manually.Bookings can be used to report already completed work by specifying the exacttime intervals a certain resource has worked on this task.Bookings can be defined in the task or resource context. If you move tasksaround very often, put your bookings in the task context.
         )
      also(%( booking.resource ))
      example('Booking')

      pattern(%( _charge !number !chargeMode ), lambda {
        checkContainer('charge')

        if @property['chargeset', @scenarioIdx].empty?
          error('task_without_chargeset',
                'The task does not have a chargeset defined.',
                @sourceFileInfo[0], @property)
        end
        case @val[2]
        when 'onstart'
          mode = :onStart
          amount = @val[1]
        when 'onend'
          mode = :onEnd
          amount = @val[1]
        when 'perhour'
          mode = :perDiem
          amount = @val[1] * 24
        when 'perday'
          mode = :perDiem
          amount = @val[1]
        when 'perweek'
          mode = :perDiem
          amount = @val[1] / 7.0
        end
        @property['charge', @scenarioIdx] +=
          [ Charge.new(amount, mode, @property, @scenarioIdx) ]
      })
      doc('charge', Specify a one-time or per-period charge to a certain account. The charge canoccur at the start of the task, at the end of it, or continuously over theduration of the task. The accounts to be charged are determined by the[[chargeset]] setting of the task.
         )
      arg(1, 'amount', 'The amount to charge')

      pattern(%( !chargeset ))

      pattern(%( _complete !number), lambda {
        if @val[1] < 0.0 || @val[1] > 100.0
          error('task_complete', "Complete value must be between 0 and 100",
                @sourceFileInfo[1], @property)
        end
        @property['complete', @scenarioIdx] = @val[1]
      })
      doc('complete', Specifies what percentage of the task is already completed. This can be usefulfor simple progress tracking like in a TODO list. The provided completiondegree is used for the ''''complete'''' and ''''gauge'''' columns in reports.Reports with calendar elements may show the completed part of the task in adifferent color.The completion percentage has no impact on the scheduler. It's meant fordocumentation purposes only.
          )
      example('Complete', '1')

      arg(1, 'percent', 'The percent value. It must be between 0 and 100.')

      pattern(%( _depends !taskDepList ), lambda {
        checkContainer('depends')
        @property['depends', @scenarioIdx] += @val[1]
        begin
          @property['forward', @scenarioIdx] = true
        rescue AttributeOverwrite
        end
      })
      doc('depends', Specifies that the task cannot start before the specified tasks have beenfinished.By using the 'depends' attribute, the scheduling policy is automatically setto asap. If both depends and precedes are used, the last policy counts.
          )
      example('Depends1')
      pattern(%( _duration !calendarDuration ), lambda {
        setDurationAttribute('duration', @val[1])
      })
      doc('duration', Specifies the time the task should last. This is calendar time, not workingtime. 7d means one week. If resources are specified they are allocated whenavailable. Availability of resources has no impact on the duration of thetask. It will always be the specified duration.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[effort]] and [[length]] attributes.
         )
      example('Durations')
      also(%( effort length ))

      pattern(%( _effort !workingDuration ), lambda {
        if @val[1] <= 0
          error('effort_zero', "Effort value must at least as large as the " +
                               "timing resolution " +
                               "(#{@project['scheduleGranularity'] / 60}min).",
                @sourceFileInfo[1], @property)
        end
        setDurationAttribute('effort', @val[1])
      })
      doc('effort', Specifies the effort needed to complete the task. An effort of ''''6d'''' (6resource-days) can be done with 2 full-time resources in 3 working days. Thetask will not finish before the allocated resources have contributed thespecified effort. Hence the duration of the task will depend on theavailability of the allocated resources. The specified effort value must be atleast as large as the [[timingresolution]].WARNING: In almost all real world projects effort is not the product of timeand resources. This is only true if the task can be partitioned without addingany overhead. For more information about this read ''The Mythical Man-Month'' byFrederick P. Brooks, Jr.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[duration]] and [[length]] attributes. A task with an effortvalue cannot be a [[milestone]].
         )
      example('Durations')
      also(%( duration length ))

      pattern(%( _end !valDate ), lambda {
        @property['end', @scenarioIdx] = @val[1]
        begin
          @property['forward', @scenarioIdx] = false
        rescue AttributeOverwrite
        end
      })
      doc('end', The end attribute provides a guideline to the scheduler when the task shouldend. It will never end later, but it may end earlier when allocatedresources are not available that long. When an end date is provided for acontainer task, it will be passed down to ALAP task that don't have a welldefined end criteria.Setting an end date will implicitely set the scheduling policy for this taskto ALAP.
         )
      example('Export', '1')
      pattern(%( _endcredit !number ), lambda {
        @property['charge', @scenarioIdx] =
          @property['charge', @scenarioIdx] +
          [ Charge.new(@val[1], :onEnd, @property, @scenarioIdx) ]
      })
      level(:deprecated)
      doc('endcredit', Specifies an amount that is credited to the accounts specified by the[[chargeset]] attributes at the moment the tasks ends.
         )
      also('charge')
      example('Account', '1')
      pattern(%( !flags ))
      doc('flags.task', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
         )

      pattern(%( !fail ))

      pattern(%( _length !workingDuration ), lambda {
        setDurationAttribute('length', @val[1])
      })
      doc('length', Specifies the duration of this task as working time, not calendar time. 7dmeans 7 working days, or 7 times 8 hours (assuming default settings), not oneweek.A task with a length specification may have resource allocations. Resourcesare allocated when they are available.  There is no guarantee that the taskwill get any resources allocated.  The availability of resources has no impacton the duration of the task. A time slot where none of the specified resourcesis available is still considered working time, if there is no global vacationand global working hours are defined accordingly.For the length calculation, the global working hours and the global leavesmatter unless the task has [[shifts.task|shifts]] assigned. In the latter casethe working hours and leaves of the shift apply for the specified period todetermine if a slot is working time or not. If a resource has additinalworking hours defined, it's quite possible that a task with a length of 5dwill have an allocated effort larger than 40 hours.  Resource working hoursonly have an impact on whether an allocation is made or not for a particulartime slot. They don't effect the resulting duration of the task.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[duration]], [[effort]] and [[milestone]] attributes.
         )
      also(%( duration effort ))

      pattern(%( !limits ), lambda {
        checkContainer('limits')
        @property['limits', @scenarioIdx] = @val[0]
      })
      doc('limits.task', Set per-interval allocation limits for the task. This setting affects all allocations for this task.
         )
      example('Limits-1', '2')

      pattern(%( _maxend !valDate ), lambda {
        @property['maxend', @scenarioIdx] = @val[1]
      })
      doc('maxend', Specifies the maximum wanted end time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If theend of the task is later than the specified value, then an error is reported.
         )

      pattern(%( _maxstart !valDate ), lambda {
        @property['maxstart', @scenarioIdx] = @val[1]
      })
      doc('maxstart', Specifies the maximum wanted start time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If thestart of the task is later than the specified value, then an error isreported.
         )

      pattern(%( _milestone ), lambda {
        setDurationAttribute('milestone')
      })
      doc('milestone', Turns the task into a special task that has no duration. You may not specify aduration, length, effort or subtasks for a milestone task.A task that only has a start or an end specification and no durationspecification, inherited start or end dates, no dependencies or sub tasks,will be recognized as milestone automatically.
         )

      pattern(%( _minend !valDate ), lambda {
        @property['minend', @scenarioIdx] = @val[1]
      })
      doc('minend', Specifies the minimum wanted end time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If theend of the task is earlier than the specified value, then an error isreported.
         )

      pattern(%( _minstart !valDate ), lambda {
        @property['minstart', @scenarioIdx] = @val[1]
      })
      doc('minstart', Specifies the minimum wanted start time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If thestart of the task is earlier than the specified value, then an error isreported.
         )

      pattern(%( _startcredit !number ), lambda {
        @property['charge', @scenarioIdx] +=
          [ Charge.new(@val[1], :onStart, @property, @scenarioIdx) ]
      })
      level(:deprecated)
      doc('startcredit', Specifies an amount that is credited to the account specified by the[[chargeset]] attributes at the moment the tasks starts.
         )
      also('charge')
      pattern(%( !taskPeriod ))

      pattern(%( _precedes !taskPredList ), lambda {
        checkContainer('precedes')
          @property['precedes', @scenarioIdx] += @val[1]
        begin
          @property['forward', @scenarioIdx] = false
        rescue AttributeOverwrite
        end
      })
      doc('precedes', Specifies that the tasks with the specified IDs cannot start before the taskhas been finished. If multiple IDs are specified, they must be separated bycommas. IDs must be either global or relative. A relative ID starts with anumber of '!'. Each '!' moves the scope to the parent task. Global IDs do notcontain '!', but have IDs separated by dots.By using the 'precedes' attribute, the scheduling policy is automatically setto alap. If both depends and precedes are used within a task, the last policycounts.
         )

      pattern(%( _priority $INTEGER ), lambda {
        if @val[1] < 0 || @val[1] > 1000
          error('task_priority', "Priority must have a value between 0 and 1000",
                @sourceFileInfo[1], @property)
        end
        @property['priority', @scenarioIdx] = @val[1]
      })
      doc('priority', Specifies the priority of the task. A task with higher priority is morelikely to get the requested resources. The default priority value of all tasksis 500. Don't confuse the priority of a tasks with the importance or urgencyof a task. It only increases the chances that the tasks gets the requestedresources. It does not mean that the task happens earlier, though that isusually the effect you will see. It also does not have any effect on tasksthat don't have any resources assigned (e.g. milestones).For milestones it will raise or lower the chances that task leading up themilestone will get their resources over task with equal priority that competefor the same resources.This attribute is inherited by subtasks if specified prior to the definitionof the subtask.
         )
      arg(1, 'value', 'Priority value (1 - 1000)')
      example('Priority')

      pattern(%( _projectid $ID ), lambda {
        unless @project['projectids'].include?(@val[1])
          error('unknown_projectid', "Unknown project ID #{@val[1]}",
                @sourceFileInfo[1])
        end
        begin
          @property['projectid', @scenarioIdx] = @val[1]
        rescue AttributeOverwrite
          # This attribute always overwrites the implicitely provided ID.
        end
      })
      doc('projectid.task', In larger projects it may be desireable to work with different project IDs forparts of the project. This attribute assignes a new project ID to this task anall subsequently defined sub tasks. The project ID needs to be declared first using [[projectid]] or [[projectids]].
         )

      pattern(%( _responsible !resourceList ), lambda {
        @property['responsible', @scenarioIdx] += @val[1]
        @property['responsible', @scenarioIdx].uniq!
      })
      doc('responsible', The ID of the resource that is responsible for this task. This value is fordocumentation purposes only. It's not used by the scheduler.
         )

      pattern(%( _scheduled ), lambda {
        if (@property['milestone', @scenarioIdx] &&
            @property['start', @scenarioIdx].nil? &&
            @property['end', @scenarioIdx].nil?) ||
           (!@property['milestone', @scenarioIdx] &&
            (@property['start', @scenarioIdx].nil? ||
             @property['end', @scenarioIdx].nil?))
          error('not_scheduled',
                "Task #{@property.fullId} is marked as scheduled but does not " +
                'have a fixed start and end date.',
                @sourceFileInfo[0], @property)
        end
        @property['scheduled', @scenarioIdx] = true
      })
      doc('scheduled', This is mostly for internal use. It specifies that the task should be ignoredfor scheduling in the scenario. This option only makes sense if you provideall resource [[booking.resource|bookings]] manually. Without bookingstatements, the task will be reported with 0 effort and no resources assigned.
         )

      pattern(%( _scheduling !schedulingDirection ), lambda {
        if @val[1] == 'alap'
          begin
            @property['forward', @scenarioIdx] = false
          rescue AttributeOverwrite
          end
        elsif @val[1] == 'asap'
          begin
            @property['forward', @scenarioIdx] = true
          rescue AttributeOverwrite
          end
        end
      })
      doc('scheduling', Specifies the scheduling policy for the task. A task can be scheduled fromstart to end (As Soon As Possible, asap) or from end to start (As Late AsPossible, alap).A task can be scheduled from start to end (ASAP mode) when it has a hard(start) or soft (depends) criteria for the start time. A task can be scheduledfrom end to start (ALAP mode) when it has a hard (end) or soft (precedes)criteria for the end time.Some task attributes set the scheduling policy implicitly. This attribute canbe used to explicitly set the scheduling policy of the task to a certaindirection. To avoid it being overwritten again by an implicit attribute thisattribute should always be the last attribute of the task.A random mixture of ASAP and ALAP tasks can have unexpected side effects onthe scheduling of the project. It increases significantly the schedulingcomplexity and results in much longer scheduling times. Especially in projectswith many hundreds of tasks the scheduling time of a project with a mixture ofASAP and ALAP times can be 2 to 10 times longer. When the projects containschains of ALAP and ASAP tasks the tasks further down the dependency chain willbe served much later than other non-chained task even when they have a muchhigher priority. This can result in situations where high priority tasks donot get their resources even though the parallel competing tasks have a muchlower priority.ALAP tasks may not have [[booking.task|bookings]] since the first booked slotdetermines the start date of the task and prevents it from being scheduledfrom end to start.As a general rule, try to avoid ALAP tasks whenever possible. Have a closeeye on tasks that have been switched implicitly to ALAP mode because theend attribute comes after the start attribute.
         )

      pattern(%( !taskShiftAssignments !shiftAssignments ), lambda {
        checkContainer('shift')
        # Set same value again to set the 'provided' state for the attribute.
        begin
          @property['shifts', @scenarioIdx] = @shiftAssignments
        rescue AttributeOverwrite
          # Multiple shift assignments are a common idiom, so don't warn about
          # them.
        end
        @shiftAssignments = nil
      })
      level(:deprecated)
      doc('shift.task', This keyword has been deprecated. Please use [[shifts.task|shifts(task)]] instead.
         )
      also('shifts.task')

      pattern(%( !taskShiftsAssignments !shiftAssignments ), lambda {
        checkContainer('shifts')
        begin
          @property['shifts', @scenarioIdx] = @shiftAssignments
        rescue AttributeOverwrite
          # Multiple shift assignments are a common idiom, so don't warn about
          # them.
        end
        @shiftAssignments = nil
      })
      doc('shifts.task', Limits the working time for this task during the during the specified intervalto the working hours of the given shift. Multiple shifts can be defined, butshift intervals may not overlap. This is an additional working timerestriction ontop of the working hours of the allocated resources. It does notreplace the resource working hour restrictions. For a resource to be assignedto a time slot, both the respective task shift as well as the resource workinghours must declare the time slot as duty slot.
          )

      pattern(%( _start !valDate), lambda {
        @property['start', @scenarioIdx] = @val[1]
        begin
          @property['forward', @scenarioIdx] = true
        rescue AttributeOverwrite
        end
      })
      doc('start', The start attribute provides a guideline to the scheduler when the task shouldstart. It will never start earlier, but it may start later when allocatedresources are not available immediately. When a start date is provided for acontainer task, it will be passed down to ASAP task that don't have a welldefined start criteria.Setting a start date will implicitely set the scheduling policy for this taskto ASAP.
         )
      also(%( end period.task maxstart minstart scheduling ))

      pattern(%( !warn ))

      # Other attributes will be added automatically.
    end

rule_taskShiftAssignments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6650
    def rule_taskShiftAssignments
      pattern(%( _shift ), lambda {
        @shiftAssignments = @property['shifts', @scenarioIdx]
      })
    end

rule_taskShiftsAssignments() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6656
    def rule_taskShiftsAssignments
      pattern(%( _shifts ), lambda {
        @shiftAssignments = @property['shifts', @scenarioIdx]
      })
    end

rule_textReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6662
    def rule_textReport
      pattern(%( !textReportHeader !reportBody ), lambda {
        @property = @property.parent
      })
      doc('textreport', This report consists of 5 RichText sections, a header, a center section with aleft and right margin and a footer. The sections may contain the output ofother defined reports.
         )
      example('textreport')
    end

rule_textReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6675
    def rule_textReportHeader
      pattern(%( _textreport !optionalID !reportName ), lambda {
        newReport(@val[1], @val[2], :textreport, @sourceFileInfo[0])
      })
    end

rule_timeInterval() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6823
    def rule_timeInterval
      pattern([ '$TIME', '_-', '$TIME' ], lambda {
        if @val[0] >= @val[2]
          error('time_interval',
                "End time of interval must be larger than start time",
                @sourceFileInfo[0])
        end
        [ @val[0], @val[2] ]
      })
    end

rule_timeSheet() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6834
    def rule_timeSheet
      pattern(%( !timeSheetHeader !timeSheetBody ), lambda {
        @timeSheet
      })
      doc('timesheet', A time sheet record can be used to capture the current status of the tasksassigned to a specific resource and the achieved progress for a given periodof time. The status is assumed to be for the end of this time period. Theremust be a separate time sheet record for each resource per period. Differentresources can use different reporting periods and reports for the sameresource may have different reporting periods as long as they don't overlap.For the time after the last time sheet, TaskJuggler will project the resultbased on the plan data. For periods without a time sheet record prior to thelast record for this resource, TaskJuggler assumes that no work has been done.The work is booked for the scenario specified by [[trackingscenario]].The intended use for time sheets is to have all resources report a time sheetevery day, week or month. All time sheets can be added to the project plan.The status information is always used to determin the current status of theproject. The [[work]], [[remaining]] and [[end.timesheet|end]] attributes areignored if there are also [[booking.task|bookings]] for the resource in thetime sheet period. The non-ignored attributes of the time sheets will beconverted into [[booking.task|booking]] statements internally. These bookingscan then be [[export|exported]] into a file which can then be added to theproject again. This way, you can use time sheets to incrementally recordprogress of your project. There is a possibility that time sheets conflictwith other data in the plan. In case TaskJuggler cannot automatically resolvethem, these conflicts have to be manually resolved by either changing the planor the time sheet.The status messages are interpreted as [[journalentry|journal entries]]. Thealert level will be evaluated and the current state of the project can be putinto a dashboard using the ''''alert'''' and ''''alertmessage'''' [[columnid|columns]].Currently, the provided effort values and dates are not yet used toautomatically update the plan data. This feature will be added in futureversions.
         )
      example('TimeSheet1', '1')
    end

rule_timeSheetAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6877
    def rule_timeSheetAttributes
      optional
      repeatable

      pattern(%( !tsNewTaskHeader !tsTaskBody ), lambda {
        @property = nil
        @timeSheetRecord = nil
      })
      doc('newtask', The keyword can be used to request a new task to the project. If the task IDrequires further parent task that don't exist yet, these tasks will berequested as well. If the task exists already, an error will be generated. Thenewly requested task can be used immediately to report progress and statusagainst it. These tasks will not automatically be added to the project plan.The project manager has to manually create them after reviewing the requestduring the time sheet reviews.
         )
      example('TimeSheet1', '3')

      pattern(%( _shift !shiftId ), lambda {
        #TODO
      })
      doc('shift.timesheet', Specifies an alternative [[shift]] for the time sheet period. This shift willoverride any existing working hour definitions for the resource. It will notoverride already declared [[leaves]] though.The primary use of this feature is to let the resources report different totalwork time for the report period.
         )

      pattern(%( !tsStatus ))

      pattern(%( !tsTaskHeader !tsTaskBody ), lambda {
        @property = nil
        @timeSheetRecord = nil
      })
      doc('task.timesheet', Specifies an existing task that progress and status should be reportedagainst.
         )
      example('TimeSheet1', '4')
    end

rule_timeSheetBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6931
    def rule_timeSheetBody
      pattern(%( _{ !timeSheetAttributes _} ), lambda {

      })
    end

rule_timeSheetFile() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6924
    def rule_timeSheetFile
      pattern(%( !timeSheet . ), lambda {
        @val[0]
      })
      lastSyntaxToken(1)
    end

rule_timeSheetHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6937
    def rule_timeSheetHeader
      pattern(%( _timesheet !resourceId !valIntervalOrDate ), lambda {
        @sheetAuthor = @val[1]
        @property = nil
        unless @sheetAuthor.leaf?
          error('ts_group_author',
                'A resource group cannot file a time sheet',
                @sourceFileInfo[1])
        end
        unless (scenarioIdx = @project['trackingScenarioIdx'])
          error('ts_no_tracking_scenario',
                'No trackingscenario defined.')
        end
        # Currently time sheets are hardcoded for scenario 0.
        @timeSheet = TimeSheet.new(@sheetAuthor, @val[2], scenarioIdx)
        @timeSheet.sourceFileInfo = @sourceFileInfo[0]
        @project.timeSheets << @timeSheet
      })
    end

rule_timeSheetReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6957
    def rule_timeSheetReport
      pattern(%( !tsReportHeader !tsReportBody ), lambda {
        @property = nil
      })
      doc('timesheetreport', For projects that flow mostly according to plan, TaskJuggler already knowsmuch of the information that should be contained in the time sheets. With thisproperty, you can generate a report that contains drafts of the time sheetsfor one or more resources. The time sheet drafts will be for thespecified report period and the specified [trackingscenario].
         )
    end

rule_timeformat() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6681
    def rule_timeformat
      pattern(%( _timeformat $STRING ), lambda {
        @val[1]
      })
      doc('timeformat', Determines how time specifications in reports look like.
         )
      arg(1, 'format', Ordinary characters placed in the format string are copied withoutconversion. Conversion specifiers are introduced by a `%' character, and arereplaced in s as follows:* ''''%a''''  The abbreviated weekday name according to the current locale.* ''''%A''''  The full weekday name according to the current locale.* ''''%b''''  The abbreviated month name according to the current locale.* ''''%B''''  The full month name according to the current locale.* ''''%c''''  The preferred date and time representation for the current locale.* ''''%C''''  The century number (year/100) as a 2-digit integer. (SU)* ''''%d''''  The day of the month as a decimal number (range 01 to 31).* ''''%e''''  Like ''''%d'''', the day of the month as a decimal number, but aleading zero is replaced by a space. (SU)* ''''%E''''  Modifier: use alternative format, see below. (SU)* ''''%F''''  Equivalent to ''''%Y-%m-%d'''' (the ISO 8601 date format). (C99)* ''''%G''''  The ISO 8601 year with century as a decimal number. The 4-digityear corresponding to the ISO week number (see %V). This has the same formatand value as ''''%y'''', except that if the ISO week number belongs to theprevious or next year, that year is used instead. (TZ)* ''''%g''''  Like %G, but without century, i.e., with a 2-digit year (00-99).(TZ)* ''''%h''''  Equivalent to ''''%b''''. (SU)* ''''%H''''  The hour as a decimal number using a 24-hour clock (range 00 to23).* ''''%I''''  The hour as a decimal number using a 12-hour clock (range 01 to12).* ''''%j''''  The day of the year as a decimal number (range 001 to 366).* ''''%k''''  The hour (24-hour clock) as a decimal number (range 0 to 23);single digits are preceded by a blank. (See also ''''%H''''.) (TZ)* ''''%l''''  The hour (12-hour clock) as a decimal number (range 1 to 12);single digits are preceded by a blank. (See also ''''%I''''.) (TZ)* ''''%m''''  The month as a decimal number (range 01 to 12).* ''''%M''''  The minute as a decimal number (range 00 to 59).* ''''%n''''  A newline character. (SU)* ''''%O''''  Modifier: use alternative format, see below. (SU)* ''''%p''''  Either 'AM' or 'PM' according to the given time value, or thecorresponding strings for the current locale. Noon is treated as `pm' andmidnight as 'am'.* ''''%P''''  Like %p but in lowercase: 'am' or 'pm' or ''''%a''''corresponding string for the current locale. (GNU)* ''''%r''''  The time in a.m. or p.m. notation. In the POSIX locale this isequivalent to ''''%I:%M:%S %p''''. (SU)* ''''%R''''  The time in 24-hour notation (%H:%M). (SU) For a versionincluding the seconds, see ''''%T'''' below.* ''''%s''''  The number of seconds since the Epoch, i.e., since 1970-01-0100:00:00 UTC.  (TZ)* ''''%S''''  The second as a decimal number (range 00 to 61).* ''''%t''''  A tab character. (SU)* ''''%T''''  The time in 24-hour notation (%H:%M:%S). (SU)* ''''%u''''  The day of the week as a decimal, range 1 to 7, Monday being 1.See also ''''%w''''. (SU)* ''''%U''''  The week number of the current year as a decimal number, range00 to 53, starting with the first Sunday as the first day of week 01. See also''''%V'''' and ''''%W''''.* ''''%V''''  The ISO 8601:1988 week number of the current year as a decimalnumber, range 01 to 53, where week 1 is the first week that has at least 4days in the current year, and with Monday as the first day of the week. Seealso ''''%U'''' and ''''%W''''. %(SU)* ''''%w''''  The day of the week as a decimal, range 0 to 6, Sunday being 0. See also ''''%u''''.* ''''%W''''  The week number of the current %year as a decimal number, range00 to 53, starting with the first Monday as the first day of week 01.* ''''%x''''  The preferred date representation for the current locale withoutthe time.* ''''%X''''  The preferred time representation for the current locale withoutthe date.* ''''%y''''  The year as a decimal number without a century (range 00 to 99).* ''''%Y''''   The year as a decimal number including the century.* ''''%z''''   The time zone as hour offset from GMT. Required to emitRFC822-conformant dates (using ''''%a, %d %%b %Y %H:%M:%S %%z''''). (GNU)* ''''%Z''''  The time zone or name or abbreviation.* ''''%+''''  The date and time in date(1) format. (TZ)* ''''%%''''  A literal ''''%'''' character.Some conversion specifiers can be modified by preceding them by the E or Omodifier to indicate that an alternative format should be used. If thealternative format or specification does not exist for the current locale, thebehavior will be as if the unmodified conversion specification were used.(SU) The Single Unix Specification mentions %Ec, %EC, %Ex, %%EX, %Ry, %EY,%Od, %Oe, %OH, %OI, %Om, %OM, %OS, %Ou, %OU, %OV, %Ow, %OW, %Oy, where theeffect of the O modifier is to use alternative numeric symbols (say, Romannumerals), and that of the E modifier is to use a locale-dependent alternativerepresentation.This documentation of the timeformat attribute has been taken from the man pageof the GNU strftime function.
         )

    end

rule_timezone() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 6971
    def rule_timezone
      pattern(%( _timezone !validTimeZone ), lambda{
        TjTime.setTimeZone(@val[1])
        @project['timezone'] = @val[1]
      })
      doc('timezone', Sets the default time zone of the project. All dates and times that have notime zones specified will be assumed to be in this time zone. If no time zoneis specified for the project, UTC is assumed.The project start and end time are not affected by this setting. They arealways considered to be UTC unless specified differently.In case the specified time zone is not hour-aligned with UTC, the[[timingresolution]] will automatically be decreased accordingly. Do notchange the timingresolution after you've set the time zone!Changing the time zone will reset the [[workinghours.project|working hours]]to the default times. It's recommended that you declare your working hoursafter the time zone.
          )
      arg(1, 'zone', Time zone to use. E. g. 'Europe/Berlin' or 'America/Denver'. Don't use the 3letter acronyms. See[http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones Wikipedia] forpossible values.
         )
    end

rule_traceReport() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7002
    def rule_traceReport
      pattern(%( !traceReportHeader !reportBody ), lambda {
        @property = @property.parent
      })
      doc('tracereport', The trace report works noticeably different than all other TaskJugglerreports. It uses a CSV file to track the values of the selected attributes.Each time ''''tj3'''' is run with the ''''--add-trace'''' option, a new set ofvalues is appended to the CSV file. The first column of the CSV file holds thedate when the snapshot was taken. This is either the current date or the''''now'''' date if provided. There is no need to specify CSV as output formatfor the report. You can either use these tracked values directly by specifying other report formats or by importing the CSV file into another program.The first column always contains the current date when thattable row was added. All subsequent columns can be defined by the user withthe [[columns]] attribute. This column set is then repeated for all propertiesthat are not hidden by [[hideaccount]], [[hideresource]] and [[hidetask]]. Bydefault, all properties are excluded. You must provide at least one of the''''hide...'''' attributes to select the properties you want to have includedin the report. Please be aware that total number of columns is the product ofattributes defined with [[columns]] times the number of included properties.Select you values carefully or you will end up with very large reports.The column headers can be customized by using the [[title.column|title]]attribute.  When you include multiple properties, these headers are not uniqueunless you include mini-queries to modify them based on the property theycolum is represeting.  You can use the queries''''<nowiki><-id-></nowiki>'''', ''''<nowiki><-name-></nowiki>'''',''''<nowiki><-scenario-></nowiki>'''' and''''<nowiki><-attribute-></nowiki>''''. ''''<nowiki><-id-></nowiki>'''' isreplaced with the ID of the property, ''''<nowiki><-name-></nowiki>'''' withthe name and so on.You can change the set of tracked values over time. Old values will bepreserved and the corresponding columns will be the last ones in the CSV file.When other formats are requested, the CSV file is read in and a report thatshows the tracked values over time will be generated. The CSV file may containall kinds of values that are being tracked. Report formats that don't supporta mix of different values will just show the values of the second column.The HTML version generates SVG graphs that are embedded in the HTML page.These graphs are only visble if the web browser supports HTML5. This is truefor the latest generation of browsers, but older browsers may not support thisformat.
         )
      example('TraceReport')
    end

rule_traceReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7052
    def rule_traceReportHeader
      pattern(%( _tracereport !optionalID !reportName ), lambda {
        newReport(@val[1], @val[2], :tracereport, @sourceFileInfo[0]) do
          # The top-level always inherits the global timeFormat setting. This is
          # not desireable in this case, so we ignore this.
          if (@property.level == 0 && !@property.provided('timeFormat')) ||
             (@property.level > 0 && !@property.modified?('timeFormat'))
            # CSV readers such of Libre-/OpenOffice can't deal with time zones. We
            # probably also don't need seconds.
            @property.set('timeFormat', '%Y-%m-%d-%H:%M')
          end
          unless @property.modified?('columns')
            # Set the default columns for this report.
            %( end ).each do |col|
              @property.get('columns') <<
              TableColumnDefinition.new(col, columnTitle(col))
            end
          end
          # Hide all accounts.
          unless @property.modified?('hideAccount')
            @property.set('hideAccount',
                          LogicalExpression.new(LogicalOperation.new(1)))
          end
          unless @property.modified?('sortAccounts')
            @property.set('sortAccounts',
                          [ [ 'tree', true, -1 ],
                            [ 'seqno', true, -1 ] ])
          end
          # Show all tasks, sorted by tree, start-up, seqno-up.
          unless @property.modified?('hideTask')
            @property.set('hideTask',
                          LogicalExpression.new(LogicalOperation.new(0)))
          end
          unless @property.modified?('sortTasks')
            @property.set('sortTasks',
                          [ [ 'tree', true, -1 ],
                            [ 'start', true, 0 ],
                            [ 'seqno', true, -1 ] ])
          end
          # Show no resources, but set sorting to id-up.
          unless @property.modified?('hideResource')
            @property.set('hideResource',
                          LogicalExpression.new(LogicalOperation.new(1)))
          end
          unless @property.modified?('sortResources')
            @property.set('sortResources', [ [ 'id', true, -1 ] ])
          end
        end
      })
    end

rule_tsNewTaskHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7103
    def rule_tsNewTaskHeader
      pattern(%( _newtask !taskIdUnverifd $STRING ), lambda {
        @timeSheetRecord = TimeSheetRecord.new(@timeSheet, @val[1])
        @timeSheetRecord.name = @val[2]
        @timeSheetRecord.sourceFileInfo = @sourceFileInfo[0]
      })
      arg(1, 'task', 'ID of the new task')
    end

rule_tsReportAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7139
    def rule_tsReportAttributes
      optional
      repeatable

      pattern(%( !hideresource ))
      pattern(%( !hidetask ))
      pattern(%( !reportEnd ))
      pattern(%( !reportPeriod ))
      pattern(%( !reportStart ))
      pattern(%( !sortResources ))
      pattern(%( !sortTasks ))
    end

rule_tsReportBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7152
    def rule_tsReportBody
      optionsRule('tsReportAttributes')
    end

rule_tsReportHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7111
    def rule_tsReportHeader
      pattern(%( _timesheetreport !optionalID $STRING ), lambda {
        newReport(@val[1], @val[2], :timeSheet, @sourceFileInfo[0]) do
          @property.set('formats', [ :tjp ])

          unless (scenarioIdx = @project['trackingScenarioIdx'])
            error('ts_no_tracking_scenario',
                  'You must have a tracking scenario defined to use time sheets.')
          end
          @property.set('scenarios', [ scenarioIdx ])
          # Show all tasks, sorted by seqno-up.
          @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
          # Show all resources, sorted by seqno-up.
          @property.set('hideResource',
                        LogicalExpression.new(LogicalOperation.new(0)))
          @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
          @property.set('loadUnit', :hours)
          @property.set('definitions', [])
        end
      })
      arg(2, 'file name', The name of the time sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel.
         )
    end

rule_tsStatus() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7207
    def rule_tsStatus
      pattern(%( !tsStatusHeader !tsStatusBody ))
      doc('status.timesheet', The status attribute can be used to describe the current status of the task orresource. The content of the status messages is added to the project journal.The status section is optional for tasks that have been worked on less thanone day during the report interval.
         )
      arg(2, 'headline', A short headline for the status. Must be 60 characters or shorter.
         )
      example('TimeSheet1', '4')
    end

rule_tsStatusAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7156
    def rule_tsStatusAttributes
      optional
      repeatable

      pattern(%( !details ))

      pattern(%( _flags !flagList ), lambda {
        @val[1].each do |flag|
          next if @journalEntry.flags.include?(flag)

          @journalEntry.flags << flag
        end
      })
      doc('flags.timesheet', Time sheet entries can have flags attached to them. These can be used toinclude only entries in a report that have a certain flag.
         )

      pattern(%( !summary ))
    end

rule_tsStatusBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7178
    def rule_tsStatusBody
      optional
      pattern(%( _{ !tsStatusAttributes _} ))
    end

rule_tsStatusHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7183
    def rule_tsStatusHeader
      pattern(%( _status !alertLevel $STRING ), lambda {
        if @val[2].length > 120
          error('ts_headline_too_long',
                "The headline must be 120 or less characters long. This one " +
                "has #{@val[2].length} characters.", @sourceFileInfo[2])
        end
        if @val[2] == 'Your headline here!'
          error('ts_no_headline',
                "'Your headline here!' is not a valid headline",
                @sourceFileInfo[2])
        end
        @journalEntry = JournalEntry.new(@project['journal'],
                                         @timeSheet.interval.end,
                                         @val[2],
                                         @property || @timeSheet.resource,
                                         @sourceFileInfo[0])
        @journalEntry.alertLevel = @val[1]
        @journalEntry.timeSheetRecord = @timeSheetRecord
        @journalEntry.author = @sheetAuthor
        @timeSheetRecord.status = @journalEntry if @timeSheetRecord
      })
    end

rule_tsTaskAttributes() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7223
    def rule_tsTaskAttributes
      optional
      repeatable

      pattern(%( _end !valDate ), lambda {
        if @val[1] < @timeSheet.interval.start
          error('ts_end_too_early',
                "The expected task end date must be after the start date of " +
                "this time sheet report.", @sourceFileInfo[1])
        end
        @timeSheetRecord.expectedEnd = @val[1]
      })
      doc('end.timesheet', The expected end date for the task. This can only be used for duration basedtask. For effort based task [[remaining]] has to be used.
         )
      example('TimeSheet1', '5')

      pattern(%( _priority $INTEGER ), lambda {
        priority = @val[1]
        if priority < 1 || priority > 1000
          error('ts_bad_priority',
                "Priority value #{priority} must be between 1 and 1000.",
                @sourceFileInfo[1])
        end
        @timeSheetRecord.priority = priority
      })
      doc('priority.timesheet', The priority is a value between 1 and 1000. It is used to determine thesequence of task when converting [[work]] to [[booking.task|bookings]]. Tasksthat need to finish earlier in the period should have a high priority, tasksthat end later in the period should have a low priority. For tasks that don'tget finished in the reported period the priority should be set to 1.
         )

      pattern(%( _remaining !workingDuration ), lambda {
        @timeSheetRecord.remaining = @val[1]
      })
      doc('remaining', The remaining effort for the task. This value is ignored if there are[[booking.task|bookings]] for the resource that overlap with the time sheetperiod.  If there are no bookings, the value is compared with the [[effort]]specification of the task. If there a mismatch between the accumulated effortspecified with bookings, [[work]] and [[remaining]] on one side and thespecified [[effort]] on the other, a warning is generated.This attribute can only be used with tasks that are effort based. Durationbased tasks need to have an [[end.timesheet|end]] attribute.
         )
      example('TimeSheet1', '6')

      pattern(%( !tsStatus ))

      pattern(%( _work !workingDurationPercent ), lambda {
        @timeSheetRecord.work = @val[1]
      })
      doc('work', The amount of time that the resource has spend with the task during thereported period. This value is ignored when there are[[booking.task|bookings]] for the resource overlapping with the time sheetperiod. If there are no bookings, TaskJuggler will try to convert the workspecification into bookings internally before the actual scheduling isstarted.Every task listed in the time sheet needs to have a work attribute. The totalaccumulated work time that is reported must match exactly the total workinghours for the resource for that period.If a resource has no vacation during the week that is reported and it has aregular 40 hour work week, exactly 40 hours total or 5 working days have to bereported.
         )
      example('TimeSheet1', '4')
    end

rule_tsTaskBody() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7302
    def rule_tsTaskBody
      pattern(%( _{ !tsTaskAttributes _} ))
    end

rule_tsTaskHeader() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7306
    def rule_tsTaskHeader
      pattern(%( _task !taskId ), lambda {
        @property = @val[1]
        unless @property.leaf?
          error('ts_task_not_leaf',
                'You cannot specify a task that has sub tasks here.',
                @sourceFileInfo[1], @property)
        end

        @timeSheetRecord = TimeSheetRecord.new(@timeSheet, @property)
        @timeSheetRecord.sourceFileInfo = @sourceFileInfo[0]
      })
      arg(1, 'task', 'ID of an already existing task')
    end

rule_vacationName() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7321
    def rule_vacationName
      optional
      pattern(%( $STRING )) # We just throw the name away
      arg(0, 'name', 'An optional name or reason for the leave')
    end

rule_valDate() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7327
    def rule_valDate
      pattern(%( !date ), lambda {
        if @val[0] < @project['start'] || @val[0] > @project['end']
          error('date_in_range',
                "Date #{@val[0]} must be within the project time frame " +
                "#{@project['start']}  - #{@project['end']}",
                @sourceFileInfo[0])
        end
        @val[0]
      })
    end

rule_valInterval() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7387
    def rule_valInterval
      pattern(%( !date !intervalEnd ), lambda {
        mode = @val[1][0]
        endSpec = @val[1][1]
        if mode == 0
          unless @val[0] < endSpec
            error('start_before_end', "The end date (#{endSpec}) must be after " +
                  "the start date (#{@val[0]}).", @sourceFileInfo[1])
          end
          iv = TimeInterval.new(@val[0], endSpec)
        else
          iv = TimeInterval.new(@val[0], @val[0] + endSpec)
        end
        checkInterval(iv)
        iv
      })
      doc('interval1', There are two ways to specify a date interval. The start and end date must lie within the specified project period.The first is the most obvious. A date interval consists of a start and endDATE. Watch out for end dates without a time specification! Datespecifications are 0 extended. An end date without a time is expanded tomidnight that day. So the day of the end date is not included in the interval!The start and end dates must be separated by a hyphen character.In the second form specifies the start date and an interval duration. Theduration must be prefixed by a plus character.
         )
    end

rule_valIntervalOrDate() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7349
    def rule_valIntervalOrDate
      pattern(%( !date !intervalOptionalEnd ), lambda {
        if @val[1]
          mode = @val[1][0]
          endSpec = @val[1][1]
          if mode == 0
            unless @val[0] < endSpec
              error('start_before_end', "The end date (#{endSpec}) must be " +
                    "after the start date (#{@val[0]}).",
                    @sourceFileInfo[1])
            end
            iv = TimeInterval.new(@val[0], endSpec)
          else
            iv = TimeInterval.new(@val[0], @val[0] + endSpec)
          end
        else
          iv = TimeInterval.new(@val[0], @val[0].sameTimeNextDay)
        end
        checkInterval(iv)
        iv
      })
      doc('interval4', There are three ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form, the end date is omitted. A 24 hour interval is assumed.The third form specifies the start date and an interval duration. The duration must be prefixed by a plus character.The start and end date of the interval must be within the specified projecttime frame.
         )
    end

rule_valIntervals() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7418
    def rule_valIntervals
      listRule('moreValIntervals', '!valIntervalOrDate')
    end

rule_validTimeZone() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7339
    def rule_validTimeZone
      pattern(%( $STRING ), lambda {
        unless TjTime.checkTimeZone(@val[0])
          error('bad_time_zone', "#{@val[0]} is not a known time zone",
                @sourceFileInfo[0])
        end
        @val[0]
      })
    end

rule_warn() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7422
    def rule_warn
      pattern(%( _warn !logicalExpression ), lambda {
        begin
          @property.set('warn', @property.get('warn') + [ @val[1] ])
        rescue AttributeOverwrite
        end
      })
      doc('warn', The warn attribute adds a [[logicalexpression|logical expression]] to theproperty. The condition described by the logical expression is checked afterthe scheduling and an warning is generated if the condition evaluates to true.This attribute is primarily intended for testing purposes.
         )
    end

rule_weekDayInterval() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7449
    def rule_weekDayInterval
      pattern(%( !weekday !weekDayIntervalEnd ), lambda {
        weekdays = Array.new(7, false)
        if @val[1].nil?
          weekdays[@val[0]] = true
        else
          d = @val[0]
          loop do
            weekdays[d] = true
            break if d == @val[1]
            d = (d + 1) % 7
          end
        end

        weekdays
      })
      arg(0, 'weekday', 'Weekday (sun - sat)')
    end

rule_weekDayIntervalEnd() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7468
    def rule_weekDayIntervalEnd
      optional
      pattern([ '_-', '!weekday' ], lambda {
        @val[1]
      })
      arg(1, 'end weekday',
          'Weekday (sun - sat). It is included in the interval.')
    end

rule_weekday() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7439
    def rule_weekday
      pattern(%( _sun ), lambda { 0 })
      pattern(%( _mon ), lambda { 1 })
      pattern(%( _tue ), lambda { 2 })
      pattern(%( _wed ), lambda { 3 })
      pattern(%( _thu ), lambda { 4 })
      pattern(%( _fri ), lambda { 5 })
      pattern(%( _sat ), lambda { 6 })
    end

rule_workingDuration() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7477
    def rule_workingDuration
      pattern(%( !number !durationUnit ), lambda {
        convFactors = [ 60, # minutes
                        60 * 60, # hours
                        60 * 60 * @project['dailyworkinghours'], # days
                        60 * 60 * @project['dailyworkinghours'] *
                        (@project.weeklyWorkingDays), # weeks
                        60 * 60 * @project['dailyworkinghours'] *
                        (@project['yearlyworkingdays'] / 12), # months
                        60 * 60 * @project['dailyworkinghours'] *
                        @project['yearlyworkingdays'] # years
                      ]
        # The result will always be in number of time slots.
        (@val[0] * convFactors[@val[1]] /
         @project['scheduleGranularity']).round.to_i
      })
      arg(0, 'value', 'A floating point or integer number')
    end

rule_workingDurationPercent() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7496
    def rule_workingDurationPercent
      pattern(%( !number !durationUnitOrPercent ), lambda {
        if @val[1] >= 0
          # Absolute value in minutes, hours or days.
          convFactors = [ 60, # minutes
            60 * 60, # hours
            60 * 60 * @project['dailyworkinghours'] # days
          ]
          # The result will always be in number of time slots.
          (@val[0] * convFactors[@val[1]] /
           @project['scheduleGranularity']).round.to_i
        else
          # Percentage values are always returned as Float in the rage of 0.0 to
          # 1.0.
          if @val[0] < 0.0 || @val[0] > 100.0
            error('illegal_percentage',
                  "Percentage values must be between 0 and 100%.",
                  @sourceFileInfo[1])
          end
          @val[0] / 100.0
        end
      })
      arg(0, 'value', 'A floating point or integer number')
    end

rule_workinghours() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7521
    def rule_workinghours
      pattern(%( _workinghours !listOfDays !listOfTimes), lambda {
        if @property.nil?
          # We are changing global working hours.
          wh = @project['workinghours']
        else
          unless (wh = @property['workinghours', @scenarioIdx])
            # The property does not have it's own WorkingHours yet.
            wh = WorkingHours.new(@project['workinghours'])
          end
        end
        wh.timezone = @project['timezone']
        begin
          7.times { |i| wh.setWorkingHours(i, @val[2]) if @val[1][i] }
        rescue
          error('bad_workinghours', $!.message)
        end

        if @property
          # Make sure we actually assign something so the attribute is marked as
          # set by the user.
          begin
            @property['workinghours', @scenarioIdx] = wh
          rescue AttributeOverwrite
            # Working hours can be set multiple times.
          end
        end
      })
    end

rule_workinghoursProject() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7551
    def rule_workinghoursProject
      pattern(%( !workinghours ))
      doc('workinghours.project', Set the default working hours for all subsequent resource definitions. Thestandard working hours are 9:00am - 12:00am, 1:00pm - 18:00pm, Monday toFriday. The working hours specification limits the availability of resourcesto certain time slots of week days.These default working hours can be replaced with other working hours forindividual resources.
         )
      also(%( dailyworkinghours workinghours.resource workinghours.shift ))
      example('Project')
    end

rule_workinghoursResource() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7567
    def rule_workinghoursResource
      pattern(%( !workinghours ))
      doc('workinghours.resource', Set the working hours for a specific resource. The working hours specificationlimits the availability of resources to certain time slots of week days.
         )
      also(%( workinghours.project workinghours.shift ))
    end

rule_workinghoursShift() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7577
    def rule_workinghoursShift
      pattern(%( !workinghours ))
      doc('workinghours.shift', Set the working hours for the shift. The working hours specification limitsthe availability of resources or the activity on a task to certain timeslots of week days.The shift working hours will replace the default or resource working hours forthe specified time frame when assigning the shift to a resource.In case the shift is used for a task, resources are only assigned during theworking hours of this shift and during the working hours of the allocatedresource. Allocations only happen when both the task shift and the resourcework hours allow work to happen.
         )
      also(%( workinghours.project workinghours.resource ))
    end

rule_yesNo() click to toggle source

    # File lib/taskjuggler/TjpSyntaxRules.rb, line 7596
    def rule_yesNo
      pattern(%( _yes ), lambda {
        true
      })
      pattern(%( _no ), lambda {
        false
      })
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.