iinov@476: include "publidoc.rnc" iinov@476: { iinov@476: start = publiquiz patrick@73: iinov@476: document.content = iinov@476: document.head?, iinov@476: (division | document.topic | document.quiz)+ patrick@84: iinov@476: division.content = iinov@476: division.head?, iinov@476: front?, iinov@476: (division | document.topic | document.quiz)+ Coraline@436: iinov@476: nowrap.content = iinov@476: inlines | blanks.inlines | blanks-m.inlines | blanks-c.inlines iinov@476: | pointing.inlines iinov@476: } patrick@73: patrick@75: iinov@476: publiquiz = iinov@476: element publiquiz { iinov@476: publiquiz.attributes, iinov@476: publiquiz.content iinov@476: } patrick@73: patrick@73: publiquiz.attributes = iinov@476: version.attribute patrick@73: patrick@73: publiquiz.content = iinov@476: document iinov@476: | quiz patrick@73: patrick@73: patrick@73: # ============================================================================= iinov@476: # QUIZ patrick@73: # ============================================================================= patrick@73: iinov@476: quiz = element quiz { quiz.attributes, quiz.content } iinov@476: document.quiz = element quiz { document.quiz.attributes, document.quiz.content } patrick@73: iinov@476: quiz.attributes = iinov@476: quiz.id.attribute? iinov@476: & quiz.type.attribute? iinov@476: & lang.attribute? iinov@476: document.quiz.attributes = iinov@476: (quiz.id.attribute | xmlid.attribute)? iinov@476: & quiz.type.attribute? iinov@476: & lang.attribute? patrick@117: quiz.id.attribute = attribute id { xsd:NMTOKEN } Patrick@158: quiz.type.attribute = attribute type { xsd:NCName } patrick@73: patrick@73: quiz.content = iinov@476: component.head?, iinov@476: instructions?, iinov@476: (engine | composite), iinov@476: help?, iinov@476: answer? iinov@476: document.quiz.content = iinov@476: document.component.head?, iinov@476: instructions?, iinov@476: (engine | composite), iinov@476: help?, iinov@476: 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 } iinov@476: blanks-m.section = iinov@476: element section { section.attributes, blanks-m.section.content } iinov@476: blanks-c.section = iinov@476: element section { section.attributes, blanks-c.section.content } iinov@476: correct.section = iinov@476: element section { section.attributes, correct.section.content } iinov@476: pointing.section = iinov@476: element section { section.attributes, pointing.section.content } patrick@73: patrick@73: blanks.section.content = iinov@476: section.head?, iinov@476: (blanks.section+ | blanks.block+) Coraline@409: blanks-m.section.content = iinov@476: section.head?, iinov@476: (blanks-m.section+ | blanks-m.block+) Coraline@441: blanks-c.section.content = iinov@476: section.head?, iinov@476: (blanks-c.section+ | blanks-c.block+) Coraline@442: correct.section.content = iinov@476: section.head?, iinov@476: (correct.section+ | correct.block+) Patrick@336: pointing.section.content = iinov@476: section.head?, iinov@476: (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 = iinov@476: choices-radio iinov@476: | choices-check iinov@476: | blanks-fill iinov@476: | blanks-select iinov@476: | blanks-media iinov@476: | blanks-choices iinov@476: | correct-line iinov@476: | pointing iinov@476: | pointing-categories iinov@476: | matching iinov@476: | sort iinov@476: | categories iinov@476: | wordsearch iinov@476: | flashcard iinov@476: | coloring iinov@476: | memory iinov@476: | dictation iinov@476: | production patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ choices ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: iinov@476: choices-radio = iinov@476: element choices-radio { choices-radio.attributes, choices-radio.content } iinov@476: choices-check = iinov@476: element choices-check { choices-check.attributes, choices-check.content } patrick@73: Patrick@376: choices-radio.attributes = iinov@476: shuffle.attribute? Patrick@376: choices-check.attributes = iinov@476: success.attribute? iinov@476: & 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 = iinov@476: choices.right iinov@476: & choices.wrong+ patrick@87: choices-check.content = iinov@476: (choices.right | choices.wrong)+ patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ blanks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: iinov@476: blanks-fill = iinov@476: element blanks-fill { blanks-fill.attributes, blanks-fill.content } iinov@476: blanks-select = iinov@476: element blanks-select { blanks-select.attributes, blanks-select.content } iinov@476: blanks-media = iinov@476: element blanks-media { blanks-select.attributes, blanks-media.content } iinov@476: blanks-choices = iinov@476: element blanks-choices { blanks-choices.content } patrick@73: patrick@87: blanks-fill.attributes = iinov@476: success.attribute? iinov@476: & strict.attribute? iinov@476: & long.attribute? patrick@87: blanks-select.attributes = iinov@476: success.attribute? iinov@476: & multiple.attribute? iinov@476: & noshuffle.attribute? iinov@476: & 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 = iinov@478: (blanks.block+ | blanks.section+), iinov@478: keyboard patrick@87: blanks-select.content = iinov@476: blanks.intruders?, iinov@476: (blanks.block+ | blanks.section+) Coraline@409: blanks-media.content = iinov@476: blanks-m.intruders?, iinov@476: (blanks-m.block+ | blanks-m.section+) Coraline@441: blanks-choices.content = iinov@476: (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 = iinov@476: remove-space.attribute? Coraline@402: remove-space.attribute = attribute remove-space { xsd:boolean } Coraline@402: Coraline@442: correct.content = iinov@476: correct.intruders?, iinov@476: (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 = iinov@476: success.attribute? iinov@476: & pointing.type.attribute? Patrick@336: pointing.type.attribute = attribute type { "radio" | "check" } patrick@73: Patrick@336: pointing.content = iinov@476: (pointing.section+ | pointing.block+) Patrick@336: Patrick@336: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pointing-categories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@336: Patrick@336: # ~~~~~~ pointing-categories iinov@476: pointing-categories = iinov@476: element pointing-categories { pointing-c.attributes, pointing-c.content } Patrick@376: Patrick@376: pointing-c.attributes = iinov@476: success.attribute? Patrick@336: Patrick@336: pointing-c.content = iinov@476: pointing-c.categories, iinov@476: 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 = iinov@476: pointing-c.category1, iinov@476: pointing-c.category2, iinov@476: (pointing-c.category3, iinov@476: (pointing-c.category4, pointing-c.category5?)?)? Patrick@336: Patrick@336: # ~~~~~~ pointing-c.categoryN iinov@476: pointing-c.category1 = iinov@476: element category { attribute id { "1" }, pointing-c.category.content } iinov@476: pointing-c.category2 = iinov@476: element category { attribute id { "2" }, pointing-c.category.content } iinov@476: pointing-c.category3 = iinov@476: element category { attribute id { "3" }, pointing-c.category.content } iinov@476: pointing-c.category4 = iinov@476: element category { attribute id { "4" }, pointing-c.category.content } iinov@476: pointing-c.category5 = iinov@476: element category { 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 = iinov@476: success.attribute? iinov@476: & multiple.attribute? iinov@476: & noshuffle.attribute? iinov@476: & orientation.attribute? patrick@75: patrick@73: matching.content = iinov@476: matching.intruders?, iinov@476: match, iinov@476: match+ patrick@73: Patrick@161: # ~~~~~~ match Patrick@161: match = element match { match.content } Patrick@161: Patrick@161: match.content = iinov@476: match.item, iinov@476: match.item Patrick@161: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sort ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: sort = element sort { sort.attributes, sort.content } patrick@73: patrick@73: sort.attributes = iinov@476: success.attribute? iinov@476: & shuffle.attribute? iinov@476: & 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 = iinov@476: title iinov@476: & shorttitle? iinov@476: & subtitle* Patrick@310: patrick@125: # ~~~~~~ categories Patrick@168: categories = element categories { categories.attributes, categories.content } patrick@125: Patrick@168: categories.attributes = iinov@476: success.attribute? iinov@476: & multiple.attribute? iinov@476: & noshuffle.attribute? iinov@476: & orientation.attribute? Patrick@310: patrick@125: categories.content = iinov@476: categories.intruders?, iinov@476: category, iinov@476: category+ patrick@125: patrick@125: # ~~~~~~ category patrick@125: category = element category { category.content } patrick@125: patrick@125: category.content = iinov@476: category.head, iinov@476: category.item* patrick@125: Coraline@438: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wordsearch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Patrick@448: Coraline@438: wordsearch = element wordsearch {wordsearch.attributes, wordsearch.content } Coraline@438: Coraline@438: wordsearch.attributes = iinov@476: strict.attribute ? iinov@476: & wordlist.attribute ? Coraline@438: Coraline@438: wordlist.attribute = attribute wordlist { "hidden" | "right" | "left" } Coraline@438: Coraline@438: wordsearch.content = iinov@476: words iinov@476: & 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 = iinov@476: side1, iinov@476: 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 iinov@476: & canvas iinov@476: & 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 = iinov@476: memory.match, iinov@476: 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@465: dictation = element dictation { dictation.attributes, dictation.content } iinov@465: iinov@465: dictation.attributes = iinov@465: case_insensitive.attribute? iinov@465: case_insensitive.attribute = attribute case-insensitive { xsd:boolean } iinov@463: iinov@463: dictation.content = iinov@472: dictation.media, iinov@465: dictation.p 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 = iinov@476: success.attribute? iinov@476: & multipage.attribute? Patrick@310: multipage.attribute = attribute multipage { xsd:boolean } patrick@75: patrick@73: composite.content = iinov@476: subquiz, iinov@476: subquiz+ patrick@77: patrick@85: # ~~~~~~ subquiz patrick@85: subquiz = element subquiz { subquiz.content } patrick@77: patrick@85: subquiz.content = iinov@476: instructions?, iinov@476: engine, iinov@476: help?, iinov@476: answer? patrick@73: iinov@478: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ keyboard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ iinov@478: iinov@478: # ~~~~~~ keyboard iinov@478: keyboard = element keyboard { keyboard.content } iinov@478: iinov@478: keyboard.content = iinov@478: keyboard.key+ iinov@478: iinov@478: # ~~~~~~ keyboard.key iinov@478: keyboard.key = element key { keyboard.key.content } iinov@478: iinov@478: keyboard.key.content = xsd:token {pattern = "."} iinov@478: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ help ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@73: help = element help { help.content } patrick@73: patrick@73: help.content = iinov@476: (section+ | block+)?, iinov@476: link* patrick@73: patrick@87: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ answer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: patrick@87: answer = element answer { answer.content } patrick@73: patrick@87: answer.content = iinov@476: (section+ | block+)?, iinov@476: link* patrick@73: patrick@73: patrick@73: # ============================================================================= patrick@73: # BLOCK LEVEL patrick@73: # ============================================================================= patrick@73: patrick@73: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ block ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ patrick@73: iinov@476: blanks.block = iinov@476: (blanks.p | blanks.list | blanks.blockquote | blanks.speech | blanks.table iinov@476: | blanks.media) iinov@476: blanks-m.block = iinov@476: (blanks-m.p | blanks-m.list | blanks-m.blockquote | blanks-m.speech iinov@476: | blanks-m.table | blanks-m.media) iinov@476: blanks-c.block = iinov@476: (blanks-c.p | blanks-c.list | blanks-c.blockquote | blanks-c.speech iinov@476: | blanks-c.table | blanks-c.media) iinov@476: correct.block = iinov@476: (correct.p | correct.list | correct.blockquote | correct.speech iinov@476: | correct.table | media) iinov@476: pointing.block = iinov@476: (pointing.p | pointing.list | pointing.blockquote | pointing.speech iinov@476: | pointing.table | media) 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 iinov@476: blanks.list = iinov@476: element list { iinov@476: block.head?, iinov@476: ( (attribute type {"ordered"}?, blanks.item, blanks.item+) | iinov@476: (attribute type {"glossary"}, item.glossary+) ) } iinov@476: blanks-m.list = iinov@476: element list { iinov@476: block.head?, iinov@476: ( (attribute type {"ordered"}?, blanks-m.item, blanks-m.item+) | iinov@476: (attribute type {"glossary"}, item.glossary+) ) } iinov@476: blanks-c.list = iinov@476: element list { iinov@476: block.head?, iinov@476: ( (attribute type {"ordered"}?, blanks.item, blanks.item+) | iinov@476: (attribute type {"glossary"}, item.glossary+) ) } iinov@476: correct.list = iinov@476: element list { iinov@476: block.head?, iinov@476: ( (attribute type {"ordered"}?, correct.item, correct.item+) | iinov@476: (attribute type {"glossary"}, item.glossary+) ) } iinov@476: pointing.list = iinov@476: element list { iinov@476: block.head?, iinov@476: ( (attribute type {"ordered"}?, pointing.item, pointing.item+) | iinov@476: (attribute type {"glossary"}, item.glossary+) ) } 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: iinov@476: blanks.blockquote = iinov@476: element blockquote { blockquote.attributes, blanks.blockquote.content } iinov@476: blanks-m.blockquote = iinov@476: element blockquote { blockquote.attributes, blanks-m.blockquote.content } iinov@476: blanks-c.blockquote = iinov@476: element blockquote { blockquote.attributes, blanks-c.blockquote.content } iinov@476: correct.blockquote = iinov@476: element blockquote { blockquote.attributes, correct.blockquote.content } iinov@476: pointing.blockquote = iinov@476: element blockquote { blockquote.attributes, pointing.blockquote.content } Patrick@313: Patrick@313: blanks.blockquote.content = iinov@476: block.head?, iinov@476: (blanks.p | speech | blanks.list)+, iinov@476: attribution? Coraline@409: blanks-m.blockquote.content = iinov@476: block.head?, iinov@476: (blanks-m.p | speech | blanks-m.list)+, iinov@476: attribution? Coraline@441: blanks-c.blockquote.content = iinov@476: block.head?, iinov@476: (blanks-c.p | speech | blanks-c.list)+, iinov@476: attribution? Coraline@442: correct.blockquote.content = iinov@476: block.head?, iinov@476: (correct.p | speech | correct.list)+, iinov@476: attribution? Patrick@336: pointing.blockquote.content = iinov@476: block.head?, iinov@476: (pointing.p | speech | pointing.list)+, iinov@476: 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 = iinov@476: blanks.speaker?, iinov@476: stage?, iinov@476: (blanks.p | blanks.blockquote)+ Coraline@409: blanks-m.speech.content = iinov@476: blanks-m.speaker?, iinov@476: stage?, iinov@476: (blanks-m.p | blanks-m.blockquote)+ Coraline@441: blanks-c.speech.content = iinov@476: blanks-c.speaker?, iinov@476: stage?, iinov@476: (blanks-c.p | blanks-c.blockquote)+ Coraline@442: correct.speech.content = iinov@476: correct.speaker?, iinov@476: stage?, iinov@476: (correct.p | correct.blockquote)+ Patrick@336: pointing.speech.content = iinov@476: pointing.speaker?, iinov@476: stage?, iinov@476: (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 = iinov@476: block.head?, iinov@476: ((thead?, blanks.tbody+) | blanks.tr+), iinov@476: blanks.table.caption? Coraline@409: blanks-m.table.content = iinov@476: block.head?, iinov@476: ((thead?, blanks-m.tbody+) | blanks-m.tr+), iinov@476: blanks-m.table.caption? Coraline@441: blanks-c.table.content = iinov@476: block.head?, iinov@476: ((thead?, blanks-c.tbody+) | blanks-c.tr+), iinov@476: blanks-c.table.caption? Coraline@442: correct.table.content = iinov@476: block.head?, iinov@476: ((thead?, correct.tbody+) | correct.tr+), iinov@476: correct.table.caption? Patrick@336: pointing.table.content = iinov@476: block.head?, iinov@476: ((thead?, pointing.tbody+) | pointing.tr+), iinov@476: 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 = iinov@476: blanks.tr+ Coraline@409: blanks-m.tbody.content = iinov@476: blanks-m.tr+ Coraline@441: blanks-c.tbody.content = iinov@476: blanks-c.tr+ Coraline@442: correct.tbody.content = iinov@476: correct.tr+ Patrick@336: pointing.tbody.content = iinov@476: 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 = iinov@476: (blanks.td | blanks.th)+ Coraline@409: blanks-m.tr.content = iinov@476: (blanks-m.td | blanks-m.th)+ Coraline@441: blanks-c.tr.content = iinov@476: (blanks-c.td | blanks-c.th)+ Coraline@442: correct.tr.content = iinov@476: (correct.td | correct.th)+ Patrick@336: pointing.tr.content = iinov@476: (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 = iinov@476: blanks.inlines iinov@476: | (blanks.p | blanks.media)+ Coraline@409: blanks-m.td.content = iinov@476: blanks-m.inlines iinov@476: | (blanks-m.p | blanks-m.media)+ Coraline@441: blanks-c.td.content = iinov@476: blanks-c.inlines iinov@476: | (blanks-c.p | blanks-c.media)+ Coraline@442: correct.td.content = iinov@476: correct.inlines iinov@476: | (correct.p | media)+ Patrick@336: pointing.td.content = iinov@476: pointing.inlines iinov@476: | (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 = iinov@476: blanks.inlines iinov@476: | (blanks.p | speech | blanks.list | blockquote)+ Coraline@409: blanks-m.caption.content = iinov@476: blanks-m.inlines iinov@476: | (blanks-m.p | speech | blanks-m.list | blockquote)+ Coraline@441: blanks-c.caption.content = iinov@476: blanks-c.inlines iinov@476: | (blanks-c.p | speech | blanks-c.list | blockquote)+ Coraline@442: correct.caption.content = iinov@476: correct.inlines iinov@476: | (correct.p | speech | correct.list | blockquote)+ Patrick@336: pointing.caption.content = iinov@476: pointing.inlines iinov@476: | (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 } iinov@472: dictation.media = element media { media.attributes, dictation.media.content } Patrick@174: Patrick@313: blanks.media.content = iinov@476: block.head?, iinov@476: (blanks.image | audio | video)+, iinov@476: blanks.media.caption?, iinov@476: link? Coraline@409: blanks-m.media.content = iinov@476: block.head?, iinov@476: (blanks-m.image | audio | video)+, iinov@476: blanks-m.media.caption?, iinov@476: link? Coraline@441: blanks-c.media.content = iinov@476: block.head?, iinov@476: (image | audio | video)+, iinov@476: blanks-c.media.caption?, iinov@476: link? Coraline@442: correct.media.content = iinov@476: block.head?, iinov@476: (image | audio | video)+, iinov@476: correct.media.caption?, iinov@476: link? Patrick@336: pointing.media.content = iinov@476: block.head?, iinov@476: (image | audio | video)+, iinov@476: pointing.media.caption?, iinov@476: link? iinov@472: dictation.media.content = iinov@476: audio 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 = iinov@476: copyright?, iinov@476: blanks.dropzone* Coraline@409: blanks-m.image.content = iinov@476: copyright?, iinov@476: blanks-m.dropzone* Patrick@174: Patrick@313: # ~~~~~~ dropzone iinov@476: blanks.dropzone = iinov@476: element dropzone { blanks.dropzone.attributes, blanks.dropzone.content } iinov@476: blanks-m.dropzone = iinov@476: element dropzone { blanks-m.dropzone.attributes, blanks-m.dropzone.content } Patrick@183: Patrick@192: blanks.dropzone.attributes = iinov@476: x.attribute iinov@476: & y.attribute Patrick@411: blanks-m.dropzone.attributes = iinov@476: x.attribute iinov@476: & y.attribute iinov@476: & h.attribute iinov@476: & w.attribute Patrick@174: Patrick@192: blanks.dropzone.content = iinov@476: blank Coraline@409: blanks-m.dropzone.content = iinov@476: blank-m Patrick@174: Patrick@313: # ~~~~~~ media.caption iinov@476: blanks.media.caption = iinov@476: element caption { caption.attributes, blanks.caption.content } iinov@476: blanks-m.media.caption = iinov@476: element caption { caption.attributes, blanks-m.caption.content } iinov@476: blanks-c.media.caption = iinov@476: element caption { caption.attributes, blanks-c.caption.content } iinov@476: correct.media.caption = iinov@476: element caption { caption.attributes, correct.caption.content } iinov@476: pointing.media.caption = iinov@476: element caption { 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 = iinov@476: inlines iinov@476: | ((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 = iinov@476: match.item+ Patrick@359: Patrick@359: # ~~~~~~~ match.item Patrick@161: match.item = element item { match.item.content } patrick@73: Patrick@161: match.item.content = iinov@476: inlines iinov@476: | (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@476: 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 = iinov@476: item.shuffle.attribute? patrick@73: item.shuffle.attribute = attribute shuffle { xsd:integer } patrick@73: Patrick@161: sort.item.content = iinov@476: inlines iinov@476: | (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 = iinov@476: category.item+ Patrick@342: Patrick@342: # ~~~~~~ category.item patrick@125: category.item = element item { category.item.content } patrick@125: Patrick@161: category.item.content = iinov@476: inlines iinov@476: | (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 = iinov@476: startx iinov@476: & starty iinov@476: & endx iinov@476: & 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: iinov@476: blanks.inlines = iinov@476: mixed { iinov@476: sup* & sub* iinov@476: & var* iinov@476: & number* iinov@476: & acronym* iinov@476: & warning* Patrick@293: iinov@476: & highlight* iinov@476: & emphasis* iinov@476: & mentioned* iinov@476: & literal* iinov@476: & term* iinov@476: & stage* iinov@476: & name* iinov@476: & foreign* iinov@476: & date* iinov@476: & math* iinov@476: & quote* iinov@476: & initial* iinov@476: & note* iinov@476: & link* iinov@476: & anchor* iinov@476: & index* iinov@476: & image* iinov@476: & audio* iinov@476: & smil* iinov@476: & nowrap* Patrick@293: iinov@476: & blank* iinov@476: } Patrick@288: iinov@476: blanks-m.inlines = iinov@476: mixed { iinov@476: sup* & sub* iinov@476: & var* iinov@476: & number* iinov@476: & acronym* iinov@476: & warning* Coraline@409: iinov@476: & highlight* iinov@476: & emphasis* iinov@476: & mentioned* iinov@476: & literal* iinov@476: & term* iinov@476: & stage* iinov@476: & name* iinov@476: & foreign* iinov@476: & date* iinov@476: & math* iinov@476: & quote* iinov@476: & initial* iinov@476: & note* iinov@476: & link* iinov@476: & anchor* iinov@476: & index* iinov@476: & image* iinov@476: & audio* iinov@476: & smil* iinov@476: & nowrap* Coraline@409: iinov@476: & blank-m* iinov@476: } Coraline@409: iinov@476: blanks-c.inlines = iinov@476: mixed { iinov@476: sup* & sub* iinov@476: & var* iinov@476: & number* iinov@476: & acronym* iinov@476: & warning* Coraline@441: iinov@476: & highlight* iinov@476: & emphasis* iinov@476: & mentioned* iinov@476: & literal* iinov@476: & term* iinov@476: & stage* iinov@476: & name* iinov@476: & foreign* iinov@476: & date* iinov@476: & math* iinov@476: & quote* iinov@476: & initial* iinov@476: & note* iinov@476: & link* iinov@476: & anchor* iinov@476: & index* iinov@476: & image* iinov@476: & audio* iinov@476: & smil* iinov@476: & nowrap* Coraline@441: iinov@476: & blank-c* iinov@476: } Coraline@441: iinov@476: correct.inlines = iinov@476: mixed { iinov@476: sup* & sub* iinov@476: & var* iinov@476: & number* iinov@476: & acronym* iinov@476: & warning* Coraline@442: iinov@476: & highlight* iinov@476: & emphasis* iinov@476: & mentioned* iinov@476: & literal* iinov@476: & term* iinov@476: & stage* iinov@476: & name* iinov@476: & foreign* iinov@476: & date* iinov@476: & math* iinov@476: & quote* iinov@476: & initial* iinov@476: & note* iinov@476: & link* iinov@476: & anchor* iinov@476: & index* iinov@476: & image* iinov@476: & audio* iinov@476: & smil* iinov@476: & nowrap* Coraline@442: iinov@476: & char* iinov@476: } Coraline@442: iinov@476: pointing.inlines = iinov@476: mixed { iinov@476: sup* & sub* iinov@476: & var* iinov@476: & number* iinov@476: & acronym* iinov@476: & warning* Patrick@293: iinov@476: & highlight* iinov@476: & emphasis* iinov@476: & mentioned* iinov@476: & literal* iinov@476: & term* iinov@476: & stage* iinov@476: & name* iinov@476: & foreign* iinov@476: & date* iinov@476: & math* iinov@476: & quote* iinov@476: & initial* iinov@476: & note* iinov@476: & link* iinov@476: & anchor* iinov@476: & index* iinov@476: & image* iinov@476: & audio* iinov@476: & smil* iinov@476: & nowrap* Patrick@293: iinov@476: & point* iinov@476: } patrick@75: iinov@476: dictation.inlines = mixed { warning* & dictation.hint* } 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 = iinov@476: area.attribute? iinov@476: & long.attribute? claire@381: area.attribute = attribute area { xsd:boolean } patrick@73: patrick@73: blank.content = iinov@476: text iinov@476: | (s+, help?, answer?) patrick@73: Coraline@409: # ~~~~~~ blank-m Coraline@409: blank-m = element blank { blank-m.content } Patrick@411: blank-m.content = iinov@476: p iinov@476: | math iinov@476: | image iinov@476: | audio iinov@476: | (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 = iinov@476: p iinov@476: | math iinov@476: | image iinov@476: | 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 = iinov@476: point.ref.attribute? Coraline@409: iinov@476: point.ref.attribute = iinov@476: attribute ref { "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@476: mistake.is.attribute? iinov@463: mistake.is.attribute = attribute is { text } iinov@463: iinov@463: mistake.content = inlines