migration_mapping

datastore grammar version 99.1

'root': [ root ] group {
	'create root': component 'context creation'
	'assignment': [ = root as $ ] component 'variable assignment: context'
	'root': component 'node mapping'
}
/* data context information */
'context creation' { }
/* execution context information */
'unguaranteed operation' {
	'annotate': [ <!, !> ] stategroup (
		'yes' {
			'annotation': text
		}
		'no' { }
	)
}
/* static data descriptors */
'number list' {
	'type': stategroup (
		'single' {
			'value': integer
		}
		'range' {
			'begin': integer
			'end': [ - ] integer
		}
	)
	'has more': stategroup (
		'yes' {
			'tail': [ , ] component 'number list'
		}
		'no' { }
	)
}
'text list' {
	'value': text
	'has more': stategroup (
		'yes' {
			'tail': [ , ] component 'text list'
		}
		'no' { }
	)
}
/* variable stack */
'variable selector' {
	'stack': stategroup (
		'non-empty' {
			'select': stategroup (
				'this' { [ $ ] }
				'parent' { [ $^ ]
					'tail': component 'variable selector'
				}
				'partition' {
					'select': stategroup (
						'key' { [ $key ] }
						'set' { [ $set ] }
					)
				}
				'branch' { [ $ ]
					'branch': reference
				}
			)
		}
	)
}
'variable assignment: context' { }
'variable assignment: number' { }
'variable assignment: text' { }
'variable assignment: regexp' { }
'variable assignment: array' { }
'variable assignment: partition' { }
'variable assignment: block' {
	'branches': [ (, ) ] dictionary { [ $ ]
		'type': stategroup (
			'context' { [ = ]
				'expression': component 'context selector'
				'create context': component 'context creation'
				'assignment': component 'variable assignment: context'
			}
			'array' { [ : array = ]
				'selection': component 'context selector'
				'transformation': stategroup (
					'none' { [ on ]
						'unguaranteed operation': component 'unguaranteed operation'
					}
					'partition' { [ partition ]
						'create bucket': component 'context creation'
					}
				)
				'index': [ [, ] ] group {
					'create context': component 'context creation'
					'assignment': component 'variable assignment: context'
					'expression': component 'number expression'
				}
				'assignment': component 'variable assignment: array'
			}
			'regexp' { [ : regexp ]
				'regexp': [ = ] reference
				'unguaranteed operation': component 'unguaranteed operation'
				'value': [ on ] component 'text expression'
				'assignment': component 'variable assignment: regexp'
			}
			'number' { [ : number ]
				'expression': [ = ] component 'number expression'
				'assignment': component 'variable assignment: number'
			}
			'text' { [ : text ]
				'expression': [ = ] component 'text expression'
				'assignment': component 'variable assignment: text'
			}
		)
	}
}
/* type specific context selection */
'context selector recursive' {
	'step': stategroup (
		'yes' {
			'type': stategroup (
				'group' {
					'attribute': [ . ] reference
				}
				'collection' {
					'attribute': [ ., * ] reference
				}
				'entry' {
					'attribute': [ . ] reference
					'key': [ [, ] ] group {
						'create context': component 'context creation'
						'assignment': component 'variable assignment: context'
						'expression': component 'text expression'
					}
					'unguaranteed operation': component 'unguaranteed operation'
				}
				'reference' {
					'attribute': [ > ] reference
				}
				'parent' { [ ^ ] }
			)
			'create context': component 'context creation'
			'optional assignment': stategroup (
				'assign' { [ as $ ]
					'assignment': component 'variable assignment: context'
				}
				'skip' { }
			)
			'tail': component 'context selector recursive'
		}
		'no' { }
	)
}
'context selector' {
	'source': stategroup (
		'stack' {
			'selection': component 'variable selector'
		}
		'array' {
			'operation': stategroup (
				'predecessor' { [ predecessor ] }
				'successor' { [ successor ] }
			)
			'key expression': [ of ] component 'number expression'
			'selection': [ in ] component 'variable selector'
			'unguaranteed operation': component 'unguaranteed operation'
		}
	)
	'steps': component 'context selector recursive'
}
/* generic sub expressions */
'regexp selector' {
	'source': stategroup (
		'stack' {
			'selection': component 'variable selector'
		}
		'inline' { [ inline ]
			'regexp': reference
			'unguaranteed operation': component 'unguaranteed operation'
			'value': [ on ] component 'text expression'
		}
	)
}
'date expression' {
	'year': component 'number expression'
	'style': stategroup (
		'calendar' {
			'month': [ - ] component 'number expression'
			'day': [ - ] component 'number expression'
		}
		'week' { [ W ]
			'week': component 'number expression'
			'day of week': stategroup (
				'monday' { [ Monday ] }
				'tuesday' { [ Tuesday ] }
				'wednesday' { [ Wednesday ] }
				'thursday' { [ Thursday ] }
				'friday' { [ Friday ] }
				'saturday' { [ Saturday ] }
				'sunday' { [ Sunday ] }
			)
		}
		'ordinal' {
			'day': [ , ] component 'number expression'
		}
	)
}
'time expression' {
	'hour': component 'number expression'
	'minute': [ : ] component 'number expression'
	'second': [ : ] component 'number expression'
}
'number expression list' {
	'expression': component 'number expression'
	'has more': stategroup (
		'yes' { [ , ]
			'tail': component 'number expression list'
		}
		'no' { }
	)
}
'number expression' {
	'type': stategroup (
		'convert text' { [ to-number ]
			'unguaranteed operation': component 'unguaranteed operation'
			'value': component 'text expression'
		}
		'cast to positive number' { [ to-positive ]
			'unguaranteed operation': component 'unguaranteed operation'
			'value': component 'number expression'
		}
		'convert date' { [ to-date ]
			'unguaranteed operation': component 'unguaranteed operation'
			'selection': component 'regexp selector'
			'components': [ where ] group {
				'year': [ year = ] reference
				'offset': stategroup (
					'month based' {
						'month': [ month = ] reference
						'day of month': [ day = ] reference
					}
					'week based' {
						'week': [ week = ] reference
						'day of week': [ day = ] stategroup (
							'monday' { [ Monday ] }
							'tuesday' { [ Tuesday ] }
							'wednesday' { [ Wednesday ] }
							'thursday' { [ Thursday ] }
							'friday' { [ Friday ] }
							'saturday' { [ Saturday ] }
							'sunday' { [ Sunday ] }
						)
					}
				)
			}
		}
		'convert date and time' { [ to-datetime ]
			'unguaranteed operation': component 'unguaranteed operation'
			'selection': component 'regexp selector'
			'components': [ where ] group {
				'year': [ year = ] reference
				'month': [ month = ] reference
				'day of month': [ day = ] reference
				'hour': [ hour = ] reference
				'minute': [ minute = ] reference
				'second': [ second = ] reference
			}
		}
		'make date' { [ make-date ]
			'date': [ (, ) ] component 'date expression'
		}
		'make date time' { [ make-date-time ]
			'date': [ ( ] component 'date expression'
			'time': [ T, ) ] component 'time expression'
		}
		'make time' { [ make-time ]
			'time': [ (, ) ] component 'time expression'
		}
		'from context' {
			'merge operation': stategroup (
				'none' { }
				'sum' { [ sum ] }
				'shared value' { [ shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
				'max value' { [ max ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
				'min value' { [ min ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'attribute': [ . ] reference
		}
		'from variable' {
			'selection': component 'variable selector'
		}
		'conditional' {
			'merge operation': stategroup (
				'none' { [ switch ] }
				'shared value' { [ switch-shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'attribute': [ . ] reference
			'branches': [ (, ) ] dictionary { [ | ]
				'has predecessor': stategroup = node-switch predecessor (
					| node = 'yes' { 'predecessor' = predecessor }
					| none = 'no'
				)
				'optional variable assignment': stategroup (
					'assign' { [ as $ ]
						'create context': component 'context creation'
						'assignment': component 'variable assignment: context'
					}
					'skip' { }
				)
				'expression': [ = ] component 'number expression'
			}
			'has branch': stategroup = node-switch .'branches' (
				| nodes = 'yes' { 'last' = last }
				| none  = 'no'
			)
		}
		'unary operation' {
			'operation': stategroup (
				'additive inverse' { [ - ] }
			)
			'expression': component 'number expression'
		}
		'list operation' {
			'operation': stategroup (
				'sum' { [ sum ] }
				'product' { [ product ] }
			)
			'list': [ (, ) ] component 'number expression list'
		}
		'division' { [ division ]
			'left': [ ( ] component 'number expression'
			'right': [ ,, ) ] component 'number expression'
		}
		'static value' {
			'value': integer
		}
	)
}
'date pattern' {
	'type': stategroup (
		'text' {
			'value': component 'text expression'
		}
		'year' { [ YYYY ] }
		'month' { [ MM ] }
		'day of month' { [ DD ] }
		'week' { [ WW ] }
		'day of week' { [ D ] }
		'day of year' { [ DDD ] }
	)
	'has tail': stategroup (
		'yes' {
			'tail': component 'date pattern'
		}
		'no' { }
	)
}
'time pattern' {
	'type': stategroup (
		'text' {
			'value': component 'text expression'
		}
		'hour' { [ hh ] }
		'minute' { [ mm ] }
		'second' { [ ss ] }
	)
	'has tail': stategroup (
		'yes' {
			'tail': component 'time pattern'
		}
		'no' { }
	)
}
'text expression: concatenate' {
	'expression': component 'text expression'
	'has more': stategroup (
		'yes' { [ , ]
			'tail': component 'text expression: concatenate'
		}
		'no' { }
	)
}
'text expression' {
	'type': stategroup (
		'convert number' { [ to-text ]
			'value': component 'number expression'
		}
		'format date' { [ format-date ]
			'date': [ (, ) ] component 'date pattern'
			'value': component 'number expression'
		}
		'format date and time' { [ format-date-time ]
			'date': [ ( ] component 'date pattern'
			'time': [ ,, ) ] component 'time pattern'
			'value': component 'number expression'
		}
		'format time' { [ format-time ]
			'time': [ (, ) ] component 'time pattern'
			'value': component 'number expression'
		}
		'from context' {
			'merge operation': stategroup (
				'none' { }
				'join' { [ join ]
					'separator': text
				}
				'shared value' { [ shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'attribute': [ . ] reference
		}
		'from regexp' { [ regexp ]
			'selection': component 'regexp selector'
			'capture': [ @ ] reference
		}
		'from variable' {
			'selection': component 'variable selector'
		}
		'conditional' {
			'merge operation': stategroup (
				'none' { [ switch ] }
				'shared value' { [ switch-shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'attribute': [ . ] reference
			'branches': [ (, ) ] dictionary { [ | ]
				'optional variable assignment': stategroup (
					'assign' { [ as $ ]
						'create context': component 'context creation'
						'assignment': component 'variable assignment: context'
					}
					'skip' { }
				)
				'expression': [ = ] component 'text expression'
			}
		}
		'concatenation' { [ concat ]
			'expressions': [ (, ) ] component 'text expression: concatenate'
		}
		'static value' {
			'value': text
		}
	)
}
'boolean expression: candidates' {
	'expression': component 'boolean expression'
	'has more': stategroup (
		'yes' { [ , ]
			'tail': component 'boolean expression: candidates'
		}
		'no' { }
	)
}
'boolean expression' {
	'type': stategroup (
		'logic operation' {
			'operation': stategroup (
				'and' { [ and ] }
				'or' { [ or ] }
			)
			'expressions': [ (, ) ] component 'boolean expression: candidates'
		}
		'compare number' {
			'sub type': stategroup (
				'binary operation' {
					'left': [ # ] component 'number expression'
					'operation': stategroup (
						'equal' { [ == ] }
						'greater' { [ > ] }
						'greater equal' { [ >= ] }
						'smaller' { [ < ] }
						'smaller equal' { [ <= ] }
					)
					'right': [ # ] component 'number expression'
				}
				'set operation' { [ is ]
					'find': [ #, in ] component 'number expression'
					'in': [ (, ) ] component 'number list'
				}
			)
		}
		'compare text' {
			'sub type': stategroup (
				'binary operation' {
					'left': component 'text expression'
					'operation': stategroup (
						'equals' { [ equals ] }
						'starts with' { [ starts-with ] }
						'ends with' { [ ends-with ] }
					)
					'right': component 'text expression'
				}
				'set operation' {
					'find': [ is, in ] component 'text expression'
					'in': [ (, ) ] component 'text list'
				}
			)
		}
	)
}
'collection selector' {
	'variable type': [ (, ) ] stategroup (
		'context' {
			'selection': component 'context selector'
			'create row': component 'context creation'
		}
		'array' { [ array ]
			'selection': component 'variable selector'
		}
	)
}
'collection expression' {
	'type': stategroup (
		'map' { [ map ]
			'selection': component 'collection selector'
			'optional assignment': stategroup (
				'assign' { [ as $ ]
					'assignment': component 'variable assignment: context'
				}
				'skip' { }
			)
			'mapping': component 'collection expression'
		}
		'partition' { [ partition ]
			'selection': component 'collection selector'
			'index': group { [ [, ] ]
				'assignment': component 'variable assignment: context'
				'expression': component 'text expression'
			}
			'create set': component 'context creation'
			'optional assignment': stategroup (
				'assign' { [ as ( $key , $set ) ]
					'key assignment': component 'variable assignment: text'
					'set assignment': component 'variable assignment: context'
					'assignment': component 'variable assignment: partition'
				}
				'skip' { }
			)
			'mapping': component 'collection expression'
		}
		'conditional' {
			'merge operation': stategroup (
				'none' { [ switch ] }
				'shared value' { [ switch-shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'attribute': [ . ] reference
			'branches': [ (, ) ] dictionary { [ | ]
				'optional variable assignment': stategroup (
					'assign' { [ as $ ]
						'create context': component 'context creation'
						'assignment': component 'variable assignment: context'
					}
					'skip' { }
				)
				'expression': component 'collection expression'
			}
		}
		'new entry' { [ = ]
			'mapping': component 'node mapping'
		}
		'sub expression' { [ (, ) ]
			'list': component 'collection expression list'
		}
		'none' { [ none ] }
	)
}
'collection expression list' {
	'has expressions': stategroup (
		'yes' {
			'expression': component 'collection expression'
			'tail': component 'collection expression list'
		}
		'no' { }
	)
}
'collection mapping' { [ = ]
	'unguaranteed operation': component 'unguaranteed operation'
	'expression': component 'collection expression'
}
'state mapping' { [ = ]
	'type': stategroup (
		'panic' { [ panic ]
			'comment': text
		}
		'conditional' { [ match ]
			'condition': component 'boolean expression'
			'on true': [ | true ] component 'state mapping'
			'on false': [ | false ] component 'state mapping'
		}
		'enrich' { [ try ]
			'try assign': component 'variable assignment: block'
			'on success': [ | success ] component 'state mapping'
			'on failure': [ | failure ] component 'state mapping'
		}
		'context switch' {
			'selection': component 'context selector'
			'on singular': [ | singular ] group {
				'create context': component 'context creation'
				'assignment': component 'variable assignment: context'
				'mapping': component 'state mapping'
			}
			'on plural': [ | plural ] group {
				'create context': component 'context creation'
				'assignment': component 'variable assignment: context'
				'mapping': component 'state mapping'
			}
		}
		'from context' {
			'merge operation': stategroup (
				'none' { [ switch ] }
				'shared value' { [ switch-shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'attribute': [ . ] reference
			'mappings': [ (, ) ] dictionary { [ | ]
				'optional variable assignment': stategroup (
					'assign' { [ as $ ]
						'create context': component 'context creation'
						'assignment': component 'variable assignment: context'
					}
					'skip' { }
				)
				'mapping': component 'state mapping'
			}
		}
		'from array' {
			'operation': stategroup (
				'first' { [ first ] }
				'last' { [ last ] }
			)
			'selection': [ in ] component 'variable selector'
			'optional variable assignment': stategroup (
				'assign' {
					'assignment': [ as $ ] component 'variable assignment: context'
				}
				'skip' { }
			)
			'on success': [ | success ] component 'state mapping'
			'on failure': [ | failure ] component 'state mapping'
		}
		'set state' {
			'state': reference
			'mapping': component 'node mapping'
		}
	)
}
'node mapping' { [ (, ) ]
	'define block': stategroup (
		'yes' {
			'block': component 'variable assignment: block'
		}
		'no' { }
	)
	'properties': dictionary {
		'type': [ : ] stategroup (
			'group' { [ group ]
				'optional binding': [ = ] stategroup (
					'bind' {
						'selection': component 'context selector'
						'create context': [ as ] component 'context creation'
						'assignment': [ $ ] component 'variable assignment: context'
					}
					'skip' { }
				)
				'mapping': component 'node mapping'
			}
			'collection' { [ collection ]
				'mapping': component 'collection mapping'
			}
			'stategroup' { [ stategroup ]
				'mapping': component 'state mapping'
			}
			'number' { [ number ]
				'value source': [ = ] stategroup (
					'clock' { [ now ] }
					'source' {
						'expression': component 'number expression'
					}
				)
			}
			'text' { [ text ]
				'expression': [ = ] component 'text expression'
			}
			'file' { [ file ]
				'value source': [ = ] stategroup (
					'static' { [ [, ] ]
						'token': text
						'extension': [ , ] text
					}
					'context' {
						'merge operation': [ / ] stategroup (
							'none' { }
							'shared value' { [ shared ]
								'unguaranteed operation': component 'unguaranteed operation'
							}
						)
						'selection': component 'context selector'
						'attribute': [ . ] reference
					}
				)
			}
		)
	}
}