patrick@73: include "publidoc.rnc" { patrick@73: start = publiquiz patrick@73: patrick@73: document.content = patrick@73: top.head?, patrick@73: (division | topic | quiz)+ patrick@84: patrick@84: division.content = patrick@84: division.head?, Patrick@353: front?, patrick@84: (division | topic | quiz)+ Coraline@436: Coraline@436: nowrap.content = Coraline@441: inlines | blanks.inlines | blanks-m.inlines | blanks-c.inlines Coraline@441: | pointing.inlines patrick@73: } patrick@73: patrick@75: patrick@73: publiquiz = element publiquiz { patrick@73: publiquiz.attributes, patrick@73: publiquiz.content patrick@73: } patrick@73: patrick@73: publiquiz.attributes = patrick@73: version.attribute patrick@73: patrick@73: publiquiz.content = patrick@73: document patrick@73: | top.quiz patrick@73: patrick@73: patrick@73: # ============================================================================= patrick@73: # TOP LEVEL patrick@73: # ============================================================================= patrick@73: Patrick@310: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ top.quiz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@128: top.quiz = element quiz { top.quiz.attributes, top.quiz.content } patrick@73: patrick@73: top.quiz.attributes = Patrick@388: quiz.id.attribute? Patrick@158: & quiz.type.attribute? patrick@73: & lang.attribute? patrick@117: quiz.id.attribute = attribute id { xsd:NMTOKEN } Patrick@158: quiz.type.attribute = attribute type { xsd:NCName } patrick@73: patrick@128: top.quiz.content = patrick@128: top.head?, claire@345: instructions?, patrick@128: (engine | composite), patrick@128: help?, patrick@128: answer? patrick@73: Patrick@310: patrick@73: # ============================================================================= Patrick@310: # COMPONENT LEVEL patrick@73: # ============================================================================= patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ quiz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: quiz = element quiz { quiz.attributes, quiz.content } patrick@73: patrick@73: quiz.attributes = Patrick@310: (quiz.id.attribute | xmlid.attribute)? Patrick@158: & quiz.type.attribute? patrick@73: & lang.attribute? patrick@73: patrick@73: quiz.content = patrick@73: component.head?, Patrick@417: instructions?, patrick@87: (engine | composite), patrick@73: help?, patrick@87: answer? patrick@73: patrick@73: patrick@73: # ============================================================================= patrick@73: # SECTION LEVEL patrick@73: # ============================================================================= patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ section ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: blanks.section = element section { section.attributes, blanks.section.content } Coraline@409: blanks-m.section = element section { Coraline@409: section.attributes, blanks-m.section.content } Coraline@441: blanks-c.section = element section { Coraline@441: section.attributes, blanks-c.section.content } Coraline@442: correct.section = element section { Coraline@442: section.attributes, correct.section.content } Patrick@336: pointing.section = element section { Patrick@336: section.attributes, pointing.section.content } patrick@73: patrick@73: blanks.section.content = patrick@73: section.head?, patrick@73: (blanks.section+ | blanks.block+) Coraline@409: blanks-m.section.content = Coraline@409: section.head?, Coraline@409: (blanks-m.section+ | blanks-m.block+) Coraline@441: blanks-c.section.content = Coraline@441: section.head?, Coraline@441: (blanks-c.section+ | blanks-c.block+) Coraline@442: correct.section.content = Coraline@442: section.head?, Coraline@442: (correct.section+ | correct.block+) Patrick@336: pointing.section.content = patrick@73: section.head?, Patrick@336: (pointing.section+ | pointing.block+) patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ instructions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: instructions = element instructions { section.content } patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ engine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: engine = patrick@87: choices-radio patrick@87: | choices-check patrick@87: | blanks-fill patrick@87: | blanks-select Coraline@409: | blanks-media Coraline@441: | blanks-choices Coraline@442: | correct-line Patrick@336: | pointing Patrick@336: | pointing-categories patrick@73: | matching patrick@73: | sort patrick@125: | categories Coraline@438: | wordsearch Patrick@448: | flashcard Patrick@450: | coloring Patrick@450: | memory iinov@463: | dictation patrick@87: | production patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ choices ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@87: choices-radio = element choices-radio { Patrick@376: choices-radio.attributes, choices-radio.content } patrick@87: choices-check = element choices-check { Patrick@376: choices-check.attributes, choices-check.content } patrick@73: Patrick@376: choices-radio.attributes = patrick@73: shuffle.attribute? Patrick@376: choices-check.attributes = Patrick@376: success.attribute? Patrick@376: & shuffle.attribute? Patrick@376: success.attribute = attribute success { xsd:decimal {maxInclusive="1"} } patrick@73: shuffle.attribute = attribute shuffle { xsd:boolean } patrick@73: patrick@87: choices-radio.content = patrick@73: choices.right patrick@73: & choices.wrong+ patrick@87: choices-check.content = patrick@73: (choices.right | choices.wrong)+ patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ blanks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@87: blanks-fill = element blanks-fill { patrick@87: blanks-fill.attributes, blanks-fill.content } patrick@87: blanks-select = element blanks-select { patrick@87: blanks-select.attributes, blanks-select.content } Coraline@409: blanks-media = element blanks-media { Coraline@409: blanks-select.attributes, blanks-media.content } Coraline@441: blanks-choices = element blanks-choices { Coraline@441: blanks-choices.content } patrick@73: patrick@87: blanks-fill.attributes = Patrick@376: success.attribute? Patrick@376: & strict.attribute? claire@381: & long.attribute? patrick@87: blanks-select.attributes = Patrick@376: success.attribute? Patrick@376: & multiple.attribute? claire@380: & noshuffle.attribute? Coraline@409: & orientation.attribute? patrick@73: strict.attribute = attribute strict { xsd:boolean } patrick@73: multiple.attribute = attribute multiple { xsd:boolean } Coraline@437: noshuffle.attribute = attribute no-shuffle { "true" | "false" | "alpha" } claire@381: long.attribute = attribute long { xsd:positiveInteger } Coraline@409: orientation.attribute = attribute orientation {"north"|"east"|"west"|"south"} patrick@73: patrick@87: blanks-fill.content = patrick@73: (blanks.block+ | blanks.section+) patrick@87: blanks-select.content = Patrick@342: blanks.intruders?, patrick@73: (blanks.block+ | blanks.section+) Coraline@409: blanks-media.content = Coraline@409: blanks-m.intruders?, Coraline@409: (blanks-m.block+ | blanks-m.section+) Coraline@441: blanks-choices.content = Coraline@441: (blanks-c.block+ | blanks-c.section+) patrick@73: Coraline@442: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ correct-line ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@448: Patrick@448: correct-line = element correct-line { correct.attributes, correct.content } Coraline@442: Patrick@450: correct.attributes = Coraline@402: remove-space.attribute? Coraline@402: remove-space.attribute = attribute remove-space { xsd:boolean } Coraline@402: Coraline@442: correct.content = Coraline@442: correct.intruders?, Coraline@442: (correct.block+ | correct.section+) Coraline@442: Patrick@336: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pointing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: Patrick@336: pointing = element pointing { pointing.attributes, pointing.content } patrick@75: Patrick@336: pointing.attributes = Patrick@376: success.attribute? Patrick@376: & pointing.type.attribute? Patrick@336: pointing.type.attribute = attribute type { "radio" | "check" } patrick@73: Patrick@336: pointing.content = Patrick@336: (pointing.section+ | pointing.block+) Patrick@336: Patrick@336: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pointing-categories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@336: Patrick@336: # ~~~~~~ pointing-categories Patrick@376: pointing-categories = element pointing-categories { Patrick@376: pointing-c.attributes, pointing-c.content } Patrick@376: Patrick@376: pointing-c.attributes = Patrick@376: success.attribute? Patrick@336: Patrick@336: pointing-c.content = Patrick@336: pointing-c.categories, Patrick@336: pointing.section Patrick@336: Patrick@336: # ~~~~~~ pointing-c.categories Patrick@336: pointing-c.categories = element categories { pointing-c.categories.content } Patrick@336: Patrick@336: pointing-c.categories.content = Patrick@336: pointing-c.category1, Patrick@336: pointing-c.category2, Patrick@336: (pointing-c.category3, Patrick@336: (pointing-c.category4, pointing-c.category5?)?)? Patrick@336: Patrick@336: # ~~~~~~ pointing-c.categoryN Patrick@336: pointing-c.category1 = element category { Patrick@336: attribute id { "1" }, pointing-c.category.content } Patrick@336: pointing-c.category2 = element category { Patrick@336: attribute id { "2" }, pointing-c.category.content } Patrick@336: pointing-c.category3 = element category { Patrick@336: attribute id { "3" }, pointing-c.category.content } Patrick@336: pointing-c.category4 = element category { Patrick@336: attribute id { "4" }, pointing-c.category.content } Patrick@336: pointing-c.category5 = element category { Patrick@336: attribute id { "5" }, pointing-c.category.content } Patrick@336: Patrick@336: pointing-c.category.content = inlines Patrick@336: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ matching ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: Patrick@161: # ~~~~~~ matching Patrick@169: matching = element matching { matching.attributes, matching.content } Patrick@169: Patrick@169: matching.attributes = Patrick@376: success.attribute? Patrick@376: & multiple.attribute? Coraline@438: & noshuffle.attribute? Coraline@409: & orientation.attribute? patrick@75: patrick@73: matching.content = Patrick@359: matching.intruders?, patrick@73: match, patrick@73: match+ patrick@73: Patrick@161: # ~~~~~~ match Patrick@161: match = element match { match.content } Patrick@161: Patrick@161: match.content = Patrick@161: match.item, Patrick@161: match.item Patrick@161: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sort ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: sort = element sort { sort.attributes, sort.content } patrick@73: patrick@73: sort.attributes = Patrick@376: success.attribute? Patrick@376: & shuffle.attribute? Coraline@409: & orientation.attribute? patrick@75: patrick@73: sort.content = iinov@462: sort.intruders?, iinov@461: comparison?, iinov@461: sort.item, iinov@461: sort.item+ patrick@73: patrick@125: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ categories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@125: Patrick@310: # ~~~~~~ category.head Patrick@310: category.head = element head { category.head.content } Patrick@310: Patrick@310: category.head.content = Patrick@384: title Patrick@384: & shorttitle? Patrick@384: & subtitle* Patrick@310: patrick@125: # ~~~~~~ categories Patrick@168: categories = element categories { categories.attributes, categories.content } patrick@125: Patrick@168: categories.attributes = Patrick@376: success.attribute? Patrick@376: & multiple.attribute? claire@380: & noshuffle.attribute? Coraline@409: & orientation.attribute? Patrick@310: patrick@125: categories.content = Patrick@344: categories.intruders?, patrick@125: category, patrick@125: category+ patrick@125: patrick@125: # ~~~~~~ category patrick@125: category = element category { category.content } patrick@125: patrick@125: category.content = patrick@125: category.head, patrick@125: category.item* patrick@125: Coraline@438: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wordsearch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@448: Coraline@438: wordsearch = element wordsearch {wordsearch.attributes, wordsearch.content } Coraline@438: Coraline@438: wordsearch.attributes = Coraline@438: strict.attribute ? Coraline@438: & wordlist.attribute ? Coraline@438: Coraline@438: wordlist.attribute = attribute wordlist { "hidden" | "right" | "left" } Coraline@438: Coraline@438: wordsearch.content = Coraline@438: words Coraline@438: & grid Coraline@438: Coraline@438: # ~~~~~~ words Coraline@438: words = element words {words.content} Coraline@438: words.content = words.item+ Coraline@438: Coraline@438: # ~~~~~~ grid Coraline@438: grid = element grid {grid.content} Coraline@438: grid.content = line+ Coraline@438: Coraline@438: line = element line {line.content} Coraline@438: line.content = cell+ Coraline@438: Coraline@438: cell = element cell {cell.content} Coraline@438: cell.content = xsd:token {pattern = "."} Patrick@450: Patrick@448: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ flashcard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@448: Patrick@448: # ~~~~~~ flashcard Patrick@448: flashcard = element flashcard { flashcard.content } Patrick@448: Patrick@448: flashcard.content = Patrick@448: side1, Patrick@448: side2 Patrick@448: Patrick@448: # ~~~~~~ side1 Patrick@448: side1 = element side1 { side1.content } Patrick@448: Patrick@448: side1.content = Patrick@448: section+ | block+ Patrick@448: Patrick@448: # ~~~~~~ side2 Patrick@448: side2 = element side2 { side2.content } Patrick@448: Patrick@448: side2.content = Patrick@448: instructions?, Patrick@448: flashcard.engine, Patrick@448: help?, Patrick@448: answer? Patrick@448: Patrick@448: # ~~~~~~ flashcard.engine Patrick@448: flashcard.engine = Patrick@448: choices-radio Patrick@448: | choices-check Patrick@448: | blanks-fill Patrick@448: | blanks-select Patrick@448: | sort Patrick@448: Patrick@450: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ coloring ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@450: Patrick@450: coloring = element coloring { coloring.attributes, coloring.content } Patrick@450: Patrick@450: coloring.attributes = Patrick@450: nomark.attribute? Patrick@450: nomark.attribute = attribute nomark { xsd:boolean } Patrick@450: Patrick@450: coloring.content = Patrick@450: palette Patrick@450: & canvas Patrick@450: & areas? Patrick@450: Patrick@450: # ~~~~~~ palette Patrick@450: palette = element palette { palette.content } Patrick@450: Patrick@450: palette.content = Patrick@450: color+ Patrick@450: Patrick@450: # ~~~~~~ canvas Patrick@450: canvas = element canvas { canvas.attributes } Patrick@450: Patrick@450: canvas.attributes = Patrick@450: media.id.attribute Patrick@450: Patrick@450: # ~~~~~~ areas Patrick@450: areas = element areas { areas.attributes } Patrick@450: Patrick@450: areas.attributes = Patrick@450: media.id.attribute Patrick@450: Patrick@450: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@450: Patrick@450: # ~~~~~~ memory Patrick@450: memory = element memory { memory.attributes, memory.content } Patrick@450: Patrick@450: memory.attributes = Patrick@450: display.attribute? Patrick@450: & delay.attribute? Patrick@450: display.attribute = attribute display { xsd:positiveInteger } Patrick@450: delay.attribute = attribute delay { xsd:positiveInteger } Patrick@450: Patrick@450: memory.content = Patrick@450: memory.match, Patrick@450: memory.match+ Patrick@450: Patrick@450: # ~~~~~~ memory.match Patrick@450: memory.match = element match { memory-m.content } Patrick@450: Patrick@450: memory-m.content = Patrick@450: memory-m.item, Patrick@450: memory-m.item, Patrick@450: audio? Patrick@450: iinov@463: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dictation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ iinov@463: iinov@463: dictation = element dictation { dictation.content } iinov@463: iinov@463: dictation.content = iinov@463: audio, iinov@463: dictation.block+ iinov@463: patrick@87: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ production ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@87: Coraline@407: production = element production { production.content } Coraline@407: Coraline@407: production.content = text patrick@87: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ composite ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@77: # ~~~~~~ composite Patrick@161: composite = element composite { composite.attributes, composite.content } Patrick@161: Patrick@161: composite.attributes = Patrick@376: success.attribute? Patrick@376: & multipage.attribute? Patrick@310: multipage.attribute = attribute multipage { xsd:boolean } patrick@75: patrick@73: composite.content = patrick@85: subquiz, Patrick@154: subquiz+ patrick@77: patrick@85: # ~~~~~~ subquiz patrick@85: subquiz = element subquiz { subquiz.content } patrick@77: patrick@85: subquiz.content = patrick@77: instructions?, Patrick@141: engine, Patrick@141: help?, Patrick@141: answer? patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ help ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: help = element help { help.content } patrick@73: patrick@73: help.content = patrick@73: (section+ | block+)?, patrick@73: link* patrick@73: patrick@87: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ answer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@87: answer = element answer { answer.content } patrick@73: patrick@87: answer.content = patrick@81: (section+ | block+)?, patrick@80: link* patrick@73: patrick@73: patrick@73: # ============================================================================= patrick@73: # BLOCK LEVEL patrick@73: # ============================================================================= patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ block ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: Patrick@313: blanks.block = ( Patrick@313: blanks.p | blanks.list | blanks.blockquote | blanks.speech | blanks.table Patrick@313: | blanks.media) Coraline@409: blanks-m.block = ( Coraline@409: blanks-m.p | blanks-m.list | blanks-m.blockquote | blanks-m.speech Coraline@409: | blanks-m.table | blanks-m.media) Coraline@441: blanks-c.block = ( Coraline@441: blanks-c.p | blanks-c.list | blanks-c.blockquote | blanks-c.speech Coraline@441: | blanks-c.table | blanks-c.media) Coraline@442: correct.block = ( Coraline@442: correct.p | correct.list | correct.blockquote | correct.speech Coraline@442: | correct.table | media) Patrick@336: pointing.block = ( Patrick@336: pointing.p | pointing.list | pointing.blockquote | pointing.speech Patrick@336: | pointing.table | media) iinov@463: dictation.block = dictation.p patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ p ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: blanks.p = element p { blanks.p.content } Coraline@409: blanks-m.p = element p { blanks-m.p.content } Coraline@441: blanks-c.p = element p { blanks-c.p.content } Coraline@442: correct.p = element p { correct.p.content } Patrick@336: pointing.p = element p { pointing.p.content } iinov@463: dictation.p = element p { dictation.p.content } patrick@73: patrick@73: blanks.p.content = iinov@463: blanks.inlines Coraline@409: blanks-m.p.content = iinov@463: blanks-m.inlines Coraline@441: blanks-c.p.content = iinov@463: blanks-c.inlines Coraline@442: correct.p.content = iinov@463: correct.inlines Patrick@336: pointing.p.content = iinov@463: pointing.inlines iinov@463: dictation.p.content = iinov@463: dictation.inlines patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: # ~~~~~~ list patrick@75: blanks.list = element list { patrick@73: block.head?, patrick@73: ( (attribute type {"ordered"}?, blanks.item, blanks.item+) Coraline@422: | (attribute type {"glossary"}, item.glossary+) ) patrick@75: } Coraline@409: blanks-m.list = element list { Coraline@409: block.head?, Coraline@441: ( (attribute type {"ordered"}?, blanks-m.item, blanks-m.item+) Coraline@441: | (attribute type {"glossary"}, item.glossary+) ) Coraline@441: } Coraline@441: blanks-c.list = element list { Coraline@441: block.head?, Coraline@409: ( (attribute type {"ordered"}?, blanks.item, blanks.item+) Coraline@422: | (attribute type {"glossary"}, item.glossary+) ) Coraline@409: } Coraline@442: correct.list = element list { Coraline@442: block.head?, Coraline@442: ( (attribute type {"ordered"}?, correct.item, correct.item+) Coraline@442: | (attribute type {"glossary"}, item.glossary+) ) Coraline@442: } Patrick@336: pointing.list = element list { patrick@73: block.head?, Patrick@336: ( (attribute type {"ordered"}?, pointing.item, pointing.item+) Coraline@422: | (attribute type {"glossary"}, item.glossary+) ) patrick@75: } patrick@73: patrick@73: # ~~~~~~ item patrick@73: blanks.item = element item { blanks.item.content } Coraline@441: blanks-m.item = element item { blanks-m.item.content } Coraline@441: blanks-c.item = element item { blanks-c.item.content } Coraline@442: correct.item = element item { correct.item.content } Patrick@336: pointing.item = element item { pointing.item.content } Patrick@450: patrick@73: Coraline@442: blanks.item.content = blanks.inlines | blanks.block+ Coraline@442: blanks-m.item.content = blanks-m.inlines | blanks-m.block+ Coraline@442: blanks-c.item.content = blanks-c.inlines | blanks-c.block+ Coraline@442: correct.item.content = correct.inlines | correct.block+ Coraline@442: pointing.item.content = pointing.inlines | pointing.block+ patrick@73: Patrick@313: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ blockquote ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@313: Patrick@313: blanks.blockquote = element blockquote { Patrick@313: blockquote.attributes, blanks.blockquote.content } Coraline@409: blanks-m.blockquote = element blockquote { Coraline@409: blockquote.attributes, blanks-m.blockquote.content } Coraline@441: blanks-c.blockquote = element blockquote { Coraline@441: blockquote.attributes, blanks-c.blockquote.content } Coraline@442: correct.blockquote = element blockquote { Coraline@442: blockquote.attributes, correct.blockquote.content } Patrick@336: pointing.blockquote = element blockquote { Patrick@336: blockquote.attributes, pointing.blockquote.content } Patrick@313: Patrick@313: blanks.blockquote.content = Patrick@313: block.head?, Patrick@313: (blanks.p | speech | blanks.list)+, Patrick@313: attribution? Coraline@409: blanks-m.blockquote.content = Coraline@409: block.head?, Coraline@409: (blanks-m.p | speech | blanks-m.list)+, Coraline@409: attribution? Coraline@441: blanks-c.blockquote.content = Coraline@441: block.head?, Coraline@441: (blanks-c.p | speech | blanks-c.list)+, Coraline@441: attribution? Coraline@442: correct.blockquote.content = Coraline@442: block.head?, Coraline@442: (correct.p | speech | correct.list)+, Coraline@442: attribution? Patrick@336: pointing.blockquote.content = Patrick@313: block.head?, Patrick@336: (pointing.p | speech | pointing.list)+, Patrick@313: attribution? Patrick@313: Patrick@313: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ speech ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@313: Patrick@313: # ~~~~~~ speech Patrick@313: blanks.speech = element speech { blanks.speech.content } Coraline@409: blanks-m.speech = element speech { blanks-m.speech.content } Coraline@441: blanks-c.speech = element speech { blanks-c.speech.content } Coraline@442: correct.speech = element speech { correct.speech.content } Patrick@336: pointing.speech = element speech { pointing.speech.content } Patrick@313: Patrick@313: blanks.speech.content = Patrick@313: blanks.speaker?, Patrick@313: stage?, Patrick@313: (blanks.p | blanks.blockquote)+ Coraline@409: blanks-m.speech.content = Coraline@409: blanks-m.speaker?, Coraline@409: stage?, Coraline@409: (blanks-m.p | blanks-m.blockquote)+ Coraline@441: blanks-c.speech.content = Coraline@441: blanks-c.speaker?, Coraline@441: stage?, Coraline@441: (blanks-c.p | blanks-c.blockquote)+ Coraline@442: correct.speech.content = Coraline@442: correct.speaker?, Coraline@442: stage?, Coraline@442: (correct.p | correct.blockquote)+ Patrick@336: pointing.speech.content = Patrick@336: pointing.speaker?, Patrick@313: stage?, Patrick@336: (pointing.p | pointing.blockquote)+ Patrick@313: Patrick@313: # ~~~~~~ speaker Patrick@313: blanks.speaker = element speaker { blanks.speaker.content } Coraline@409: blanks-m.speaker = element speaker { blanks-m.speaker.content } Coraline@441: blanks-c.speaker = element speaker { blanks-c.speaker.content } Coraline@442: correct.speaker = element speaker { correct.speaker.content } Patrick@336: pointing.speaker = element speaker { pointing.speaker.content } Patrick@313: Patrick@313: blanks.speaker.content = blanks.inlines Coraline@409: blanks-m.speaker.content = blanks-m.inlines Coraline@441: blanks-c.speaker.content = blanks-c.inlines Coraline@442: correct.speaker.content = correct.inlines Patrick@336: pointing.speaker.content = pointing.inlines Patrick@313: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: Patrick@313: # ~~~~~~ table patrick@249: blanks.table = element table { table.attributes, blanks.table.content } Coraline@409: blanks-m.table = element table { table.attributes, blanks-m.table.content } Coraline@441: blanks-c.table = element table { table.attributes, blanks-m.table.content } Coraline@442: correct.table = element table { table.attributes, correct.table.content } Patrick@336: pointing.table = element table { table.attributes, pointing.table.content } patrick@73: patrick@73: blanks.table.content = patrick@73: block.head?, Patrick@358: ((thead?, blanks.tbody+) | blanks.tr+), Patrick@313: blanks.table.caption? Coraline@409: blanks-m.table.content = Coraline@409: block.head?, Coraline@409: ((thead?, blanks-m.tbody+) | blanks-m.tr+), Coraline@409: blanks-m.table.caption? Coraline@441: blanks-c.table.content = Coraline@441: block.head?, Coraline@441: ((thead?, blanks-c.tbody+) | blanks-c.tr+), Coraline@441: blanks-c.table.caption? Coraline@442: correct.table.content = Coraline@442: block.head?, Coraline@442: ((thead?, correct.tbody+) | correct.tr+), Coraline@442: correct.table.caption? Patrick@336: pointing.table.content = patrick@73: block.head?, Patrick@358: ((thead?, pointing.tbody+) | pointing.tr+), Patrick@336: pointing.table.caption? patrick@73: patrick@73: # ~~~~~~ tbody patrick@249: blanks.tbody = element tbody { blanks.tbody.content } Coraline@409: blanks-m.tbody = element tbody { blanks-m.tbody.content } Coraline@441: blanks-c.tbody = element tbody { blanks-m.tbody.content } Coraline@442: correct.tbody = element tbody { correct.tbody.content } Patrick@336: pointing.tbody = element tbody { pointing.tbody.content } patrick@73: patrick@73: blanks.tbody.content = patrick@249: blanks.tr+ Coraline@409: blanks-m.tbody.content = Coraline@409: blanks-m.tr+ Coraline@441: blanks-c.tbody.content = Coraline@441: blanks-c.tr+ Coraline@442: correct.tbody.content = Coraline@442: correct.tr+ Patrick@336: pointing.tbody.content = Patrick@336: pointing.tr+ patrick@73: patrick@249: # ~~~~~~ tr patrick@249: blanks.tr = element tr { tr.attributes, blanks.tr.content } Coraline@409: blanks-m.tr = element tr { tr.attributes, blanks-m.tr.content } Coraline@441: blanks-c.tr = element tr { tr.attributes, blanks-c.tr.content } Coraline@442: correct.tr = element tr { tr.attributes, correct.tr.content } Patrick@336: pointing.tr = element tr { tr.attributes, pointing.tr.content } patrick@73: patrick@249: blanks.tr.content = patrick@249: (blanks.td | blanks.th)+ Coraline@409: blanks-m.tr.content = Coraline@409: (blanks-m.td | blanks-m.th)+ Coraline@441: blanks-c.tr.content = Coraline@441: (blanks-c.td | blanks-c.th)+ Coraline@442: correct.tr.content = Coraline@442: (correct.td | correct.th)+ Patrick@336: pointing.tr.content = Patrick@336: (pointing.td | pointing.th)+ patrick@73: patrick@249: # ~~~~~~ td, th patrick@249: blanks.td = element td { td.attributes, blanks.td.content } patrick@249: blanks.th = element th { td.attributes, blanks.td.content } Coraline@409: blanks-m.td = element td { td.attributes, blanks-m.td.content } Coraline@409: blanks-m.th = element th { td.attributes, blanks-m.td.content } Coraline@441: blanks-c.td = element td { td.attributes, blanks-c.td.content } Coraline@441: blanks-c.th = element th { td.attributes, blanks-c.td.content } Coraline@442: correct.td = element td { td.attributes, correct.td.content } Coraline@442: correct.th = element th { td.attributes, correct.td.content } Patrick@336: pointing.td = element td { td.attributes, pointing.td.content } Patrick@336: pointing.th = element th { td.attributes, pointing.td.content } patrick@73: patrick@249: blanks.td.content = patrick@75: blanks.inlines Patrick@313: | (blanks.p | blanks.media)+ Coraline@409: blanks-m.td.content = Coraline@409: blanks-m.inlines Coraline@409: | (blanks-m.p | blanks-m.media)+ Coraline@441: blanks-c.td.content = Coraline@441: blanks-c.inlines Coraline@441: | (blanks-c.p | blanks-c.media)+ Coraline@442: correct.td.content = Coraline@442: correct.inlines Coraline@442: | (correct.p | media)+ Patrick@336: pointing.td.content = Patrick@336: pointing.inlines Patrick@336: | (pointing.p | media)+ Patrick@313: Patrick@313: # ~~~~~~ table.caption Patrick@313: blanks.table.caption = element caption { blanks.caption.content } Coraline@409: blanks-m.table.caption = element caption { blanks-m.caption.content } Coraline@441: blanks-c.table.caption = element caption { blanks-c.caption.content } Coraline@442: correct.table.caption = element caption { correct.caption.content } Patrick@336: pointing.table.caption = element caption { pointing.caption.content } Patrick@313: Patrick@313: blanks.caption.content = Patrick@313: blanks.inlines Patrick@313: | (blanks.p | speech | blanks.list | blockquote)+ Coraline@409: blanks-m.caption.content = Coraline@409: blanks-m.inlines Coraline@409: | (blanks-m.p | speech | blanks-m.list | blockquote)+ Coraline@441: blanks-c.caption.content = Coraline@441: blanks-c.inlines Coraline@441: | (blanks-c.p | speech | blanks-c.list | blockquote)+ Coraline@442: correct.caption.content = Coraline@442: correct.inlines Coraline@442: | (correct.p | speech | correct.list | blockquote)+ Patrick@336: pointing.caption.content = Patrick@336: pointing.inlines Patrick@336: | (pointing.p | speech | pointing.list | blockquote)+ patrick@73: Patrick@174: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ media ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@174: Patrick@313: # ~~~~~~ media Patrick@313: blanks.media = element media { media.attributes, blanks.media.content } Coraline@409: blanks-m.media = element media { media.attributes, blanks-m.media.content } Coraline@441: blanks-c.media = element media { media.attributes, blanks-c.media.content } Coraline@442: correct.media = element media { media.attributes, correct.media.content } Patrick@336: pointing.media = element media { media.attributes, pointing.media.content } Patrick@174: Patrick@313: blanks.media.content = Patrick@174: block.head?, Patrick@174: (blanks.image | audio | video)+, Patrick@313: blanks.media.caption?, Patrick@313: link? Coraline@409: blanks-m.media.content = Coraline@409: block.head?, Coraline@409: (blanks-m.image | audio | video)+, Coraline@409: blanks-m.media.caption?, Coraline@409: link? Coraline@441: blanks-c.media.content = Coraline@441: block.head?, Coraline@441: (image | audio | video)+, Coraline@441: blanks-c.media.caption?, Coraline@441: link? Coraline@442: correct.media.content = Coraline@442: block.head?, Coraline@442: (image | audio | video)+, Coraline@442: correct.media.caption?, Coraline@442: link? Patrick@336: pointing.media.content = Patrick@313: block.head?, Patrick@313: (image | audio | video)+, Patrick@336: pointing.media.caption?, Patrick@174: link? Patrick@174: Patrick@174: # ~~~~~~ blanks.image Patrick@174: blanks.image = element image { image.attributes, blanks.image.content } Coraline@409: blanks-m.image = element image { image.attributes, blanks-m.image.content } Patrick@174: Patrick@174: blanks.image.content = Patrick@174: copyright?, Patrick@192: blanks.dropzone* Coraline@409: blanks-m.image.content = Coraline@409: copyright?, Coraline@409: blanks-m.dropzone* Patrick@174: Patrick@313: # ~~~~~~ dropzone Patrick@192: blanks.dropzone = element dropzone { Patrick@192: blanks.dropzone.attributes, blanks.dropzone.content } Coraline@409: blanks-m.dropzone = element dropzone { Patrick@411: blanks-m.dropzone.attributes, blanks-m.dropzone.content } Patrick@183: Patrick@192: blanks.dropzone.attributes = Patrick@183: x.attribute Patrick@310: & y.attribute Patrick@411: blanks-m.dropzone.attributes = patrick@194: x.attribute patrick@194: & y.attribute Coraline@412: & h.attribute patrick@194: & w.attribute Patrick@174: Patrick@192: blanks.dropzone.content = Patrick@183: blank Coraline@409: blanks-m.dropzone.content = Coraline@409: blank-m Patrick@174: Patrick@313: # ~~~~~~ media.caption Patrick@313: blanks.media.caption = element caption { Patrick@313: caption.attributes, blanks.caption.content } Coraline@409: blanks-m.media.caption = element caption { Coraline@409: caption.attributes, blanks-m.caption.content } Coraline@441: blanks-c.media.caption = element caption { Coraline@441: caption.attributes, blanks-c.caption.content } Coraline@442: correct.media.caption = element caption { Coraline@442: caption.attributes, correct.caption.content } Patrick@336: pointing.media.caption = element caption { Patrick@336: caption.attributes, pointing.caption.content } Patrick@313: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~ choices.right, choices.wrong ~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: choices.right = element right { choices.right.content } patrick@73: choices.wrong = element wrong { choices.right.content } patrick@73: patrick@73: choices.right.content = patrick@73: inlines Patrick@161: | ((p | image | (audio, image?) | video), help?, answer?) patrick@73: Coraline@409: # ~~~~~~~~~~~~~~~~~~~~ blanks.intruders, blanks-m.intruders ~~~~~~~~~~~~~~~~~~ patrick@73: Patrick@342: blanks.intruders = element intruders { blanks.intruders.content } Coraline@409: blanks-m.intruders = element intruders { blanks-m.intruders.content } patrick@73: Coraline@409: blanks.intruders.content = blank+ Coraline@409: blanks-m.intruders.content = blank-m+ patrick@73: Coraline@442: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ correct.intruders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Coraline@442: Coraline@442: correct.intruders = element intruders { correct.intruders.content } Coraline@442: Coraline@442: correct.intruders.content = char+ Coraline@442: Patrick@359: # ~~~~~~~~~~~~~~~~~~~~~~~ matching.intruders, match.item ~~~~~~~~~~~~~~~~~~~~~~ patrick@73: Patrick@359: # ~~~~~~~ matching.intruders Patrick@359: matching.intruders = element intruders { matching.intruders.content } Patrick@359: Patrick@359: matching.intruders.content = Patrick@359: match.item+ Patrick@359: Patrick@359: # ~~~~~~~ match.item Patrick@161: match.item = element item { match.item.content } patrick@73: Patrick@161: match.item.content = Patrick@161: inlines Patrick@341: | (p, help?, answer?) patrick@73: iinov@462: # ~~~~~~~~~~~~~~~~~~~~ sort.intruders, comparison, sort.item ~~~~~~~~~~~~~~~~~~ patrick@73: iinov@461: # ~~~~~~~ sort.intruders iinov@461: sort.intruders = element intruders { sort.intruders.content } iinov@461: iinov@461: sort.intruders.content = iinov@461: sort.item+ iinov@461: iinov@462: # ~~~~~~ comparison iinov@462: comparison = element comparison { comparison.content } iinov@462: iinov@462: comparison.content = inlines iinov@462: patrick@73: # ~~~~~~ sort.item patrick@73: sort.item = element item { sort.item.attributes, sort.item.content } patrick@73: patrick@73: sort.item.attributes = patrick@73: item.shuffle.attribute? patrick@73: item.shuffle.attribute = attribute shuffle { xsd:integer } patrick@73: Patrick@161: sort.item.content = Patrick@161: inlines Patrick@341: | (p, help?, answer?) patrick@73: Patrick@344: # ~~~~~~~~~~~~~~~~~~~~~ categories.intruders, category.item ~~~~~~~~~~~~~~~~~~~ patrick@125: Patrick@344: # ~~~~~~ categories.intruders Patrick@344: categories.intruders = element intruders { categories.intruders.content } Patrick@342: Patrick@344: categories.intruders.content = Patrick@342: category.item+ Patrick@342: Patrick@342: # ~~~~~~ category.item patrick@125: category.item = element item { category.item.content } patrick@125: Patrick@161: category.item.content = Patrick@161: inlines Patrick@341: | (p, help?, answer?) patrick@125: Coraline@438: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ words.item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Coraline@438: words.item = element item {words.item.content, words.item.attributes } Patrick@450: Coraline@438: words.item.content = inlines Coraline@438: Coraline@438: words.item.attributes = Coraline@438: startx Coraline@438: & starty Coraline@438: & endx Coraline@438: & endy Coraline@438: Coraline@438: startx = attribute startx {xsd:token {pattern = "[a-zA-Z]+"}} Coraline@438: starty = attribute starty {xsd:token {pattern = "\d+"}} Coraline@438: endx = attribute endx {xsd:token {pattern = "[a-zA-Z]+"}} Coraline@438: endy = attribute endy {xsd:token {pattern = "\d+"}} Coraline@438: Patrick@450: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ color ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@450: Patrick@450: color = element color { color.attributes } Patrick@450: Patrick@450: color.attributes = Patrick@450: color.code Patrick@450: & color.coderef? Patrick@450: color.code = attribute code {xsd:token { pattern = "#(\d|\w){6}"}} Patrick@450: color.coderef = attribute coderef { list{xsd:token { pattern = "#(\d|\w){6}"}+}} Patrick@450: Patrick@450: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memory-m.item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@450: Patrick@450: memory-m.item = element item { memory-m.item.content } Patrick@450: Patrick@450: memory-m.item.content = image Patrick@450: patrick@73: patrick@73: # ============================================================================= patrick@73: # INLINE LEVEL patrick@73: # ============================================================================= patrick@73: patrick@75: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@75: Patrick@293: blanks.inlines = mixed { Patrick@293: sup* Patrick@293: & sub* Patrick@293: & var* Patrick@293: & number* Patrick@293: & acronym* Patrick@293: & warning* Patrick@293: Patrick@291: & highlight* Patrick@291: & emphasis* Patrick@291: & mentioned* Patrick@350: & literal* Patrick@350: & term* Patrick@291: & stage* Patrick@350: & name* Patrick@350: & foreign* Patrick@350: & date* Patrick@350: & math* Patrick@351: & quote* Patrick@291: & initial* Patrick@291: & note* Patrick@291: & link* Patrick@291: & anchor* Patrick@291: & index* Patrick@351: & image* Patrick@351: & audio* Patrick@351: & smil* Coraline@436: & nowrap* Patrick@293: patrick@75: & blank* Patrick@293: } Patrick@288: Coraline@409: blanks-m.inlines = mixed { Coraline@409: sup* Coraline@409: & sub* Coraline@409: & var* Coraline@409: & number* Coraline@409: & acronym* Coraline@409: & warning* Coraline@409: Coraline@409: & highlight* Coraline@409: & emphasis* Coraline@409: & mentioned* Coraline@409: & literal* Coraline@409: & term* Coraline@409: & stage* Coraline@409: & name* Coraline@409: & foreign* Coraline@409: & date* Coraline@409: & math* Coraline@409: & quote* Coraline@409: & initial* Coraline@409: & note* Coraline@409: & link* Coraline@409: & anchor* Coraline@409: & index* Coraline@409: & image* Coraline@409: & audio* Coraline@409: & smil* Coraline@436: & nowrap* Coraline@409: Coraline@409: & blank-m* Coraline@409: } Coraline@409: Coraline@441: blanks-c.inlines = mixed { Coraline@441: sup* Coraline@441: & sub* Coraline@441: & var* Coraline@441: & number* Coraline@441: & acronym* Coraline@441: & warning* Coraline@441: Coraline@441: & highlight* Coraline@441: & emphasis* Coraline@441: & mentioned* Coraline@441: & literal* Coraline@441: & term* Coraline@441: & stage* Coraline@441: & name* Coraline@441: & foreign* Coraline@441: & date* Coraline@441: & math* Coraline@441: & quote* Coraline@441: & initial* Coraline@441: & note* Coraline@441: & link* Coraline@441: & anchor* Coraline@441: & index* Coraline@441: & image* Coraline@441: & audio* Coraline@441: & smil* Coraline@441: & nowrap* Coraline@441: Coraline@441: & blank-c* Coraline@441: } Coraline@441: Coraline@442: correct.inlines = mixed { Coraline@442: sup* Coraline@442: & sub* Coraline@442: & var* Coraline@442: & number* Coraline@442: & acronym* Coraline@442: & warning* Coraline@442: Coraline@442: & highlight* Coraline@442: & emphasis* Coraline@442: & mentioned* Coraline@442: & literal* Coraline@442: & term* Coraline@442: & stage* Coraline@442: & name* Coraline@442: & foreign* Coraline@442: & date* Coraline@442: & math* Coraline@442: & quote* Coraline@442: & initial* Coraline@442: & note* Coraline@442: & link* Coraline@442: & anchor* Coraline@442: & index* Coraline@442: & image* Coraline@442: & audio* Coraline@442: & smil* Coraline@442: & nowrap* Coraline@442: Coraline@442: & char* Coraline@442: } Coraline@442: Patrick@336: pointing.inlines = mixed { Patrick@293: sup* Patrick@293: & sub* Patrick@293: & var* Patrick@293: & number* Patrick@293: & acronym* Patrick@293: & warning* Patrick@293: Patrick@291: & highlight* Patrick@291: & emphasis* Patrick@291: & mentioned* Patrick@350: & literal* Patrick@350: & term* Patrick@291: & stage* Patrick@350: & name* Patrick@350: & foreign* Patrick@350: & date* Patrick@350: & math* Patrick@351: & quote* Patrick@291: & initial* Patrick@291: & note* Patrick@291: & link* Patrick@291: & anchor* Patrick@291: & index* Patrick@351: & image* Patrick@351: & audio* Patrick@351: & smil* Coraline@436: & nowrap* Patrick@293: Patrick@336: & point* Patrick@293: } patrick@75: iinov@463: dictation.inlines = mixed { iinov@463: warning* iinov@463: & dictation.hint* iinov@463: } iinov@463: Coraline@441: # ~~~~~~~~~~~~~~~~~~~~~~~~~~ blank, blank-m, blank-c ~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: # ~~~~~~ blank Patrick@216: blank = element blank { blank.attributes, blank.content } Patrick@216: Patrick@216: blank.attributes = claire@381: area.attribute? claire@381: & long.attribute? claire@381: area.attribute = attribute area { xsd:boolean } patrick@73: patrick@73: blank.content = patrick@73: text patrick@87: | (s+, help?, answer?) patrick@73: Coraline@409: # ~~~~~~ blank-m Coraline@409: blank-m = element blank { blank-m.content } Patrick@411: blank-m.content = Patrick@411: p Patrick@411: | math Patrick@411: | image Patrick@411: | audio Patrick@411: | (s-m+, help?, answer?) Patrick@450: Coraline@441: # ~~~~~~ blank-c Coraline@441: blank-c = element blank { blank-c.attributes, blank-c.content } Patrick@450: Coraline@441: blank-c.attributes = form.attribute? Coraline@441: form.attribute = attribute form { 'radio' | 'check' } Patrick@450: Coraline@441: blank-c.content = (blank-c.right | blank-c.wrong)+, help?, answer? Coraline@441: blank-c.right = element right { inlines } Patrick@450: blank-c.wrong = element wrong { inlines } Coraline@409: patrick@73: # ~~~~~~ s patrick@73: s = element s { s.content } Coraline@409: s.content = text patrick@73: Coraline@409: # ~~~~~~ s-m Coraline@409: s-m = element s { s-m.content } Patrick@411: s-m.content = Patrick@411: p Patrick@411: | math Patrick@411: | image Patrick@411: | audio Patrick@450: Coraline@442: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Coraline@442: Coraline@442: char = element char { char.attributes, char.content } Coraline@442: Coraline@442: char.attributes = function.attribute? Coraline@442: function.attribute = attribute function { "accent" | "uppercase" } Coraline@442: Coraline@442: char.content = text patrick@73: Patrick@336: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ point ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: Patrick@336: point = element point { point.attributes, point.content } patrick@73: Patrick@336: point.attributes = Patrick@336: point.ref.attribute? Coraline@409: Patrick@340: point.ref.attribute = attribute ref { Patrick@340: "right" | "cat1" | "cat2" | "cat3" | "cat4" | "cat5" } Patrick@336: Patrick@356: point.content = inlines iinov@463: iinov@463: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dictation.hint ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ iinov@463: iinov@463: # ~~~~~~ dictation.hint iinov@463: dictation.hint = element hint { dictation.hint.content } iinov@463: iinov@463: dictation.hint.content = iinov@463: dictation.hint.w, iinov@463: mistake+ iinov@463: iinov@463: # ~~~~~~ dictation.hint.w iinov@463: dictation.hint.w = element w { text } iinov@463: iinov@463: # ~~~~~~ mistake iinov@463: mistake = element mistake { mistake.attributes, mistake.content } iinov@463: iinov@463: mistake.attributes = iinov@463: mistake.is.attribute iinov@463: mistake.is.attribute = attribute is { text } iinov@463: iinov@463: mistake.content = inlines