database_transformation

relational-database-bridge grammar version 101

'root': [ root ] group {
	'root': [ = ] component 'node mapping'
}
/* data context information */
'context creation' { }
/* execution context information */
'unguaranteed operation' {
	'annotate': stategroup (
		'yes' { [ <!, !> ]
			'annotation' : text
		}
		'no' { }
	)
}
'null guard' {
	'require guard': stategroup (
		'yes' { [ nullable ]
			'unguaranteed operation': component 'unguaranteed operation'
		}
		'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: enum' { }
'variable assignment: regexp' { }
'variable assignment: array' { }
'variable assignment: partition' { }
'variable assignment: block' {
	'branches': [ (, ) ] dictionary { @block indent [ $ ]
		'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'
			}
			'enum' { [ : enum ]
				'expression': [ = ] component 'enum expression'
				'assignment': component 'variable assignment: enum'
			}
		)
	}
}
/* type specific context selection */
'implicit constraint' {
	'key type': stategroup (
		'primary key' {
			'fields': [ (, ) ] dictionary {
				'data type': [ == ] stategroup (
					'enum' { [ enum ]
						'value': component 'enum expression'
					}
					'integer' { [ integer ]
						'value': component 'number expression'
					}
					'text' { [ text ]
						'value': component 'text expression'
					}
				)
			}
		}
		'unique index' {
			'index': [ : ] reference
			'fields': [ (, ) ] dictionary {
				'data type': [ == ] stategroup (
					'enum' { [ enum ]
						'value': component 'enum expression'
					}
					'integer' { [ integer ]
						'value': component 'number expression'
					}
					'text' { [ text ]
						'value': component 'text expression'
					}
				)
			}
		}
	)
	'unguaranteed operation': component 'unguaranteed operation'
}
'context selector recursive' {
	'step': stategroup (
		'yes' {
			'type': stategroup (
				'explicit foreign key' {
					'link': [ >> ] reference
				}
				'implicit foreign key' {
					'table': [ >> ] reference
					'create context' : component 'context creation'
					'assignment' : component 'variable assignment: context'
					'expression' : component 'implicit constraint'
				}
				'child collection' { [ inverse ]
					'source': [ table ] reference
					'links to me': [ >> ] reference
				}
			)
			'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 (
		'root' {
			'table': [ table ] reference
			'create context': component 'context creation'
		}
		'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'
		}
	)
}
'number expression transformation' {
	'base': [ * ] integer
	'exponent': [ ^ ] integer
	'rounding': stategroup (
		'ordinary' { [ round ] }
		'ceil' { [ ceil ] }
		'floor' { [ floor ] }
	)
}
'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'
		}
		'convert date' { [ to-date ]
			'unguaranteed operation': component 'unguaranteed operation'
			'selection': component 'regexp selector'
			'components': @block indent [ where ] group {
				'year': @block indent  [ year = ] reference
				'offset': stategroup (
					'month based' {
						'month': @block indent [ month = ] reference
						'day of month': @block indent [ day = ] reference
					}
					'week based' {
						'week': @block indent [ week = ] reference
						'day of week': @block indent [ 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': @block indent [ where ] group {
				'year': @block indent [ year = ] reference
				'month': @block indent [ month = ] reference
				'day of month': @block indent [ day = ] reference
				'hour': @block indent [ hour = ] reference
				'minute': @block indent [ minute = ] reference
				'second': @block indent [ 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'
			'field': [ . ] reference
			'conversion': stategroup (
				'real to integer' {
					'transformation': component 'number expression transformation'
				}
				'none' { }
			)
			'null guard': component 'null guard'
		}
		'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'
			'field': [ ? ] reference
			'null guard': component 'null guard'
			'branches': [ (, ) ] dictionary { @block indent [ | ]
				'has predecessor': stategroup = node-switch predecessor (
					| node = 'yes' { 'predecessor' = predecessor }
					| none = 'no'
				)
				'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
		}
	)
}
'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'
		}
		'from context' {
			'merge operation': stategroup (
				'none' { }
				'join' { [ join ]
					'separator': text
				}
				'shared value' { [ shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'field': [ . ] reference
			'null guard': component 'null guard'
		}
		'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'
			'field': [ ? ] reference
			'null guard': component 'null guard'
			'branches': [ (, ) ] dictionary { @block indent [ | ]
				'expression': [ = ] component 'text expression'
			}
		}
		'concatenation' { [ concat ]
			'expressions': [ (, ) ] component 'text expression: concatenate'
		}
		'static value' {
			'value' : text
		}
	)
}
'enum expression' {
	'type': stategroup (
		'from context' {
			'merge operation': stategroup (
				'none' { }
				'shared value' { [ shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'field': [ . ] reference
			'null guard': component 'null guard'
		}
		'from variable' {
			'selection': component 'variable selector'
		}
	)
}
'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'
				}
			)
		}
		'from context' { [ bool ]
			'selection': component 'context selector'
			'merge operation': stategroup (
				'none' { }
				'shared value' { [ shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'field': [ . ] reference
			'null guard': component 'null guard'
		}
	)
}
'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'
		'new entry' { [ = ]
			'mapping': component 'node mapping'
		}
		'sub expression' { [ (, ) ]
			'list': @block indent component 'collection expression list'
		}
		'none' { [ none ] }
	)
}
'collection expression list' {
	'has expressions': stategroup (
		'yes' {
			'expression': @block 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': @block indent [ | true ] component 'state mapping'
			'on false': @block indent [ | false ] component 'state mapping'
		}
		'enrich' { @block indent [ try ]
			'try assign': component 'variable assignment: block'
			'on success': @block [ | success ] component 'state mapping'
			'on failure': @block [ | failure ] component 'state mapping'
		}
		'context switch' {
			'selection': component 'context selector'
			'on singular': @block indent [ | singular ] group {
				'create context': component 'context creation'
				'assignment': component 'variable assignment: context'
				'mapping': component 'state mapping'
			}
			'on plural': @block indent [ | plural ] group {
				'create context': component 'context creation'
				'assignment': component 'variable assignment: context'
				'mapping': component 'state mapping'
			}
		}
		'number switch' { [ number-switch ]
			'number': component 'number expression'
			'on positive': @block indent [ | positive ] component 'state mapping'
			'on negative': @block indent [ | negative ] component 'state mapping'
			'on zero': @block indent [ | zero ] component 'state mapping'
		}
		'from context' {
			'merge operation': stategroup (
				'none' { [ switch ] }
				'shared value' { [ switch-shared ]
					'unguaranteed operation': component 'unguaranteed operation'
				}
			)
			'selection': component 'context selector'
			'field': [ ? ] reference
			'null guard': component 'null guard'
			'mappings': [ (, ) ] dictionary { @block indent [ | ]
				'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': @block indent [ | success ] component 'state mapping'
			'on failure': @block indent [ | failure ] component 'state mapping'
		}
		'set state' {
			'state': reference
			'mapping': component 'node mapping'
		}
	)
}
'node mapping' { [ (, ) ]
	'define block': stategroup (
		'yes' { @block indent
			'block': component 'variable assignment: block'
		}
		'no' { }
	)
	'properties': dictionary { @block indent
		'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 ]
				'type': [ = ] stategroup (
					'unbounded' { }
					'bounded' { [ unsafe ]
						'unguaranteed operation': component 'unguaranteed operation'
					}
				)
				'value source': stategroup (
					'clock' { [ now ] }
					'source' {
						'expression': component 'number expression'
					}
				)
			}
			'text' { [ text ]
				'expression': [ = ] component 'text expression'
			}
		)
	}
}