The grammar for a subset of XML.
Used https://cs.lmu.edu/~ray/notes/xmlgrammar/ as a reference.
class markup grammar
var markup parser parser
markup grammar(character handler the character handler)
this • the character handler = the character handler
public void add elements(readonly collection[element id] new element ids)
public void add attributes(readonly collection[attribute id] new attribute ids)
public void add entities(readonly collection[special text] new entities)
option matcher[character, attribute fragment] option fragment list(readonly list[matcher[character, attribute fragment]] matchers) pure
option matcher[character, text fragment] option text fragment(readonly list[matcher[character, text fragment]] matchers) pure
option matcher[character, text element] option text element(readonly list[matcher[character, text element]] matchers) pure
option matcher[character, attribute fragment] option fragment(matcher[character, string] attr value, matcher[character, special text] entity ref) pure
return option fragment list([entity ref !> matcher[character, attribute fragment], attr value !> matcher[character, attribute fragment]])
matcher[character, attribute fragment] repeat or none fragment(matcher[character, attribute fragment] the matcher) pure
return repeat matcher[character, attribute fragment, attribute fragment] • new(the matcher, true, join fragments)
matcher[character, text fragment] repeat or none text(matcher[character, text fragment] the matcher) pure
return repeat matcher[character, text fragment, text fragment] • new(the matcher, true, join fragments text)
matcher[character, immutable list[attribute state]] repeat or none attribute(matcher[character, attribute state] the matcher) pure
return repeat matcher[character, immutable list[attribute state], attribute state] • new(the matcher, true, cast attributes)
text element match start element(readonly list[any value] the list) pure
if element id is null
dictionary[attribute id, attribute fragment] attributes dictionary : list dictionary[attribute id, attribute fragment] • new()
for (attribute : attributes)
text element match text element(readonly list[any value] the list) pure
if start tag • get id != text library • ERROR ELEMENT && start tag name != end tag name
parser • report error("Mismatched element name: start " ++ start tag name ++ ", end " ++ end tag name)
special text make entity 2nd(readonly list[any value] the list) pure
attribute fragment select 2nd attribute fragment(readonly list[any value] the list) pure => the list[1] !> attribute fragment
attribute state select 2nd attribute state(readonly list[any value] the list) pure => the list[1] !> attribute state
text element select 2nd text element(readonly list[any value] the list) pure => the list[1] !> text element
protected matcher[character, text element] document()
lt : one character('<')
gt : one character('>')
slash : one character('/')
amp : one character('&')
semicolon : one character(';')
quot : one character('"')
apos : one character('\'')
eq : one character('=')
entity ref = sequence matcher[character, special text] • new([amp, name, semicolon], make entity 2nd)
attribute value in quot = sequence matcher[character, attribute fragment] • new([quot, repeat or none fragment(option fragment(quot attr value, entity ref)), quot], select 2nd attribute fragment)
attribute value in apos = sequence matcher[character, attribute fragment] • new([apos, repeat or none fragment(option fragment(apos attr value, entity ref)), apos], select 2nd attribute fragment)
attribute = sequence matcher[character, attribute state] • new([name, equals, attribute value], make attribute)
attributes : repeat or none attribute(sequence matcher[character, attribute state] • new([space opt, attribute], select 2nd attribute state))
empty element = sequence matcher[character, text element] • new([lt, name, attributes, space opt, slash, gt], match start element)
content element : option text fragment([element fragment, entity ref !> matcher[character, text fragment]])
content tail : repeat or none text(sequence matcher[character, text fragment] • new([content element .> pattern[character], char data opt], join2))
content = sequence matcher[character, text fragment] • new([char data opt, content tail .> pattern[character]], join2)
pattern[character] start tag : sequence matcher[character, text element] • new([lt, name, attributes, space opt, gt], match start element)
end tag : sequence matcher[character, string] • new([lt, slash, name, space opt, gt], select end tag)
element • add option(sequence matcher[character, text element] • new([start tag, content, end tag], match text element))
result : sequence matcher[character, text element] • new([space opt, element, space opt], select 2nd text element)
result • validate()
return result