processor

connector grammar version 27

'archetype': stategroup (
	'scheduled provider' { [ provider ]
		'main routine': component 'statement'
		'command routines': dictionary { [ command ]
			'has next': stategroup = node-switch successor (
				| node = 'yes' { 'next' = successor }
				| none = 'no'
			)
			'statement': [ do ] component 'statement'
		}
	}
	'consumer' { [ consumer ]
		'context keys': [ (, ) ] dictionary {
			'has next': stategroup = node-switch successor (
				| node = 'yes' { 'next' = successor }
				| none = 'no'
			)
			'value': [ = ] component 'value promise'
		}
		'routines': dictionary { [ routine ]
			'has next': stategroup = node-switch successor (
				| node = 'yes' { 'next' = successor }
				| none = 'no'
			)
			'binding': [ on ] stategroup (
				'event' {
					'event': [ event ] reference
				}
				'node' { }
			)
			'named type': component 'interface named path'
			'statement': [ do ] component 'statement'
		}
	}
)
/* interface bindings */
'interface type path' {
	'has step': stategroup (
		'yes' {
			'property': [ . ] reference
			'type': stategroup (
				'collection' { ['[ ]'] }
				'choice' {
					'state': [ ? ] reference
				}
				'node' { }
			)
			'tail': component 'interface type path'
		}
		'no' { }
	)
}
'interface named path' {
	'segments': dictionary {
		'has previous': stategroup = node-switch predecessor (
			| node = 'yes' { 'previous' = predecessor }
			| none = 'no'
		)
		'has next': stategroup = node-switch successor (
			| node = 'yes' { 'next' = successor }
			| none = 'no'
		)
		'steps': [ = ] component 'interface type path'
	}
	'has segment': stategroup = node-switch .'segments' (
		| nodes = 'yes' {
			'first' = first
			'last' = last
		}
		| none  = 'no'
	)
}
/* type system */
'schema scalar type' {
	'type': stategroup (
		'boolean' { [ boolean ] }
		'integer' { [ integer ]
			'rule': component 'decimal import rule'
		}
		'text' { [ text ] }
		'choice' { [ choice ]
			'options': [ (, ) ] dictionary {
				'base type': stategroup (
					'integer' {
						'value': [ : ] integer
					}
					'text' { }
				)
			}
		}
	)
}
'schema complex type' {
	'type': stategroup (
		'any' { [ any ] }
		'node' {
			'node': component 'schema node type'
		}
		'collection' { [ collection ]
			'type': component 'schema complex type'
		}
		'list' { [ list ]
			'type': component 'schema complex type'
		}
		'scalar' {
			'type': component 'schema scalar type'
		}
	)
}
'schema node type' {
	'properties': [ {, } ] dictionary {
		'has next': stategroup = node-switch successor (
			| node = 'yes' { 'next' = successor }
			| none = 'no'
		)
		'has attributes': stategroup (
			'yes' { [ <, > ]
				'attributes': dictionary {
					'has next': stategroup = node-switch successor (
						| node = 'yes' { 'next' = successor }
						| none = 'no'
					)
					'type': [ : ] component 'schema scalar type'
				}
				'filters': dictionary { [ where ]
					'has next': stategroup = node-switch successor (
						| node = 'yes' { 'next' = successor }
						| none = 'no'
					)
					'value': [ is ] component 'value promise'
				}
			}
			'no' { }
		)
		'is optional': [ : ] stategroup (
			'yes' { [ optional ] }
			'no' { }
		)
		'type': component 'schema complex type'
	}
}
'schema type' {
	'root': component 'schema complex type'
}
/* execution state */
'stack block' {
	'values': dictionary { [ let $ ]
		'has previous': stategroup = node-switch predecessor (
			| node = 'yes' { 'previous' = predecessor }
			| none = 'no'
		)
		'has next': stategroup = node-switch successor (
			| node = 'yes' { 'next' = successor }
			| none = 'no'
		)
		'type': stategroup (
			'inferred' {
				'value': [ = ] component 'value promise'
			}
			'schema' {
				'schema': [ as ] component 'schema type'
				'statement': [ = ] component 'statement'
			}
		)
	}
}
'stack selector' {
	'stack': stategroup (
		'non-empty' {
			'select': stategroup (
				'this frame' {
					'value': [ $ ] reference
				}
				'parent frame' {
					'tail': [ ^ ] component 'stack selector'
				}
			)
		}
	)
}
'parameters' {
	'values': [ (, ) ] dictionary { [ $ ]
		'has next': stategroup = node-switch successor (
			| node = 'yes' { 'next' = successor }
			| none = 'no'
		)
		'type': [ : ] stategroup (
			'boolean' { [ boolean ] }
			'integer' { [ integer ] }
			'text' { [ text ] }
		)
	}
}
'arguments' {
	'values': [ (, ) ] dictionary { [ $ ]
		'has next': stategroup = node-switch successor (
			| node = 'yes' { 'next' = successor }
			| none = 'no'
		)
		'value': [ = ] component 'value promise'
	}
}
'lambda' { [ lambda ]
	'parameters': component 'parameters'
	'statement': component 'statement'
}
'lambda selector' {
	'step': stategroup (
		'parent' {
			'tail': [ ^ ] component 'lambda selector'
		}
		'this' { }
	)
}
/* target mapping */
/* implementation */
'decimal import rule' {
	'decimal point translation': stategroup (
		'yes' {
			'places': [ << (, ) ] component 'value promise'
		}
		'no' { }
	)
}
'pattern rule piece' {
	'type': stategroup (
		'pattern' {
			'capture': stategroup (
				'yes' { [ $ ] }
				'no' { }
			)
			'type': stategroup (
				'decimal' { [ decimal ]
					'rule': component 'decimal import rule'
				}
				'text' { [ text ] }
			)
		}
		'static' {
			'text': text
		}
	)
	'has tail': stategroup (
		'yes' {
			'tail': component 'pattern rule piece'
		}
		'no' { }
	)
}
'pattern rule' {
	'parts': dictionary {
		'has next': [ : ] stategroup = node-switch successor (
			| node = 'yes' { 'next' = successor }
			| none = 'no'
		)
		'pieces': component 'pattern rule piece'
	}
	'head': reference = first
}
'promise path' {
	'step': stategroup (
		'optional value' { [ get ] }
		'entity lookup' {
			'key': [ [, ] ] component 'promise'
		}
		'file fetch' {
			'field': stategroup (
				'token' { [ .token ] }
				'extension' { [ .extension ] }
			)
		}
		'entity fetch' {
			'field': stategroup (
				'key' { [ .key ] }
				'value' { [ .value ] }
			)
		}
		'https fetch' {
			'field': stategroup (
				'status' { [ .status ] }
				'content' { [ .content ] }
			)
		}
		'node fetch' {
			'property': [ . ] reference
			'sub property': stategroup (
				'yes' {
					'attribute': [ <, > ] reference
				}
				'no' { }
			)
		}
		'interface choice' {
			'state': [ ? ] reference
		}
	)
}
'promise chain' {
	'has step': stategroup (
		'yes' {
			'step': stategroup (
				'path' {
					'step': component 'promise path'
				}
				'complex' { [ => ]
					'type': stategroup (
						/* type conversions */
						'parse' {
							'as': [ parse as ] stategroup (
								'JSON' { [ JSON ]
									/* Parses a JSON object.
									 * On success it results in source-data and must first be passed to a decorator before it is usable.
									 */
								}
								'XML' { [ XML ]
									/* Parses a XML document.
									 * On success it results in source-data and must first be passed to a decorator before it is usable.
									 */
								}
								'ISO Date Time' { [ ISODateTime ]
									/* Parses an ISO-8601 date and time, however it must have at least Seconds accuracy. (source: https://en.wikipedia.org/wiki/ISO_8601)
									 * Combines an ISODate and ISOTime separated with T, but the Date and Time components must both be in the same format.
									 *  Calendar dates + Time: YYYYMMDDThhmmss[.sss ] or YYYY-MM-DDThh:mm:ss[.sss ]
									 *  Week dates + Time: YYYYWwwDThhmmss[.sss ] or YYYY-Www-DThh:mm:ss[.sss ]
									 *  Ordinal dates + Time: YYYYDDDThhmmss[.sss ] or YYYY-DDDThh:mm:ss[.sss ]
									 * In all cases the Time component may contain a Time Zone, when omitted local time is assumed.
									 * On success it results in a Alan DateTime.
									 */
								}
								'ISO Date' { [ ISODate ]
									/* Parses an ISO-8601 date, however it must have Day accuracy. (source: https://en.wikipedia.org/wiki/ISO_8601)
									 *  Calendar dates: YYYYMMDD or YYYY-MM-DD
									 *  Week dates: YYYYWwwD or YYYY-Www-D
									 *  Ordinal dates: YYYYDDD or YYYY-DDD
									 * On success it results in a Alan Date.
									 */
								}
								'ISO Time' { [ ISOTime ]
									/* Parses an ISO-8601 time, however it must have at least Seconds accuracy. (source: https://en.wikipedia.org/wiki/ISO_8601)
									 *  Time: hhmmss[.sss ] or hh:mm:ss[.sss ]
									 *   The fraction separated by a dot is allowed but discarded.
									 *  Time Zone: Z or ±hh or ±hhmm or ±hh:mm
									 *   The timezone is allowed but discarded.
									 * On success it results in the amount of seconds since midnight.
									 */
								}
								'decimal' { [ decimal ]
									/* Parses a decimal value.
									 *  Decimal: [+- ]d[.f ]
									 *   Any number of digits can be provided, but the supported range is limited by the implementation.
									 *   An optional minus or plus sign is allowed before the first digit the set the sign.
									 *   The fraction separated by a dot is allowed and the amount of digits may differ from the `rule`,
									 *   but only the digits specified by `rule` are kept with possibly additional 0 digits introduced when insufficient precision was provided.
									 */
									'rule': component 'decimal import rule'
								}
								'lines' { [ lines ]
									'trim spaces': stategroup (
										'yes' { [ trim, spaces ]
											'locations': stategroup (
												'leading' { [ leading ] }
												'trailing' { [ trailing ] }
												'both' { }
											)
										}
										'no' { }
									)
								}
								'pattern' { [ pattern ]
									'pattern': [ (, ) ] component 'pattern rule'
								}
							)
						}
						'serialize' {
							'as': [ serialize as ] stategroup (
								'JSON' { [ JSON ] }
								'ISO Date Time' { [ ISODateTime ] }
								'ISO Date' { [ ISODate ] }
								'ISO Time' { [ ISOTime ] }
								'decimal' { [ decimal ]
									'rule': component 'decimal import rule'
								}
							)
						}
						'decorate' {
							'schema': [ decorate as ] component 'schema type'
						}
						'https' { [ HTTPS ] dynamic-order
							'method': stategroup (
								'get' { [ GET ] }
								'post' { [ POST ]
									'content': [ (, ) ] component 'promise'
								}
								'put' { [ PUT ]
									'content': [ (, ) ] component 'promise'
								}
							)
							'has parameters': stategroup (
								'yes' { [ parameters: ]
									'parameters': [ (, ) ] dictionary {
										'has next': stategroup = node-switch successor (
											| node = 'yes' { 'next' = successor }
											| none = 'no'
										)
										'value': [ = ] component 'promise'
									}
									'first': reference = first
								}
								'no' { }
							)
							'has custom headers': stategroup (
								'yes' { [ headers: ]
									'headers': [ (, ) ] dictionary {
										'has next': stategroup = node-switch successor (
											| node = 'yes' { 'next' = successor }
											| none = 'no'
										)
										'value': [ : ] component 'promise'
									}
								}
								'no' { }
							)
						}
						/* compute new values */
						'compare' {
							'type': stategroup (
								'equality' { [ is ] }
								'relational' {
									'operator': stategroup (
										'smaller' { [ less-than ] }
										'smaller equal' { [ less-than or is ] }
										'greater' { [ greater-than ] }
										'greater equal' { [ greater-than or is ] }
									)
								}
							)
							'other': [ (, ) ] component 'promise'
						}
						'reduce' {
							'merge': stategroup (
								'value' {
									'merge type': stategroup (
										'shared' { [ shared ] }
										'sum' { [ sum ] }
										'product' { [ product ] }
										'join' { [ join ]
											'separator': stategroup (
												'yes' {
													'value': [ (, ) ] component 'promise'
												}
												'no' { }
											)
										}
										'logical and' { [ and ] }
										'logical or' { [ or ] }
									)
									'for each': [ (, ) ] component 'promise chain'
								}
								'meta' {
									'merge type': stategroup (
										'count' { [ count ] }
									)
								}
								'filter' { [ filter ] }
							)
							'filter': stategroup (
								'yes' {
									'filters': [ (, ) ] dictionary { [ where ]
										'has next': stategroup = node-switch successor (
											| node = 'yes' { 'next' = successor }
											| none = 'no'
										)
										'value': [ => ] component 'promise chain'
									}
								}
								'no' { }
							)
						}
					)
				}
			)
			'tail': component 'promise chain'
		}
		'no' { }
	)
}
'promise' {
	'head': stategroup (
		/* fetch from key-value pair system */
		'variable' {
			'variable': [ var ] reference
		}
		/* static/hardcoded values */
		'static integer' {
			'value': integer
		}
		'static text' {
			'type': stategroup (
				'text' {
					'value': text
				}
				'line break' { [ line-break ] }
				'guid' { [ guid ] }
			)
		}
		'static boolean' {
			'value': stategroup (
				'true' { [ true ] }
				'false' { [ false ] }
			)
		}
		/* fetch from execution state */
		'stored' {
			'selection': component 'stack selector'
		}
		'context' { [ $ ] }
		'captured error' { [ error ] }
		/* compute new values */
		'list merge' {
			'operation': stategroup (
				'sum' { [ sum ] }
				'product' { [ product ] }
				'concatenate' { [ concatenate ]
					'separator': stategroup (
						'yes' {
							'value': component 'promise'
						}
						'no' { }
					)
				}
				'logical and' { [ and ] }
				'logical or' { [ or ] }
			)
			'promises': [ (, ) ] component 'promises'
		}
		'arithmetic' {
			'operation': stategroup (
				'inversion' { [ - ]
					'operand': [ (, ) ] component 'promise'
				}
				'division' { [ division (, ) ]
					'numerator': component 'promise'
					'denominator': [ , ] component 'promise'
				}
			)
		}
		'file constructor' { [ file (, ) ]
			'token': [ token = ] component 'promise'
			'extension': [ extension = ] component 'promise'
		}
	)
	'chain': component 'promise chain'
	'alternative': stategroup (
		'yes' {
			'type': [ || ] stategroup (
				'value' {
					'value': component 'promise'
				}
				'throw' {
					'message': [ throw ] text
				}
			)
		}
		'no' { }
	)
}
'promises' {
	'value': component 'promise'
	'has tail': stategroup (
		'yes' {
			'tail': [ , ] component 'promises'
		}
		'no' { }
	)
}
'value promise' {
	'promise': component 'promise'
}
'target expression' {
	'type': stategroup (
		'node' {
			'properties': [ (, ) ] dictionary {
				'statement': [ = ] component 'statement'
			}
		}
		'entry' { [ create ]
			'implicit key': stategroup (
				'yes' {
					'value': [ [, ] ] component 'value promise'
				}
				'no' { }
			)
			'target': component 'target expression'
		}
		'state' {
			'type': stategroup (
				'interface' { [ create ]
					'state': reference
					'target': component 'target expression'
				}
				'schema' {
					'option': [ option ] reference
				}
			)
		}
		'scalar' {
			'value': component 'value promise'
		}
	)
}
'statement' {
	'type': stategroup (
		/* general statements */
		'block' { [ {, } ]
			'scope': stategroup (
				'yes' {
					'stack block': component 'stack block'
				}
				'no' { }
			)
			'statement': component 'statements'
		}
		'guard' {
			'guarded statement': [ try ] component 'statement'
			'optional assignment': [ catch ] stategroup (
				'yes' { [ as $ ] }
				'no' { }
			)
			'fallback statement': [ => ] component 'statement'
		}
		'condition' {
			'type': stategroup (
				'boolean' {
					'condition': [ match ] component 'value promise'
					'cases': [ (, ) ] group {
						'on true': [ | true => ] component 'statement'
						'on false': [ | false => ] component 'statement'
					}
				}
				'existence' {
					'value': [ any ] component 'promise'
					'cases': [ (, ) ] group {
						'on value': [ | value as $ => ] component 'statement'
						'on error': [ | error => ] component 'statement'
					}
				}
				'switch' {
					'value': [ switch ] component 'value promise'
					'cases': [ (, ) ] dictionary { [ | ]
						'has next': stategroup = node-switch successor (
							| node = 'yes' { 'next' = successor }
							| none = 'no'
						)
						'optional assignment': stategroup (
							'yes' { [ as $ ] }
							'no' { }
						)
						'statement': [ => ] component 'statement'
					}
				}
			)
		}
		'walk' {
			'value': [ walk, as $ ] component 'value promise'
			'statement': [ => ] component 'statement'
		}
		'call' {
			'type': [ call ] stategroup (
				'lambda' {
					'lambda': component 'lambda'
				}
				'recurs' {
					'selector': component 'lambda selector'
				}
			)
			'arguments': [ with ] component 'arguments'
		}
		'no operation' { [ no-op ] }
		'throw' {
			'type': stategroup (
				'captured error' { [ rethrow ] }
				'new error' { [ throw ]
					'message': text
				}
			)
		}
		/* map to target */
		'target' {
			'target': component 'target expression'
		}
		/* change target */
		'execute command' {
			'context': [ execute ] component 'value promise'
			'command': [ : ] reference
			'statement': [ with ] component 'statement'
		}
	)
}
'statements' {
	'statement': component 'statement'
	'has more statements': stategroup (
		'yes' {
			'statement': component 'statements'
		}
		'no' { }
	)
}