widget

webclient grammar version uhura.6.0

'binding context': stategroup (
	'none' { [ static ] }
	'select' {
		'binding': [ binding ] reference
		'switch client binding context': stategroup (
			'yes' { [ on ]
				'constrained on containing binding': stategroup (
					'yes' {
						'type path': component 'client binding type path'
						'instance binding': reference
					}
					'no' { [ unconstrained ]
						'instance binding': reference
					}
				)
			}
			'no' { }
		)
	}
)
'widget': component 'widget configuration node'
'optional context definition': component 'optional context definition'
'expression': component 'expression'
'client binding type path' {
	'has steps': stategroup (
		'no' { }
		'yes' {
			'type': stategroup (
				'state' {
					'state group': [ . ] reference
					'state': [ ? ] reference
				}
				'collection' {
					'collection': [ . ] reference
				}
				'binding' {
					'instance binding': reference
				}
			)
			'tail': component 'client binding type path'
		}
	)
}
'configuration attribute persistence' {
	'persist': stategroup (
		'yes' { [ @persist ]
			'per session': stategroup (
				'yes' { [ session ] }
				'no' { }
			)
			'per entry': stategroup (
				'yes' { [ entry ] }
				'no' { }
			)
		}
		'no' { }
	)
}
'optional state HACK' { }
'widget configuration node' { [ {, } ]
	'attributes': dictionary {
		'switch client binding context': stategroup (
			'yes' { [ on ]
				'constrained on containing binding': stategroup (
					'yes' { }
					'no' { [ unconstrained ]
						'instance binding': reference
					}
				)
				'type path': component 'client binding type path'
			}
			'no' { }
		)
		'type': [ : ] stategroup (
			'widget' { [ widget ] }
			'window' { [ window ]
				'node': component 'widget configuration node'
			}
			'view' { [ view ] }
			'configuration' {
				'type': stategroup (
					'number' { [ number ] dynamic-order
						'persistence': component 'configuration attribute persistence'
						'has default': stategroup (
							'yes' { [ default: ]
								'value': integer
							}
							'no' { }
						)
					}
					'text' { [ text ] dynamic-order
						'has default': stategroup (
							'yes' { [ default: ]
								'type': stategroup (
									'static' {
										'value': text
									}
									'unique id' { [ unique-id ] }
								)
							}
							'no' { }
						)
						'persistence': component 'configuration attribute persistence'
					}
					'list' { [ list ]
						'node': component 'widget configuration node'
					}
					'state group' { [ stategroup ] dynamic-order
						'has default': stategroup (
							'yes' { [ default: ]
								'state': reference
							}
							'no' { }
						)
						'persistence': component 'configuration attribute persistence'
						'states': [ (, ) ] dictionary {
							'state default': component 'optional state HACK'
							'node': component 'widget configuration node'
						}
					}
				)
			}
			'binding' { [ binding ]
				'constrained on containing binding': stategroup (
					'yes' {
						'type path': component 'client binding type path'
						'instance binding': reference
					}
					'no' { [ unconstrained ]
						'instance binding': reference
					}
				)
				'node': component 'widget configuration node'
			}
		)
	}
}
'context ancestor path' {
	'has step': stategroup (
		'no' {
			'context': stategroup (
				'implicit' { }
				'anonymous' { [ $ ] }
				'named' {
					'variable name': [ $ ] reference
				}
			)
		}
		'yes' { [ ^ ]
			'tail': component 'context ancestor path'
		}
		'root' { [ root ] }
	)
}
'control binding' {
	'binding type': stategroup (
		'let declaration' {
			'path': component 'context ancestor path'
			'declaration': [ @ ] reference
		}
		'static' {
			'control': [ control ] reference
			'node binding': component 'widget implementation node'
		}
		'window' {
			'window': [ window ] reference
			'variable': [, => ] component 'variable'
			'control binding': component 'control binding'
		}
		'widget' {
			'context': component 'context selection'
			'widget': [ widget ] reference
		}
		'client binding widget' {
			'context': [ binding widget ] component 'context selection'
		}
	)
}
'context selection' {
	'change context to': stategroup (
		'engine state' { [ engine ]
			'engine state binding': reference
		}
		'other context' {
			'ancestor path': component 'context ancestor path'
			'path': component 'context selection path'
		}
	)
}
'context selection path' {
	'has steps': stategroup (
		'no' { }
		'yes' {
			'type': stategroup (
				'unconstrained configuration attribute' {
					'configuration attribute': [ unconstrained :: ] reference
				}
				'constrained configuration attribute' {
					'configuration attribute': [ :: ] reference
				}
				'client binding' {
					'binding': [ / ] reference
				}
			)
			'tail': component 'context selection path'
		}
	)
}
'instruction selection' {
	'context': component 'context selection'
	'configuration attribute type': stategroup (
		'binding' {
			'instruction': [ >> ] reference
			'has arguments': stategroup (
				'no' { }
				'yes' {
					'first argument': [ (, ) ] component 'instruction argument'
				}
			)
		}
		'configuration' {
			'instruction': stategroup (
				'set state' { [ set state ]
					'state group': reference
					'state': [ : ] reference
					'node': component 'instruction argument configuration node'
				}
				'set number' { [ set number ]
					'number': reference
					'argument': [ = ] component 'number argument'
				}
				'set text' { [ set text ]
					'text': reference
					'argument': [ = ] component 'text argument'
				}
			)
		}
	)
}
'instruction argument' {
	'type': stategroup (
		'number' { [ number ]
			'argument': component 'number argument'
		}
		'text' { [ text ]
			'argument': component 'text argument'
		}
		'file' { [ file ] }
		'view' { [ view ]
			'context': component 'context selection'
			'view configuration': reference
		}
	)
	'next argument': stategroup (
		'no' { }
		'exists' { [ , ]
			'argument': component 'instruction argument'
		}
	)
}
'instruction argument configuration node' { [ (, ) ]
	'attributes': dictionary {
		'type': stategroup (
			'configuration' {
				'type': [ : ] stategroup (
					'number' { [ number ]
						'argument': [ = ] component 'number argument'
					}
					'text' { [ text ]
						'argument': [ = ] component 'text argument'
					}
					'state group' { [ state ]
						'state': reference
						'node': component 'instruction argument configuration node'
					}
				)
			}
		)
	}
}
'widget implementation attribute' {
	'expression': [ = ] component 'one or more expression'
}
'widget implementation node' { [ {, } ]
	'attributes': dictionary {
		'attribute': component 'widget implementation attribute'
	}
}
'expression list' {
	'optional context definition': component 'optional context definition'
	'expression': component 'expression'
	'has next': stategroup (
		'yes' {
			'next': [ , ] component 'expression list'
		}
		'no' { }
	)
}
'one or more expression' {
	'multiplicity': stategroup (
		'singular' {
			'expression': component 'expression'
		}
		'plural' {
			'expression': [ [, ] ] component 'expression list'
		}
	)
}
'variable' {
	'context': component 'context selection'
	'identifier': [ as $ ] stategroup (
		'anonymous' { }
		'named' {
			'named values': dictionary {
				'has successor': stategroup = node-switch successor (
					| node = 'yes' { }
					| none = 'no'
				)
			}
			'name': reference = first
		}
	)
	'let declarations': component 'let declarations'
}
'let declarations' {
	'let declarations': dictionary { [ let ]
		'expression': [ : ] component 'expression'
	}
}
'optional context definition' {
	'define context': stategroup (
		'yes' {
			'variable': [ define context, => ] component 'variable'
		}
		'no' { }
	)
}
'variable assignment' {
	'assign': stategroup (
		'yes' {
			'variable': component 'variable'
		}
		'no' { }
	)
}
'expression' {
	'type': stategroup (
		'control' {
			'control binding': component 'control binding'
		}
		'node switch' { [ switch ]
			'context': component 'context selection'
			'from': stategroup (
				'collection' {
					'collection': [ . ] reference
					'key': [ [, ] ] component 'scalar'
				}
				'list' {
					'list': [ . :: ] reference
					'index': [ [, ] ] component 'scalar'
				}
			)
			'cases': [ (, ) ] group {
				'variable assignment': [ | node ] component 'variable assignment'
				'node': [ => ] component 'one or more expression'
				'none': [ | none => ] component 'one or more expression'
			}
		}
		'switch' { [ switch ]
			'context': component 'context selection'
			'type': stategroup (
				'configuration' {
					'state group': [ . :: ] reference
					'states': [ (, ) ] dictionary { [ | ]
						'variable assignment': component 'variable assignment'
						'next': [ => ] component 'one or more expression'
					}
				}
				'binding' {
					'property': [ . ] reference
					'states': [ (, ) ] dictionary { [ | ]
						'variable assignment': component 'variable assignment'
						'next': [ => ] component 'one or more expression'
					}
				}
			)
		}
		'match' { [ match ]
			'type': stategroup (
				'text' { [ text ]
					'left expression': component 'scalar'
					'right expression': [ == ] component 'scalar'
				}
				'number' { [ number ]
					'left expression': component 'scalar'
					'right expression': [ == ] component 'scalar'
				}
			)
			'cases': [ (, ) ] group {
				'true': [ | true => ] component 'one or more expression'
				'false': [ | false => ] component 'one or more expression'
			}
		}
		'walk' { [ walk ]
			'context': component 'context selection'
			'type': stategroup (
				'configuration' {
					'list': [ . :: ] reference
				}
				'widget binding' {
					'collection property': [ . ] reference
					'sort': stategroup (
						'yes' { [ sort by ]
							'by': [ (, ) ] component 'expression'
						}
						'no' { }
					)
				}
			)
			'variable': component 'variable'
			'entry expression': [ => ] component 'one or more expression'
		}
		'create entry' {
			'for': stategroup (
				'state' {
					'state': reference
				}
				'control node' { }
			)
			'node': component 'widget implementation node'
		}
		'none' { [ none ] }
		'instruction' {
			'instruction': component 'instruction selection'
		}
		'sort collection' {
			'context': component 'context selection'
			'direction': stategroup (
				'ascending' { [ ascending ] }
				'descending' { [ descending ] }
			)
		}
		'scalar' {
			'value': component 'scalar'
		}
	)
}
'number argument' {
	'expression': component 'expression'
}
'text argument' {
	'expression': component 'expression'
}
'scalar' {
	'binding type': stategroup (
		'static text' {
			'text': text
		}
		'phrase' {
			'phrase': reference
		}
		'configuration' {
			'context': component 'context selection'
			'type': stategroup (
				'text' { [ . ] }
				'number' { [ # ] }
			)
			'attribute': [ :: ] reference
		}
		'event' {
			'type': stategroup (
				'text' { [ argument ] }
				'number' { [ # argument ] }
			)
		}
		'binding' {
			'context': component 'context selection'
			'type': stategroup (
				'key' { [ .key ] }
				'property' {
					'type': stategroup (
						'text' { [ . ] }
						'reference' { [ > ] }
						'number' { [ # ] }
					)
					'property': reference
				}
			)
		}
		'static number' {
			'value': integer
		}
		'unary expression' {
			'type': stategroup (
				'absolute value' { [ abs ] }
				'sign inversion' { [ - ] }
			)
			'value': [ (, ) ] component 'scalar'
		}
		'list expression' {
			'operation': stategroup (
				'sum' { [ sum ] }
				'minimum' { [ min ] }
				'maximum' { [ max ] }
				'product' { [ product ] }
			)
			'value': [ (, ) ] component 'one or more expression'
		}
		'current time' { [ current time ]
			'throttle': stategroup (
				'yes' {
					'interval': [ interval: ] integer
				}
				'no' { }
			)
		}
		'list index' {
			'context': [, index ] component 'context selection'
		}
	)
	'transform': stategroup (
		'no' { }
		'yes' { [ transform ]
			'transformer': reference
		}
	)
	'format': stategroup (
		'no' { }
		'yes' { [ format ]
			'formatter': reference
		}
	)
}