Structural 3.0.0 Language Specification ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Contents ───────────────────────────────────────────────────────────────────────────── 1 Notational Conventions ........................................ conventions 1.1 Unicode ........................................... conventions.unicode 1.2 EBNF ................................................. conventions.ebnf 1.3 Haskell ........................................... conventions.haskell 1.4 S-Expressions ...................................... conventions.sexprs 1.5 S-Expression Metasyntax ................................ fmt_canon.meta 2 Model ............................................................... model 2.1 Overview ............................................... model.overview 2.2 Inline Content ........................................... model.inline 2.3 Block Content ............................................. model.block 3 Canonical Format ................................................ fmt_canon 3.1 Overview ........................................... fmt_canon.overview 3.2 Inline Elements ..................................... fmt_canon.inlines 3.3 Block Elements ....................................... fmt_canon.blocks 4 Imperative Format ................................................. fmt_imp 4.1 Overview ............................................. fmt_imp.overview 4.2 Block Commands ......................................... fmt_imp.blocks 5 XML Format ........................................................ fmt_xml 5.1 Overview ............................................. fmt_xml.overview 5.2 RELAX-NG Schema ........................................ fmt_xml.schema 1 Notational Conventions [id: conventions] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Contents ───────────────────────────────────────────────────────────────────────────── 1.1 Unicode ............................................. conventions.unicode 1.2 EBNF ................................................... conventions.ebnf 1.3 Haskell ............................................. conventions.haskell 1.4 S-Expressions ........................................ conventions.sexprs 1.5 S-Expression Metasyntax .................................. fmt_canon.meta 1.5.1 Overview ............................................................ 1.5.2 Rules ............................................................... 1.5.3 Examples ............................................................ 1.1 Unicode [id: conventions.unicode] 1 The specification makes reference to the Unicode character set which, at the time of writing, is at version 8.0.0. The specification often references specific Unicode characters, and does so using the standard notation U+NNNN, where N represents a hexadecimal digit. For example, U+03BB corresponds to the lowercase lambda symbol λ. 1.2 EBNF [id: conventions.ebnf] 1 The specification gives grammar definitions in ISO/IEC 14977:1996 Extended Backus-Naur form. 1.3 Haskell [id: conventions.haskell] 1 Rather than rely on untyped and ambiguous mathematical notation, this documentation expresses all mathematics and type definitions in strict Haskell 2010 [url: http://www.haskell.org/onlinereport/haskell2010/] with no extensions. All Haskell sources are included along with the documentation and can therefore be executed from the command line GHCi [url: http://www.haskell.org/haskellwiki/GHC/GHCi] tool in order to interactively check results and experiment with functions. 2 When used within prose, functions are referred to using fully qualified notation, such as (Vector3f.cross n t). This is the application of the cross function defined in the Vector3f module, to the arguments n and t. 1.4 S-Expressions [id: conventions.sexprs] 1 An s-expression is defined by the following grammar: 1.4.2 S-Expression Grammar ────────────────────────── expression = symbol | quoted_string | "[" , { expression } , "]" | "(" , { expression } , ")" ; 3 The sequences U+000D U+000A and U+000A are recognized as line terminators for the purposes of tracking line and column numbers for diagnostic messages. Bare U+000D characters are not permitted to appear outside of quoted strings. 4 The terminals of the grammar are given as: 1.4.5 S-Expression Grammar ────────────────────────── symbol_character = ? not (")" | "(" | "[" | "]" | U+0022 | WHITESPACE) ? ; symbol = symbol_character , { symbol_character } ; quoted_character = ? not U+0022 ? ; quoted_string = U+0022 , (quoted_character | escape) , { (quoted_character | escape) } , U+0022 ; escape = escape_carriage | escape_newline | escape_tab | escape_quote | escape_unicode4 | escape_unicode8 ; escape_carriage = "\r" ; escape_newline = "\n" ; escape_quote = "\" , U+0022 ; escape_tab = "\t" ; escape_unicode4 = "\u" , hex_digit , hex_digit , hex_digit , hex_digit ; escape_unicode8 = "\u" , hex_digit , hex_digit , hex_digit , hex_digit , hex_digit , hex_digit , hex_digit , hex_digit ; hex_digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0" | "a" | "A" | "b" | "B" | "c" | "C" | "d" | "D" | "e" | "E" | "f" | "F" ; 6 Due to limitations in the EBNF [url: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form] format, the definitions for symbol_character and quoted_character cannot be expressed directly. Informally, the symbol_character rule should be understood to specify any Unicode character that is not whitespace, is not U+0028 (, is not U+0029 ), and is not U+0022 ". 1.5 S-Expression Metasyntax [id: fmt_canon.meta] 1.5.1 Overview 1 Because no formal standard exists to describe the actual structure of parsed s-expressions, a small language is introduced here to describe the forms used to describe the document elements specified later on in this publication. The syntax of the syntax rules are themselves given as s-expressions, and to avoid an infinite regression problem akin to trying to specify EBNF using EBNF itself, the language here is described informally with an executable Haskell specification [SEMatcher.hs] [url: SEMatcher.hs] to make the semantics clear where English cannot. 1.5.2 Rules 1 A rule may take one of the following forms: 1.5.2.2 Rules ───────────── data Rule = MAnySymbol | MAnyQuoted | MAnyList | MExactSymbol String | MExactQuoted String | MExactList [Rule] | MChoice [Rule] | MListVariadic [Rule] Rule deriving Eq 3 The s-expression syntax of each rule may be inferred from the given Show instance: 1.5.2.4 Rule Syntax ─────────────────── instance Show Rule where show (MExactSymbol s) = "(#exact-symbol " ++ s ++ ")" show (MExactQuoted s) = "(#exact-quoted " ++ s ++ ")" show (MExactList s) = "(#exact-list [" ++ (concatMap show s) ++ "])" show MAnySymbol = "#any-symbol" show MAnyQuoted = "#any-quoted" show MAnyList = "#any-list" show (MChoice s) = "(#choice [" ++ (concatMap show s) ++ "])" show (MListVariadic s m) = "(#variadic [" ++ (concatMap show s) ++ "]" ++ (show m) ++ ")" 5 A rule is r said to match an expression e if, given the matches function defined below, matches e r == True. 1.5.2.6 Informal Description Of Rules ───────────────────────────────────── • The #any-symbol rule matches an expression e iff e is a symbol. • The #any-quoted rule matches an expression e iff e is a quoted string. • The #any-list rule matches an expression e iff e is a list. • The (#exact-symbol s) rule matches an expression e iff e is a symbol with the value s. • The (#exact-quoted s) rule matches an expression e iff e is a quoted string with the value s. • The (#exact-list (m₀ m₁ ... mₙ)) rule matches an expression e iff e is a list, the length of e is n + 1, and ∀k. 0 <= k <= n → e[k] matches mₖ. • The (#choice (m₀ ... mₙ)) rule matches an expression e iff exactly one rule in the given list (m₀ ... mₙ) matches e. Accordingly, the rule (#choice ()) never matches anything. • The (#variadic (m₀ m₁ ... mₙ) r) rule matches an expression e iff e is a list, the length of e is >= n + 1, ∀k. 0 <= k <= n → e[k] matches mₖ, and the remaining elements in e match r. Accordingly, the rule (#variadic () r) will check that every element of a given list matches r, and will always match for a given empty list. 7 Matching an arbitrary s-expression against a rule is a simple matter of checking to see if the structure of the given expression matches the structure allowed by the rule against which it is being matched. A complete definition of a matching function that encodes the above rules is as follows: 1.5.2.8 Match Function ────────────────────── matches :: SE.Expr -> Rule -> Bool matches (SE.ESymbol e) (MExactSymbol s) = e == s matches (SE.ESymbol _) (MExactQuoted _) = False matches (SE.ESymbol _) (MExactList _) = False matches (SE.ESymbol _) MAnySymbol = True matches (SE.ESymbol _) MAnyQuoted = False matches (SE.ESymbol _) MAnyList = False matches (SE.ESymbol _) (MListVariadic _ _) = False matches (SE.EQuoted _) MAnySymbol = False matches (SE.EQuoted _) MAnyQuoted = True matches (SE.EQuoted _) MAnyList = False matches (SE.EQuoted e) (MExactQuoted s) = e == s matches (SE.EQuoted _) (MExactSymbol _) = False matches (SE.EQuoted _) (MExactList _) = False matches (SE.EQuoted _) (MListVariadic _ _) = False matches (SE.EList _) (MExactSymbol _) = False matches (SE.EList _) (MExactQuoted _) = False matches (SE.EList _) MAnySymbol = False matches (SE.EList _) MAnyQuoted = False matches (SE.EList _) MAnyList = True matches (SE.EList s) (MExactList m) = (length s) == (length m) && all (\(xe,xm) -> matches xe xm) (zip s m) matches (SE.EList s) (MListVariadic m0 mr) = if (length s >= length m0) then let prefix_zip = take (length m0) (zip s m0) prefix_ok = all (\(xe,xm) -> matches xe xm) prefix_zip suffix = drop (length m0) s suffix_zip = zip suffix (replicate (length suffix) mr) suffix_ok = all (\(xe,xm) -> matches xe xm) suffix_zip in prefix_ok && suffix_ok else False matches e (MChoice m0)= 1 == length (filter (matches e) m0) 1.5.3 Examples 1 This section is informative. These results can be reproduced by evaluating the given terms in the SEMatcher module using Haskell's interactive command prompt. 2 The expression x is matched by the rule #any-symbol, but "x" is not: 1.5.3.3 Example 0 ───────────────── > matches (SE.ESymbol "x") MAnySymbol True > matches (SE.EQuoted "x") MAnySymbol False 4 The expression (x y z) is matched by the rule (#exact-list (#exact-symbol "x") (#exact-symbol "y") (#exact-symbol "z")), but (x y y) and (x y) are not: 1.5.3.5 Example 1 ───────────────── > matches (SE.EList [SE.ESymbol "x", SE.ESymbol "y", SE.ESymbol "z"]) (MExactList [MExactSymbol "x", MExactSymbol "y", MExactSymbol "z"]) True > matches (SE.EList [SE.ESymbol "x", SE.ESymbol "y", SE.ESymbol "y"]) (MExactList [MExactSymbol "x", MExactSymbol "y", MExactSymbol "z"]) False > matches (SE.EList [SE.ESymbol "x", SE.ESymbol "y"]) (MExactList [MExactSymbol "x", MExactSymbol "y", MExactSymbol "z"]) False 2 Model [id: model] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Contents ───────────────────────────────────────────────────────────────────────────── 2.1 Overview ................................................. model.overview 2.2 Inline Content ............................................. model.inline 2.2.1 Overview ...................................... model.inline.overview 2.2.2 Types ............................................ model.inline.types 2.2.3 Text .............................................. model.inline.text 2.2.4 Term .............................................. model.inline.term 2.2.5 Image ............................................ model.inline.image 2.2.6 Verbatim ...................................... model.inline.verbatim 2.2.7 Link .............................................. model.inline.link 2.2.8 Link External ............................ model.inline.link_external 2.2.9 Footnote Reference ........................ model.inline.footnote_ref 2.2.10 Ordered List ............................. model.inline.list_ordered 2.2.11 Unordered List ......................... model.inline.list_unordered 2.2.12 Table ........................................... model.inline.table 2.2.13 Include ....................................... model.inline.include 2.2.14 Complete Inline Model ........................ model.inline.complete 2.3 Block Content ............................................... model.block 2.3.1 Overview ....................................... model.block.overview 2.3.2 ID ................................................... model.block.id 2.3.3 Paragraph ..................................... model.block.paragraph 2.3.4 Formal Item ................................. model.block.formal_item 2.3.5 Footnote ....................................... model.block.footnote 2.3.6 Subsection ................................... model.block.subsection 2.3.7 Section ......................................... model.block.section 2.3.8 Part ............................................... model.block.part 2.3.9 Document ....................................... model.block.document 2.3.10 Import .......................................... model.block.import 2.1 Overview [id: model.overview] 1 The definition of the structural language is given as an algebraic data type. Later parts of the specification define the concrete syntax that maps text to terms of the described types. 2 A structural document consists of nested block [ref: model.block] terms that, at the lowest level, contain inline [ref: model.inline] terms. 2.2 Inline Content [id: model.inline] 2.2.1 Overview [id: model.inline.overview] 1 An inline value is the smallest unit of content that can appear in a structural document. The type of inline content is given by the following definition: 2.2.1.2 Inline Content ────────────────────── data InlineContent = ICText InlineText | ICTerm InlineTerm | ICImage InlineImage | ICVerbatim InlineVerbatim | ICLink InlineLinkInternal | ICLinkExternal InlineLinkExternal | ICListOrdered InlineListOrdered | ICListUnordered InlineListUnordered | ICFootnoteRef InlineFootnoteRef | ICTable InlineTable | ICInclude InlineInclude deriving Eq 2.2.2 Types [id: model.inline.types] 1 Most elements defined here may have an associated type parameter that can be used to distinguish the element from other elements of the same type during document processing. As an example, the author of a document may tag all mentions of a software package with a type parameter value of package so that the mentions can be highlighted when the document is exported to one of the supported export formats. The values have no intrinsic meaning; their meaning is decided by the author of any given document. 2 Type identifiers are restricted to combinations of letters, numbers, and U+005F "_". 2.2.2.3 Type Identifier Syntax ────────────────────────────── type_character = ? p{IsLetter} | p{isNumber} | U+005F ? ; type = type_character , { type_character } ; 2.2.3 Text [id: model.inline.text] 1 The simplest type of inline content that appears in structural documents is the InlineText type. Terms of type InlineText are simply strings. 2.2.3.2 Text ──────────── data InlineText = InlineText String deriving Eq 2.2.4 Term [id: model.inline.term] 1 The InlineTerm type denotes a significant element of a section of text. It is usually used to highlight or mark individual words. 2.2.4.2 Term ──────────── data InlineTerm = InlineTerm { termType :: Maybe String, termContent :: [InlineText] } deriving Eq 3 As shown by the type definition, values of type InlineTerm may have an associated optional type [ref: model.inline.types] parameter value. 2.2.5 Image [id: model.inline.image] 1 The InlineImage type denotes a reference to an image. The location of the image is given by the target parameter. The width and height of the image can be specified by the optional size parameter. The associated list of inline text [ref: model.inline.text] elements are used as fallback text in the case that the image becomes unavailable. 2.2.5.2 Text ──────────── data InlineImage = InlineImage { imageType :: Maybe String, imageTarget :: URI.T, imageSize :: Maybe Size, imageContent :: [InlineText] } deriving Eq 3 As shown by the type definition, values of type InlineImage may have an associated optional type [ref: model.inline.types] parameter value. 2.2.6 Verbatim [id: model.inline.verbatim] 1 The InlineVerbatim type denotes a section of text in which whitespace should be preserved exactly as it was written. 2.2.6.2 Verbatim ──────────────── data InlineVerbatim = InlineVerbatim { verbatimType :: Maybe String, verbatimContent :: InlineText } deriving Eq 3 As shown by the type definition, values of type InlineVerbatim may have an associated optional type [ref: model.inline.types] parameter value. 2.2.7 Link [id: model.inline.link] 1 The InlineLinkInternal type denotes a link to an element within the current document. The value of the given target parameter must be equal to the value of the id parameter on an existing block [ref: model.block] value. 2.2.7.2 Link ──────────── data InlineLinkInternal = InlineLinkInternal { linkInternalTarget :: ID.T, linkInternalContent :: [LinkContent] } deriving Eq 3 Only a restricted subset of the available inline content types are allowed to appear as descendants of links. The subset is described by the LinkContent type: 2.2.7.4 Link Content ──────────────────── data LinkContent = LCText InlineText | LCImage InlineImage deriving Eq 2.2.8 Link External [id: model.inline.link_external] 1 The InlineLinkExternal type denotes a link to an external resource. 2.2.8.2 Link External ───────────────────── data InlineLinkExternal = InlineLinkExternal { linkExternalTarget :: URI.T, linkExternalContent :: [LinkContent] } deriving Eq 2.2.9 Footnote Reference [id: model.inline.footnote_ref] 1 The InlineFootnoteRef type denotes a link to a footnote [ref: model.block.footnote] within the current document. 2 The value of the given target parameter must be equal to the value of the id parameter on an existing footnote [ref: model.block.footnote] value. 2.2.9.3 Footnote Reference ────────────────────────── data InlineFootnoteRef = InlineFootnoteRef { footnoteTarget :: ID.T } deriving Eq 2.2.10 Ordered List [id: model.inline.list_ordered] 1 The InlineListOrdered type denotes a list of elements that should be understood to be ordered. The individual elements of the list are denoted by values of the ListItem type. 2.2.10.2 Ordered List ───────────────────── data ListItem = ListItem { listItemContent :: [InlineContent] } deriving Eq 2.2.10.3 Ordered List ───────────────────── data InlineListOrdered = InlineListOrdered { listOrderedItems :: [ListItem] } deriving Eq 2.2.11 Unordered List [id: model.inline.list_unordered] 1 The InlineListUnordered type denotes a list of elements that should be understood to be in no specific order. 2.2.11.2 Unordered List ─────────────────────── data InlineListUnordered = InlineListUnordered { listUnorderedItems :: [ListItem] } deriving Eq 2.2.12 Table [id: model.inline.table] 1 The InlineTable type is a relatively complex type that describes a table consisting of rows, with each row consisting of a number of cells. 2.2.12.2 Table Cell ─────────────────── data TableCell = TableCell { tableCellContent :: [TableCellContent] } deriving Eq 2.2.12.3 Table Row ────────────────── data TableRow = TableRow { tableRowCells :: [TableCell] } deriving Eq 2.2.12.4 Table ────────────── data InlineTable = InlineTable { tableType :: Maybe String, tableSummary :: [InlineText], tableHead :: Maybe TableHead, tableBody :: TableBody } deriving Eq 5 A table may have an optional head that describes the number and names of columns in the table. 2.2.12.6 Table Head ─────────────────── data TableRow = TableRow { tableRowCells :: [TableCell] } deriving Eq 7 Implementations are required to check that, if a head is defined, the number of cells in each table row is equal to the number of column names defined in the head. 2.2.12.8 Table Check ──────────────────── tableCheck :: InlineTable -> Bool tableCheck table = case (tableHead table) of Nothing -> True Just th -> let rows = tableBodyRows $ tableBody table expected = length $ tableHeadNames th in all (\row -> length (tableRowCells row) == expected) rows 9 Tables may not be nested. That is, the inline content that may appear inside a table cell must not contain a table. 2.2.12.10 Table Cell Content ──────────────────────────── data TableCellContent = TCText InlineText | TCTerm InlineTerm | TCImage InlineImage | TCVerbatim InlineVerbatim | TCLink InlineLinkInternal | TCLinkExternal InlineLinkExternal | TCListOrdered InlineListOrdered | TCListUnordered InlineListUnordered | TCFootnoteRef InlineFootnoteRef | TCInclude InlineInclude deriving Eq 2.2.13 Include [id: model.inline.include] 1 The InlineInclude type denotes a link to an external file. Values of type InlineInclude do not actually appear in documents directly: They are replaced with the contents of the referenced file as if they had been inserted as a single quoted string. 2.2.13.2 Include ──────────────── data InlineInclude = InlineInclude { includeFile :: String } deriving Eq 2.2.14 Complete Inline Model [id: model.inline.complete] 2.2.14.1 Type Model ─────────────────── module InlineContent where import qualified URI import qualified ID data InlineText = InlineText String deriving Eq data InlineTerm = InlineTerm { termType :: Maybe String, termContent :: [InlineText] } deriving Eq data Size = Size { sizeWidth :: Integer, sizeHeight :: Integer } deriving Eq data InlineImage = InlineImage { imageType :: Maybe String, imageTarget :: URI.T, imageSize :: Maybe Size, imageContent :: [InlineText] } deriving Eq data InlineVerbatim = InlineVerbatim { verbatimType :: Maybe String, verbatimContent :: InlineText } deriving Eq data LinkContent = LCText InlineText | LCImage InlineImage deriving Eq data InlineLinkInternal = InlineLinkInternal { linkInternalTarget :: ID.T, linkInternalContent :: [LinkContent] } deriving Eq data InlineLinkExternal = InlineLinkExternal { linkExternalTarget :: URI.T, linkExternalContent :: [LinkContent] } deriving Eq data ListItem = ListItem { listItemContent :: [InlineContent] } deriving Eq data InlineListOrdered = InlineListOrdered { listOrderedItems :: [ListItem] } deriving Eq data InlineListUnordered = InlineListUnordered { listUnorderedItems :: [ListItem] } deriving Eq data InlineFootnoteRef = InlineFootnoteRef { footnoteTarget :: ID.T } deriving Eq type TableColumnName = [InlineText] data TableHead = TableHead { tableHeadNames :: [TableColumnName] } deriving Eq data TableCell = TableCell { tableCellContent :: [TableCellContent] } deriving Eq data TableCellContent = TCText InlineText | TCTerm InlineTerm | TCImage InlineImage | TCVerbatim InlineVerbatim | TCLink InlineLinkInternal | TCLinkExternal InlineLinkExternal | TCListOrdered InlineListOrdered | TCListUnordered InlineListUnordered | TCFootnoteRef InlineFootnoteRef | TCInclude InlineInclude deriving Eq data TableRow = TableRow { tableRowCells :: [TableCell] } deriving Eq data TableBody = TableBody { tableBodyRows :: [TableRow] } deriving Eq data InlineTable = InlineTable { tableType :: Maybe String, tableSummary :: [InlineText], tableHead :: Maybe TableHead, tableBody :: TableBody } deriving Eq tableCheck :: InlineTable -> Bool tableCheck table = case (tableHead table) of Nothing -> True Just th -> let rows = tableBodyRows $ tableBody table expected = length $ tableHeadNames th in all (\row -> length (tableRowCells row) == expected) rows data InlineInclude = InlineInclude { includeFile :: String } deriving Eq data InlineContent = ICText InlineText | ICTerm InlineTerm | ICImage InlineImage | ICVerbatim InlineVerbatim | ICLink InlineLinkInternal | ICLinkExternal InlineLinkExternal | ICListOrdered InlineListOrdered | ICListUnordered InlineListUnordered | ICFootnoteRef InlineFootnoteRef | ICTable InlineTable | ICInclude InlineInclude deriving Eq 2.3 Block Content [id: model.block] 2.3.1 Overview [id: model.block.overview] 1 A block value denotes a significant section of content within a document. 2.3.2 ID [id: model.block.id] 1 All block values have an optional id parameter that, if present, must be unique within a document. The value of this parameter may be used by link [ref: model.inline.link] elements to create intra-document links to content. 2 Identifiers are restricted to combinations of letters, numbers, U+005F "_", U+002D "-", and U+002E ".". 2.3.2.3 Identifier Syntax ───────────────────────── id_character = ? p{IsLetter} | p{isNumber} | U+005F | U+002D | U+002E ? ; id = id_character , { id_character } ; 4 An id value k is said to exist if there is exactly one element in the document d such that (hasID k d == Just k): 2.3.2.5 Identifier Existence ──────────────────────────── module IDExistence where import qualified ID import qualified BlockContent as BC import qualified Control.Monad as CM class HasID a where hasID :: ID.T -> a -> Maybe ID.T maybeEq :: Eq a => a -> Maybe a -> Maybe a maybeEq x Nothing = Nothing maybeEq x (Just y) = if x == y then Just y else Nothing instance HasID BC.BlockParagraph where hasID k b = maybeEq k (BC.para_id b) instance HasID BC.BlockFormalItem where hasID k b = maybeEq k (BC.formal_id b) instance HasID BC.BlockFootnote where hasID k b = maybeEq k (Just $ BC.footnote_id b) instance HasID BC.SubsectionContent where hasID k (BC.SCParagraph b) = hasID k b hasID k (BC.SCFormalItem b) = hasID k b hasID k (BC.SCFootnote b) = hasID k b instance HasID BC.BlockSubsection where hasID k b = case maybeEq k (BC.subsection_id b) of Just x -> Just k Nothing -> CM.foldM hasID k (BC.subsection_content b) instance HasID BC.BlockSection where hasID k b = case maybeEq k (BC.section_id b) of Just x -> Just k Nothing -> case BC.section_content b of Left ss -> CM.foldM hasID k ss Right sc -> CM.foldM hasID k sc instance HasID BC.BlockPart where hasID k b = case maybeEq k (BC.part_id b) of Just x -> Just k Nothing -> CM.foldM hasID k (BC.part_content b) instance HasID BC.BlockDocument where hasID k b = case maybeEq k (BC.document_id b) of Just x -> Just k Nothing -> case BC.document_content b of Left p -> CM.foldM hasID k p Right s -> CM.foldM hasID k s 6 Implementations are required to check that all id values are unique within a document, and that all id values referenced by links within a document exist. 2.3.3 Paragraph [id: model.block.paragraph] 1 A paragraph is one of the lowest level block values in terms of structural significance. It is simply a container for inline [ref: model.inline] content. 2.3.3.2 Paragraph ───────────────── data BlockParagraph = BlockParagraph { para_type :: Maybe String, para_id :: Maybe ID.T, para_content :: [I.InlineContent] } 2.3.4 Formal Item [id: model.block.formal_item] 1 A formal-item is similar to a paragraph [ref: model.block.paragraph] except that it has an explicit title. 2.3.4.2 Formal Item ─────────────────── data BlockFormalItem = BlockFormalItem { formal_type :: Maybe String, formal_id :: Maybe ID.T, formal_title :: [I.InlineText], formal_content :: [I.InlineContent] } 2.3.5 Footnote [id: model.block.footnote] 1 A footnote is similar to a paragraph [ref: model.block.paragraph] except that it denotes content that should appear as supplemental information at the bottom of a page when the document is processed for presentation. 2 A footnote must have an id value specified, and may be referenced by any number of footnote-ref [ref: model.inline.footnote_ref] values. 2.3.5.3 Footnote ──────────────── data BlockFootnote = BlockFootnote { footnote_type :: Maybe String, footnote_id :: ID.T, footnote_content :: [I.InlineContent] } 2.3.6 Subsection [id: model.block.subsection] 1 A subsection is a container for subsection content. A subsection is required to have a title. 2.3.6.2 Subsection Content ────────────────────────── data SubsectionContent = SCParagraph BlockParagraph | SCFormalItem BlockFormalItem | SCFootnote BlockFootnote 2.3.6.3 Subsection ────────────────── data BlockSubsection = BlockSubsection { subsection_type :: Maybe String, subsection_id :: Maybe ID.T, subsection_title :: [I.InlineText], subsection_content :: [SubsectionContent] } 2.3.7 Section [id: model.block.section] 1 A section is a container for either subsection content [ref: model.block.subsection.content], or subsections [ref: model.block.subsection], but not both at the same time. A section is required to have a title. 2.3.7.2 Section ─────────────── data BlockSection = BlockSection { section_type :: Maybe String, section_id :: Maybe ID.T, section_title :: [I.InlineText], section_content :: Either [BlockSubsection] [SubsectionContent] } 2.3.8 Part [id: model.block.part] 1 A part is a container for sections [ref: model.block.section]. A part is required to have a title. 2.3.8.2 Part ──────────── data BlockPart = BlockPart { part_type :: Maybe String, part_id :: Maybe ID.T, part_title :: [I.InlineText], part_content :: [BlockSection] } 2.3.9 Document [id: model.block.document] 1 A document is the top-level container of other content. It may contain a list of parts [ref: model.block.part], or a list of sections [ref: model.block.section], but not both. A document is required to have a title. 2.3.9.2 Document ──────────────── data BlockDocument = BlockDocument { document_type :: Maybe String, document_id :: Maybe ID.T, document_title :: [I.InlineText], document_content :: Either [BlockPart] [BlockSection] } 2.3.10 Import [id: model.block.import] 1 An import is somewhat analogous to the inline include [ref: model.inline.include] type, except that the referenced file is actually parsed as a structural block value and inserted into the current document at the location of the import value. 2.3.10.2 Import ─────────────── data BlockImport = BlockImport { importFile :: String } 3 Canonical Format [id: fmt_canon] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Contents ───────────────────────────────────────────────────────────────────────────── 3.1 Overview ............................................. fmt_canon.overview 3.2 Inline Elements ....................................... fmt_canon.inlines 3.2.1 Overview ................................. fmt_canon.inlines.overview 3.2.2 Text ......................................... fmt_canon.inlines.text 3.2.3 Term ......................................... fmt_canon.inlines.term 3.2.4 Image ....................................... fmt_canon.inlines.image 3.2.5 Verbatim ................................. fmt_canon.inlines.verbatim 3.2.6 Link ......................................... fmt_canon.inlines.link 3.2.7 Link External ....................... fmt_canon.inlines.link_external 3.2.8 Footnote Reference ................... fmt_canon.inlines.footnote_ref 3.2.9 Ordered List ......................... fmt_canon.inlines.list_ordered 3.2.10 Unordered List .................... fmt_canon.inlines.list_unordered 3.2.11 Table ...................................... fmt_canon.inlines.table 3.2.12 Include .................................. fmt_canon.inlines.include 3.3 Block Elements ......................................... fmt_canon.blocks 3.3.1 Paragraph ................................ fmt_canon.blocks.paragraph 3.3.2 Formal Item ............................ fmt_canon.blocks.formal_item 3.3.3 Footnote .................................. fmt_canon.blocks.footnote 3.3.4 Subsection .............................. fmt_canon.blocks.subsection 3.3.5 Section .................................... fmt_canon.blocks.section 3.3.6 Part .......................................... fmt_canon.blocks.part 3.3.7 Document .................................. fmt_canon.blocks.document 3.3.8 Import ...................................... fmt_canon.blocks.import 3.1 Overview [id: fmt_canon.overview] 1 The structural language defines a number of different concrete syntaxes used to produce values of the types defined by the model [ref: model]. The primary canonical syntax is based on s-expressions [ref: conventions.sexprs]. 3.2 Inline Elements [id: fmt_canon.inlines] 3.2.1 Overview [id: fmt_canon.inlines.overview] 3.2.1.1 Main Syntax ─────────────────── canon_inline = (#choice [ canon_footnote_ref canon_image canon_include canon_link canon_link_external canon_list_ordered canon_list_unordered canon_term canon_text canon_verbatim ]) 3.2.2 Text [id: fmt_canon.inlines.text] 1 The concrete syntax specified here maps text to values of the InlineText [ref: model.inline.text] type. Most contexts in documents that accept text can also accept include [ref: fmt_canon.inlines.include] values, so an additional rule is given here that allows choosing between values of the two types. 3.2.2.2 Text Syntax ─────────────────── canon_text = (#choice [#any-symbol #any-quoted]) canon_text_or_include = (#choice [canon_text canon_include]) 3.2.3 Term [id: fmt_canon.inlines.term] 1 The concrete syntax specified here maps text to values of the InlineTerm [ref: model.inline.term] type. 3.2.3.2 Term Syntax ─────────────────── canon_type = (#exact-list [#exact-symbol "type"] #any-symbol) canon_term_name = (#exact-symbol "term") canon_term = (#choice [ (#variadic [canon_term_name] canon_text_or_include) (#variadic [canon_term_name canon_type] canon_text_or_include) ]) 3.2.4 Image [id: fmt_canon.inlines.image] 1 The concrete syntax specified here maps text to values of the InlineImage [ref: model.inline.image] type. 3.2.4.2 Image Syntax ──────────────────── canon_target = (#exact-list [#exact-symbol "target"] canon_text) canon_size = (#exact-list [#exact-symbol "size"] #any-symbol #any-symbol) canon_image_name = (#exact-symbol "image") canon_image = (#choice [ (#variadic [canon_image_name canon_target] canon_text_or_include) (#variadic [canon_image_name canon_target canon_type] canon_text_or_include) (#variadic [canon_image_name canon_target canon_size] canon_text_or_include) (#variadic [canon_image_name canon_target canon_size canon_type] canon_text_or_include) ]) 3.2.5 Verbatim [id: fmt_canon.inlines.verbatim] 1 The concrete syntax specified here maps text to values of the InlineVerbatim [ref: model.inline.verbatim] type. 3.2.5.2 Verbatim Syntax ─────────────────────── canon_verbatim_name = (#exact-symbol "verbatim") canon_verbatim = (#choice [ (#exact-list [canon_verbatim_name canon_text_or_include]) (#exact-list [canon_verbatim_name canon_type canon_text_or_include]) ]) 3.2.6 Link [id: fmt_canon.inlines.link] 1 The concrete syntax specified here maps text to values of the InlineLinkInternal [ref: model.inline.link] type. 3.2.6.2 Link Syntax ─────────────────── canon_link_name = (#exact-symbol "link") canon_link = (#variadic [canon_link_name canon_target] canon_text_or_include) 3.2.7 Link External [id: fmt_canon.inlines.link_external] 1 The concrete syntax specified here maps text to values of the InlineLinkExternal [ref: model.inline.link_external] type. 3.2.7.2 Link External Syntax ──────────────────────────── canon_link_external_name = (#exact-symbol "link-ext") canon_link_external = (#variadic [canon_link_external_name canon_target] canon_text_or_include) 3.2.8 Footnote Reference [id: fmt_canon.inlines.footnote_ref] 1 The concrete syntax specified here maps text to values of the InlineFootnoteRef [ref: model.inline.footnote_ref] type. 3.2.8.2 Footnote Reference Syntax ───────────────────────────────── canon_footnote_ref_name = (#exact-symbol "footnote-ref") canon_footnote_ref = (#exact-list canon_footnote_ref_name canon_text) 3.2.9 Ordered List [id: fmt_canon.inlines.list_ordered] 1 The concrete syntax specified here maps text to values of the InlineListOrdered [ref: model.inline.list_ordered] type. 3.2.9.2 Ordered List Syntax ─────────────────────────── canon_list_item_name = (#exact-symbol "item") canon_list_item = (#variadic [canon_list_item_name] canon_inline) canon_list_ordered_name = (#exact-symbol "list-ordered") canon_list_ordered = (#variadic [canon_list_ordered_name] canon_list_item) 3.2.10 Unordered List [id: fmt_canon.inlines.list_unordered] 1 The concrete syntax specified here maps text to values of the InlineListUnordered [ref: model.inline.list_unordered] type. 3.2.10.2 Unordered List Syntax ────────────────────────────── canon_list_unordered_name = (#exact-symbol "list-unordered") canon_list_unordered = (#variadic [canon_list_unordered_name] canon_list_item) 3.2.11 Table [id: fmt_canon.inlines.table] 1 The concrete syntax specified here maps text to values of the InlineTable [ref: model.inline.table] type. 3.2.11.2 Table Syntax ───────────────────── canon_table_name = (#exact-symbol "table") canon_table_summary_name = (#exact-symbol "summary") canon_table_summary = (#variadic [canon_table_summary_name] canon_text_or_include) canon_table_body_cell_name = (#exact-symbol "cell") canon_table_body_cell = (#variadic [canon_table_body_cell_name] canon_inline) canon_table_body_row_name = (#exact-symbol "row") canon_table_body_row = (#variadic [canon_table_body_row_name] canon_table_body_cell) canon_table_body_name = (#exact-symbol "body") canon_table_body = (#variadic [canon_table_body_name] canon_table_body_row) canon_table_body_head_cell_name = (#exact-symbol "name") canon_table_body_head_cell = (#variadic [canon_table_body_head_cell_name] canon_text) canon_table_head_name = (#exact-symbol "head") canon_table_head = (#variadic [canon_table_head_name] canon_table_head_cell) canon_table = (#choice [ (#exact-list [canon_table_name canon_table_summary cannon_table_body]) (#exact-list [canon_table_name canon_table_summary canon_type cannon_table_body]) (#exact-list [canon_table_name canon_table_summary cannon_table_head cannon_table_body]) (#exact-list [canon_table_name canon_table_summary canon_type cannon_table_head cannon_table_body]) ]) 3.2.12 Include [id: fmt_canon.inlines.include] 1 The concrete syntax specified here maps text to values of the InlineInclude [ref: model.inline.include] type. 3.2.12.2 Include Syntax ─────────────────────── canon_include_name = (#exact-symbol "include") canon_include = (#exact-list [canon_include_name #any-quoted]) 3.3 Block Elements [id: fmt_canon.blocks] 3.3.1 Paragraph [id: fmt_canon.blocks.paragraph] 1 The concrete syntax specified here maps text to values of the BlockParagraph [ref: model.block.paragraph] type. 3.3.1.2 Paragraph Syntax ──────────────────────── canon_id_name = (#exact-symbol "id") canon_id = (#exact-list [canon_id_name canon_text]) canon_paragraph_name = (#exact-symbol "paragraph") canon_paragraph = (#choice [ (#variadic [canon_paragraph_name] canon_inline) (#variadic [canon_paragraph_name canon_id] canon_inline) (#variadic [canon_paragraph_name canon_id canon_type] canon_inline) (#variadic [canon_paragraph_name canon_type canon_id] canon_inline) (#variadic [canon_paragraph_name canon_type] canon_inline) ]) 3.3.2 Formal Item [id: fmt_canon.blocks.formal_item] 1 The concrete syntax specified here maps text to values of the BlockFormalItem [ref: model.block.formal_item] type. 3.3.2.2 Formal Item Syntax ────────────────────────── canon_title_name = (#exact-symbol "title") canon_title = (#variadic [canon_title_name] canon_text) canon_formal_item_name = (#exact-symbol "formal-item") canon_formal_item = (#choice [ (#variadic [canon_formal_item_name canon_title] canon_inline) (#variadic [canon_formal_item_name canon_title canon_id] canon_inline) (#variadic [canon_formal_item_name canon_title canon_id canon_type] canon_inline) (#variadic [canon_formal_item_name canon_title canon_type canon_id] canon_inline) (#variadic [canon_formal_item_name canon_title canon_type] canon_inline) ]) 3.3.3 Footnote [id: fmt_canon.blocks.footnote] 1 The concrete syntax specified here maps text to values of the BlockFootnote [ref: model.block.footnote] type. 3.3.3.2 Footnote Syntax ─────────────────────── canon_footnote_name = (#exact-symbol "footnote") canon_footnote = (#choice [ (#variadic [canon_footnote_name canon_id] canon_inline) (#variadic [canon_footnote_name canon_id canon_type] canon_inline) ]) 3.3.4 Subsection [id: fmt_canon.blocks.subsection] 1 The concrete syntax specified here maps text to values of the BlockSubsection [ref: model.block.subsection] type. 3.3.4.2 Subsection Syntax ───────────────────────── canon_subsection_name = (#exact-symbol "subsection") canon_subsection_content = (#choice [canon_paragraph canon_footnote canon_formal_item]) canon_subsection = (#choice [ (#variadic [canon_subsection_name canon_title] canon_subsection_content) (#variadic [canon_subsection_name canon_title canon_id] canon_subsection_content) (#variadic [canon_subsection_name canon_title canon_id canon_type] canon_subsection_content) (#variadic [canon_subsection_name canon_title canon_type canon_id] canon_subsection_content) (#variadic [canon_subsection_name canon_title canon_type] canon_subsection_content) ]) 3.3.5 Section [id: fmt_canon.blocks.section] 1 The concrete syntax specified here maps text to values of the BlockSection [ref: model.block.section] type. 3.3.5.2 Section Syntax ────────────────────── canon_section_name = (#exact-symbol "section") canon_section_content = (#choice [canon_subsection canon_subsection_content]) canon_section = (#choice [ (#variadic [canon_section_name canon_title] canon_section_content) (#variadic [canon_section_name canon_title canon_id] canon_section_content) (#variadic [canon_section_name canon_title canon_id canon_type] canon_section_content) (#variadic [canon_section_name canon_title canon_type canon_id] canon_section_content) (#variadic [canon_section_name canon_title canon_type] canon_section_content) ]) 3.3.6 Part [id: fmt_canon.blocks.part] 1 The concrete syntax specified here maps text to values of the BlockPart [ref: model.block.part] type. 3.3.6.2 Part Syntax ─────────────────── canon_part_name = (#exact-symbol "part") canon_part = (#choice [ (#variadic [canon_part_name canon_title] canon_section) (#variadic [canon_part_name canon_title canon_id] canon_section) (#variadic [canon_part_name canon_title canon_id canon_type] canon_section) (#variadic [canon_part_name canon_title canon_type canon_id] canon_section) (#variadic [canon_part_name canon_title canon_type] canon_section) ]) 3.3.7 Document [id: fmt_canon.blocks.document] 1 The concrete syntax specified here maps text to values of the BlockDocument [ref: model.block.document] type. 3.3.7.2 Document Syntax ─────────────────────── canon_document_name = (#exact-symbol "document") canon_document_content = (#choice [canon_section canon_part]) canon_document = (#choice [ (#variadic [canon_document_name canon_title] canon_document_content) (#variadic [canon_document_name canon_title canon_id] canon_document_content) (#variadic [canon_document_name canon_title canon_id canon_type] canon_document_content) (#variadic [canon_document_name canon_title canon_type canon_id] canon_document_content) (#variadic [canon_document_name canon_title canon_type] canon_document_content) ]) 3.3.8 Import [id: fmt_canon.blocks.import] 1 The concrete syntax specified here maps text to values of the BlockImport [ref: model.block.import] type. 3.3.8.2 Import Syntax ───────────────────── canon_import_name = (#exact-symbol "import") canon_import = (#exact-list [canon_import_name canon_text]) 4 Imperative Format [id: fmt_imp] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Contents ───────────────────────────────────────────────────────────────────────────── 4.1 Overview ............................................... fmt_imp.overview 4.2 Block Commands ........................................... fmt_imp.blocks 4.2.1 Overview .................................... fmt_imp.blocks.overview 4.2.2 Structural Significance .................... fmt_imp.blocks.structsig 4.2.3 Paragraph .................................. fmt_imp.blocks.paragraph 4.2.4 Formal Item .............................. fmt_imp.blocks.formal_item 4.2.5 Footnote .................................... fmt_imp.blocks.footnote 4.2.6 Subsection ................................ fmt_imp.blocks.subsection 4.2.7 Section ...................................... fmt_imp.blocks.section 4.2.8 Part ............................................ fmt_imp.blocks.part 4.2.9 Document .................................... fmt_imp.blocks.document 4.1 Overview [id: fmt_imp.overview] 1 One observation of all document languages that present a tree-like structure and syntax is that the writer spends a certain amount of time managing the tree structure itself. Although s-expressions [ref: conventions.sexprs] represent about the most lightweight syntax possible for representing trees directly, it's possible to reduce the syntactic overhead even further by allowing the author to progressively define trees using a series of imperative commands. 2 The so-called imperative syntax combines the inline [ref: fmt_canon.inlines] elements from the canonical syntax with a set of imperative block commands. 4.2 Block Commands [id: fmt_imp.blocks] 4.2.1 Overview [id: fmt_imp.blocks.overview] 1 An imperative command begins the construction of a new block [ref: model.block]. Any block currently under construction that is of lesser than or equal to structural significance [ref: fmt_imp.blocks.structsig] is completed on receipt of the command (or on end-of-file), prior to beginning the construction of a new block. Inline [ref: model.inline] content is supplied to blocks that accept it by simply including the content between commands: 4.2.1.2 Imperative Example ────────────────────────── [subsection [title An example subsection]] [paragraph] This is some content for the first paragraph. [paragraph] This is some [term [type emphasis] content] for the second paragraph. [subsection [title Another example subsection]] [paragraph] This is some content for the first paragraph of the next section. 3 An imperative command may take one of the following forms: 4.2.1.4 Imperative Commands ─────────────────────────── data ImperativeContent = ICParagraph ImperativeParagraph | ICFormalItem ImperativeFormalItem | ICFootnote ImperativeFootnote | ICSubsection ImperativeSubsection | ICSection ImperativeSection | ICPart ImperativePart | ICDocument ImperativeDocument | ICImport ImperativeImport deriving Eq 5 Imperative commands create values of the types specified in the model [ref: model.block], and therefore the same rules apply with regards to where blocks can be created. For example, it is an error (by the definition of the section [ref: model.block.section] type) to first create a subsection [ref: model.block.subsection] inside a section and then attempt to follow it with the definition of a paragraph [ref: model.block.paragraph]. 4.2.2 Structural Significance [id: fmt_imp.blocks.structsig] 1 In order for the receipt of a command to complete the construction of a block that is already under construction, it is necessary to define an ordering on the structural significance of each of the block types. 4.2.2.2 Significance Ordering ───────────────────────────── instance Ord ImperativeContent where compare (ICParagraph _) (ICParagraph _) = EQ compare (ICParagraph _) (ICFormalItem _) = EQ compare (ICParagraph _) (ICFootnote _) = EQ compare (ICParagraph _) (ICSubsection _) = LT compare (ICParagraph _) (ICSection _) = LT compare (ICParagraph _) (ICPart _) = LT compare (ICParagraph _) (ICDocument _) = LT compare (ICFormalItem _) (ICParagraph _) = EQ compare (ICFormalItem _) (ICFormalItem _) = EQ compare (ICFormalItem _) (ICFootnote _) = EQ compare (ICFormalItem _) (ICSubsection _) = LT compare (ICFormalItem _) (ICSection _) = LT compare (ICFormalItem _) (ICPart _) = LT compare (ICFormalItem _) (ICDocument _) = LT compare (ICFootnote _) (ICParagraph _) = EQ compare (ICFootnote _) (ICFormalItem _) = EQ compare (ICFootnote _) (ICFootnote _) = EQ compare (ICFootnote _) (ICSubsection _) = LT compare (ICFootnote _) (ICSection _) = LT compare (ICFootnote _) (ICPart _) = LT compare (ICFootnote _) (ICDocument _) = LT compare (ICSubsection _) (ICParagraph _) = GT compare (ICSubsection _) (ICFormalItem _) = GT compare (ICSubsection _) (ICFootnote _) = GT compare (ICSubsection _) (ICSubsection _) = EQ compare (ICSubsection _) (ICSection _) = LT compare (ICSubsection _) (ICPart _) = LT compare (ICSubsection _) (ICDocument _) = LT compare (ICSection _) (ICParagraph _) = GT compare (ICSection _) (ICFormalItem _) = GT compare (ICSection _) (ICFootnote _) = GT compare (ICSection _) (ICSubsection _) = GT compare (ICSection _) (ICSection _) = EQ compare (ICSection _) (ICPart _) = LT compare (ICSection _) (ICDocument _) = LT compare (ICPart _) (ICParagraph _) = GT compare (ICPart _) (ICFormalItem _) = GT compare (ICPart _) (ICFootnote _) = GT compare (ICPart _) (ICSubsection _) = GT compare (ICPart _) (ICSection _) = GT compare (ICPart _) (ICPart _) = EQ compare (ICPart _) (ICDocument _) = LT compare (ICDocument _) (ICParagraph _) = GT compare (ICDocument _) (ICFormalItem _) = GT compare (ICDocument _) (ICFootnote _) = GT compare (ICDocument _) (ICSubsection _) = GT compare (ICDocument _) (ICSection _) = GT compare (ICDocument _) (ICPart _) = GT compare (ICDocument _) (ICDocument _) = EQ compare (ICImport i) e = compare (importContent i) e compare e (ICImport i) = compare e (importContent i) 3 The importContent function is a function that maps import blocks to their imported content. This is a function of the actual language implementation and so is left undefined in this specification. 4.2.2.4 Import Content ────────────────────── importContent :: ImperativeImport -> ImperativeContent importContent _ = undefined 4.2.3 Paragraph [id: fmt_imp.blocks.paragraph] 1 A paragraph command begins a new paragraph [ref: model.block.paragraph] in the current context. 4.2.3.2 Paragraph ───────────────── data ImperativeParagraph = ImperativeParagraph { para_type :: Maybe String, para_id :: Maybe ID.T } deriving Eq 3 The concrete syntax for the command is as follows: 4.2.3.4 Syntax ────────────── imperative_paragraph = (#choice [ (#exact-list [canon_paragraph_name]) (#exact-list [canon_paragraph_name canon_id]) (#exact-list [canon_paragraph_name canon_id canon_type]) (#exact-list [canon_paragraph_name canon_type canon_id]) (#exact-list [canon_paragraph_name canon_type]) ]) 4.2.4 Formal Item [id: fmt_imp.blocks.formal_item] 1 A formal-item command begins a new formal item [ref: model.block.formal_item] in the current context. 4.2.4.2 Formal Item ─────────────────── data ImperativeFormalItem = ImperativeFormalItem { formal_type :: Maybe String, formal_id :: Maybe ID.T, formal_title :: [I.InlineText] } deriving Eq 3 The concrete syntax for the command is as follows: 4.2.4.4 Syntax ────────────── imperative_formal_item = (#choice [ (#exact-list [canon_formal_item_name canon_title]) (#exact-list [canon_formal_item_name canon_title canon_id]) (#exact-list [canon_formal_item_name canon_title canon_id canon_type]) (#exact-list [canon_formal_item_name canon_title canon_type canon_id]) (#exact-list [canon_formal_item_name canon_title canon_type]) ]) 4.2.5 Footnote [id: fmt_imp.blocks.footnote] 1 A footnote command begins a new footnote [ref: model.block.footnote] in the current context. 4.2.5.2 Footnote ──────────────── data ImperativeFootnote = ImperativeFootnote { footnote_type :: Maybe String, footnote_id :: ID.T } deriving Eq 3 The concrete syntax for the command is as follows: 4.2.5.4 Syntax ────────────── imperative_footnote = (#choice [ (#exact-list [canon_footnote_name canon_id]) (#exact-list [canon_footnote_name canon_id canon_type]) ]) 4.2.6 Subsection [id: fmt_imp.blocks.subsection] 1 A subsection command begins a new subsection [ref: model.block.subsection] in the current context. 4.2.6.2 Subsection ────────────────── data ImperativeSubsection = ImperativeSubsection { subsection_type :: Maybe String, subsection_id :: Maybe ID.T, subsection_title :: [I.InlineText] } deriving Eq 3 The concrete syntax for the command is as follows: 4.2.6.4 Syntax ────────────── imperative_subsection = (#choice [ (#exact-list [canon_subsection_name canon_title]) (#exact-list [canon_subsection_name canon_title canon_id]) (#exact-list [canon_subsection_name canon_title canon_id canon_type]) (#exact-list [canon_subsection_name canon_title canon_type canon_id]) (#exact-list [canon_subsection_name canon_title canon_type]) ]) 4.2.7 Section [id: fmt_imp.blocks.section] 1 A section command begins a new section [ref: model.block.section] in the current context. 4.2.7.2 Section ─────────────── data ImperativeSection = ImperativeSection { section_type :: Maybe String, section_id :: Maybe ID.T, section_title :: [I.InlineText] } deriving Eq 3 The concrete syntax for the command is as follows: 4.2.7.4 Syntax ────────────── imperative_section = (#choice [ (#exact-list [canon_section_name canon_title]) (#exact-list [canon_section_name canon_title canon_id]) (#exact-list [canon_section_name canon_title canon_id canon_type]) (#exact-list [canon_section_name canon_title canon_type canon_id]) (#exact-list [canon_section_name canon_title canon_type]) ]) 4.2.8 Part [id: fmt_imp.blocks.part] 1 A part command begins a new part [ref: model.block.part] in the current context. 4.2.8.2 Part ──────────── data ImperativePart = ImperativePart { part_type :: Maybe String, part_id :: Maybe ID.T, part_title :: [I.InlineText] } deriving Eq 3 The concrete syntax for the command is as follows: 4.2.8.4 Syntax ────────────── imperative_part = (#choice [ (#exact-list [canon_part_name canon_title]) (#exact-list [canon_part_name canon_title canon_id]) (#exact-list [canon_part_name canon_title canon_id canon_type]) (#exact-list [canon_part_name canon_title canon_type canon_id]) (#exact-list [canon_part_name canon_title canon_type]) ]) 4.2.9 Document [id: fmt_imp.blocks.document] 1 A document command begins a new document [ref: model.block.document] in the current context. 4.2.9.2 Document ──────────────── data ImperativeDocument = ImperativeDocument { document_type :: Maybe String, document_id :: Maybe ID.T, document_title :: [I.InlineText] } deriving Eq 3 The concrete syntax for the command is as follows: 4.2.9.4 Syntax ────────────── imperative_document = (#choice [ (#exact-list [canon_document_name canon_title]) (#exact-list [canon_document_name canon_title canon_id]) (#exact-list [canon_document_name canon_title canon_id canon_type]) (#exact-list [canon_document_name canon_title canon_type canon_id]) (#exact-list [canon_document_name canon_title canon_type]) ]) 5 XML Format [id: fmt_xml] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Contents ───────────────────────────────────────────────────────────────────────────── 5.1 Overview ............................................... fmt_xml.overview 5.2 RELAX-NG Schema .......................................... fmt_xml.schema 5.1 Overview [id: fmt_xml.overview] 1 The XML format is defined as a simple encoding of the canonical [ref: fmt_canon] format as XML. Instead of include [ref: model.inline.include] and import [ref: model.block.import] elements, the user is expected to use XInclude [url: https://www.w3.org/TR/xinclude/]. 5.2 RELAX-NG Schema [id: fmt_xml.schema] 5.2.1 Schema ──────────── Footnotes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━