template

connector grammar version 39

'prefix': text
'constraints': dictionary { [ where ]
	'has prev': stategroup = node-switch predecessor (
		| node = 'yes' { 'prev' = predecessor }
		| none = 'no'
	)
	'has next': stategroup = node-switch successor (
		| node = 'yes' { 'next' = successor }
		| none = 'no'
	)
	'object': [ -> ] component 'object expression'
	'suffix': text
}
'has constraint': stategroup = node-switch .'constraints' (
	| nodes = 'yes' { 'first' = first }
	| none  = 'no'
)
'root': component 'statement'
'binding' {
	'name': [ as ] stategroup (
		'explicit' {
			'name': reference = first
			'names': dictionary { [ $ ]
				'has successor': stategroup = node-switch successor (
					| node = 'yes' { }
					| none = 'no'
				)
			}
		}
		'implicit' { [ $ ] }
	)
}
'optional binding' {
	'has assignment': stategroup (
		'yes' {
			'binding': component 'binding'
		}
		'no' { }
	)
}
'stack path' {
	'has steps': stategroup (
		'yes' { [ $^ ]
			'tail': component 'stack path'
		}
		'no' { }
	)
}
'binding step' {
	'name': stategroup (
		'explicit' {
			'head': component 'stack path'
			'name': [ $ ] reference
		}
		'implicit' { [ $ ] }
	)
}
'object path step' {
	'type': stategroup (
		'collection' { [ * ] }
		'state' {
			'state': [ ? ] reference
		}
		'reference' {
			'property': [ > ] reference
		}
		'property' {
			'property': [ . ] reference
		}
	)
}
'object path tail' {
	'has step': stategroup (
		'yes' {
			'step': component 'object path step'
			'tail': component 'object path tail'
		}
		'no' { }
	)
}
'object path' {
	'context': stategroup (
		'explicit' {
			'context': stategroup (
				'data constraint' {
					'constraint': [ & ] reference
				}
				'binding' {
					'step': component 'binding step'
				}
				'root' { [ root ] }
				'number' {
					'value': integer
				}
				'text' {
					'value': text
				}
			)
		}
		'implicit' {
			'property': reference
		}
	)
	'steps': component 'object path tail'
}
'object expression' {
	'object': component 'object path'
	'operation': stategroup (
		'lookup' {
			'key': [ [, ] ] component 'text path'
			'tail': component 'object path tail'
		}
		'equality' { [ is ]
			'other': [ (, ) ] stategroup (
				'object' {
					'other object': component 'object path'
				}
				'first' { [ first ] }
				'last' { [ last ] }
			)
		}
		'existence' { }
	)
}
'number path' {
	'object': component 'object path'
}
'text path' {
	'object': component 'object path'
}
'statement' {
	'has statement': stategroup (
		'yes' {
			'type': stategroup (
				'walk' { [ walk ]
					'objects': component 'object path'
					'binding': component 'optional binding'
					'prefix': text
					'statement': component 'statement'
					'suffix': [ /walk ] text
				}
				'state switch' { [ switch ]
					'stategroup': component 'object path'
					'empty': text
					'states': dictionary { [ case ]
						'binding': component 'optional binding'
						'prefix': text
						'statement': component 'statement'
						'empty': [ /case ] text
					}
					'suffix': [ /switch ] text
				}
				'object switch' { [ switch ]
					'object': component 'object expression'
					'empty': text
					'node': [ case node ] group {
						'binding': component 'optional binding'
						'prefix': text
						'statement': component 'statement'
						'empty': [ /case ] text
					}
					'none': stategroup (
						'yes' { [ case none ]
							'prefix': text
							'none': component 'statement'
							'empty': [ /case ] text
						}
						'no' { }
					)
					'suffix': [ /switch ] text
				}
				'format' { [ format ]
					'object': component 'object path'
					'type': stategroup (
						'number' {
							'with base': stategroup (
								'yes' { [ / ]
									'base': component 'number path'
								}
								'no' { }
							)
							'style': stategroup (
								'decimal' { [ decimal ] }
								'currency' { [ currency= ]
									'currency': component 'text path'
								}
								'spellout' { [ spellout ] }
							)
							'styling': dictionary {
								'value': [ = ] stategroup (
									'off' { [ off ] }
									'object' {
										'object': component 'object path'
									}
								)
							}
						}
						'date time' {
							'with time': stategroup (
								'yes' { [ date-time ] }
								'no' { [ date ] }
							)
							'style': stategroup (
								'pattern' { [ style= ]
									/* https://unicode-org.github.io/icu/userguide/format_parse/datetime/#date-field-symbol-table */
									'value': component 'text path'
								}
								'full' { [ style=full ] }
								'long' { [ style=long ] }
								'medium' { [ style=medium ] }
								'short' { [ style=short ] }
							)
							'styling': dictionary {
								'value': [ = ] component 'text path'
							}
						}
					)
					'suffix': text
				}
				'text' {
					'value': component 'text path'
					'escaping': stategroup (
						'default' { }
						'overwrite' {
							'dictionary': [ escape=(, ) ] dictionary {
								'text': [ = ] text
							}
						}
						'none' { [ escape=none ] }
					)
					'suffix': text
				}
			)
			'tail': component 'statement'
		}
		'no' { }
	)
}