RelaxNG/publiquiz.rnc
author iinov
mer., 14 août 2019 20:01:39 +0200
changeset 478 90e0fdca7fb7
parent 476 6c30a3543cd8
child 479 5061282c7396
permissions -rw-r--r--
Exemple de clavier
iinov@476
     1
include "publidoc.rnc"
iinov@476
     2
    {
iinov@476
     3
     start = publiquiz
patrick@73
     4
iinov@476
     5
     document.content =
iinov@476
     6
         document.head?,
iinov@476
     7
         (division | document.topic | document.quiz)+
patrick@84
     8
iinov@476
     9
     division.content =
iinov@476
    10
         division.head?,
iinov@476
    11
         front?,
iinov@476
    12
         (division | document.topic | document.quiz)+
Coraline@436
    13
iinov@476
    14
     nowrap.content =
iinov@476
    15
         inlines | blanks.inlines | blanks-m.inlines | blanks-c.inlines
iinov@476
    16
         | pointing.inlines
iinov@476
    17
    }
patrick@73
    18
patrick@75
    19
iinov@476
    20
publiquiz =
iinov@476
    21
    element publiquiz {
iinov@476
    22
        publiquiz.attributes,
iinov@476
    23
        publiquiz.content
iinov@476
    24
    }
patrick@73
    25
patrick@73
    26
publiquiz.attributes =
iinov@476
    27
    version.attribute
patrick@73
    28
patrick@73
    29
publiquiz.content =
iinov@476
    30
    document
iinov@476
    31
    | quiz
patrick@73
    32
patrick@73
    33
patrick@73
    34
# =============================================================================
iinov@476
    35
#                                    QUIZ
patrick@73
    36
# =============================================================================
patrick@73
    37
iinov@476
    38
quiz = element quiz { quiz.attributes, quiz.content }
iinov@476
    39
document.quiz = element quiz { document.quiz.attributes, document.quiz.content }
patrick@73
    40
iinov@476
    41
quiz.attributes =
iinov@476
    42
    quiz.id.attribute?
iinov@476
    43
    & quiz.type.attribute?
iinov@476
    44
    & lang.attribute?
iinov@476
    45
document.quiz.attributes =
iinov@476
    46
    (quiz.id.attribute | xmlid.attribute)?
iinov@476
    47
    & quiz.type.attribute?
iinov@476
    48
    & lang.attribute?
patrick@117
    49
quiz.id.attribute = attribute id { xsd:NMTOKEN }
Patrick@158
    50
quiz.type.attribute = attribute type { xsd:NCName }
patrick@73
    51
patrick@73
    52
quiz.content =
iinov@476
    53
    component.head?,
iinov@476
    54
    instructions?,
iinov@476
    55
    (engine | composite),
iinov@476
    56
    help?,
iinov@476
    57
    answer?
iinov@476
    58
document.quiz.content =
iinov@476
    59
    document.component.head?,
iinov@476
    60
    instructions?,
iinov@476
    61
    (engine | composite),
iinov@476
    62
    help?,
iinov@476
    63
    answer?
patrick@73
    64
patrick@73
    65
patrick@73
    66
# =============================================================================
patrick@73
    67
#                                 SECTION LEVEL
patrick@73
    68
# =============================================================================
patrick@73
    69
patrick@73
    70
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ section ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
    71
patrick@73
    72
blanks.section = element section { section.attributes, blanks.section.content }
iinov@476
    73
blanks-m.section =
iinov@476
    74
    element section { section.attributes, blanks-m.section.content }
iinov@476
    75
blanks-c.section =
iinov@476
    76
    element section { section.attributes, blanks-c.section.content }
iinov@476
    77
correct.section =
iinov@476
    78
    element section { section.attributes, correct.section.content }
iinov@476
    79
pointing.section =
iinov@476
    80
    element section { section.attributes, pointing.section.content }
patrick@73
    81
patrick@73
    82
blanks.section.content =
iinov@476
    83
    section.head?,
iinov@476
    84
    (blanks.section+ | blanks.block+)
Coraline@409
    85
blanks-m.section.content =
iinov@476
    86
    section.head?,
iinov@476
    87
    (blanks-m.section+ | blanks-m.block+)
Coraline@441
    88
blanks-c.section.content =
iinov@476
    89
    section.head?,
iinov@476
    90
    (blanks-c.section+ | blanks-c.block+)
Coraline@442
    91
correct.section.content =
iinov@476
    92
    section.head?,
iinov@476
    93
    (correct.section+ | correct.block+)
Patrick@336
    94
pointing.section.content =
iinov@476
    95
    section.head?,
iinov@476
    96
    (pointing.section+ | pointing.block+)
patrick@73
    97
patrick@73
    98
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ instructions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
    99
patrick@73
   100
instructions = element instructions { section.content }
patrick@73
   101
patrick@73
   102
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ engine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   103
patrick@73
   104
engine =
iinov@476
   105
    choices-radio
iinov@476
   106
    | choices-check
iinov@476
   107
    | blanks-fill
iinov@476
   108
    | blanks-select
iinov@476
   109
    | blanks-media
iinov@476
   110
    | blanks-choices
iinov@476
   111
    | correct-line
iinov@476
   112
    | pointing
iinov@476
   113
    | pointing-categories
iinov@476
   114
    | matching
iinov@476
   115
    | sort
iinov@476
   116
    | categories
iinov@476
   117
    | wordsearch
iinov@476
   118
    | flashcard
iinov@476
   119
    | coloring
iinov@476
   120
    | memory
iinov@476
   121
    | dictation
iinov@476
   122
    | production
patrick@73
   123
patrick@73
   124
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ choices ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   125
iinov@476
   126
choices-radio =
iinov@476
   127
    element choices-radio { choices-radio.attributes, choices-radio.content }
iinov@476
   128
choices-check =
iinov@476
   129
    element choices-check { choices-check.attributes, choices-check.content }
patrick@73
   130
Patrick@376
   131
choices-radio.attributes =
iinov@476
   132
    shuffle.attribute?
Patrick@376
   133
choices-check.attributes =
iinov@476
   134
    success.attribute?
iinov@476
   135
    & shuffle.attribute?
Patrick@376
   136
success.attribute = attribute success { xsd:decimal {maxInclusive="1"} }
patrick@73
   137
shuffle.attribute = attribute shuffle { xsd:boolean }
patrick@73
   138
patrick@87
   139
choices-radio.content =
iinov@476
   140
    choices.right
iinov@476
   141
    & choices.wrong+
patrick@87
   142
choices-check.content =
iinov@476
   143
    (choices.right | choices.wrong)+
patrick@73
   144
patrick@73
   145
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ blanks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   146
iinov@476
   147
blanks-fill =
iinov@476
   148
    element blanks-fill { blanks-fill.attributes, blanks-fill.content }
iinov@476
   149
blanks-select =
iinov@476
   150
    element blanks-select { blanks-select.attributes, blanks-select.content }
iinov@476
   151
blanks-media =
iinov@476
   152
    element blanks-media { blanks-select.attributes, blanks-media.content }
iinov@476
   153
blanks-choices =
iinov@476
   154
    element blanks-choices { blanks-choices.content }
patrick@73
   155
patrick@87
   156
blanks-fill.attributes =
iinov@476
   157
    success.attribute?
iinov@476
   158
    & strict.attribute?
iinov@476
   159
    & long.attribute?
patrick@87
   160
blanks-select.attributes =
iinov@476
   161
    success.attribute?
iinov@476
   162
    & multiple.attribute?
iinov@476
   163
    & noshuffle.attribute?
iinov@476
   164
    & orientation.attribute?
patrick@73
   165
strict.attribute = attribute strict { xsd:boolean }
patrick@73
   166
multiple.attribute = attribute multiple { xsd:boolean }
Coraline@437
   167
noshuffle.attribute = attribute no-shuffle { "true" | "false" | "alpha" }
claire@381
   168
long.attribute = attribute long { xsd:positiveInteger }
Coraline@409
   169
orientation.attribute = attribute orientation {"north"|"east"|"west"|"south"}
patrick@73
   170
patrick@87
   171
blanks-fill.content =
iinov@478
   172
    (blanks.block+ | blanks.section+),
iinov@478
   173
    keyboard
patrick@87
   174
blanks-select.content =
iinov@476
   175
    blanks.intruders?,
iinov@476
   176
    (blanks.block+ | blanks.section+)
Coraline@409
   177
blanks-media.content =
iinov@476
   178
    blanks-m.intruders?,
iinov@476
   179
    (blanks-m.block+ | blanks-m.section+)
Coraline@441
   180
blanks-choices.content =
iinov@476
   181
    (blanks-c.block+ | blanks-c.section+)
patrick@73
   182
Coraline@442
   183
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ correct-line ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@448
   184
Patrick@448
   185
correct-line = element correct-line { correct.attributes, correct.content }
Coraline@442
   186
Patrick@450
   187
correct.attributes =
iinov@476
   188
    remove-space.attribute?
Coraline@402
   189
remove-space.attribute = attribute remove-space { xsd:boolean }
Coraline@402
   190
Coraline@442
   191
correct.content =
iinov@476
   192
    correct.intruders?,
iinov@476
   193
    (correct.block+ | correct.section+)
Coraline@442
   194
Patrick@336
   195
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pointing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   196
Patrick@336
   197
pointing = element pointing { pointing.attributes, pointing.content }
patrick@75
   198
Patrick@336
   199
pointing.attributes =
iinov@476
   200
    success.attribute?
iinov@476
   201
    & pointing.type.attribute?
Patrick@336
   202
pointing.type.attribute = attribute type { "radio" | "check" }
patrick@73
   203
Patrick@336
   204
pointing.content =
iinov@476
   205
    (pointing.section+ | pointing.block+)
Patrick@336
   206
Patrick@336
   207
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pointing-categories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@336
   208
Patrick@336
   209
# ~~~~~~ pointing-categories
iinov@476
   210
pointing-categories =
iinov@476
   211
    element pointing-categories { pointing-c.attributes, pointing-c.content }
Patrick@376
   212
Patrick@376
   213
pointing-c.attributes =
iinov@476
   214
    success.attribute?
Patrick@336
   215
Patrick@336
   216
pointing-c.content =
iinov@476
   217
    pointing-c.categories,
iinov@476
   218
    pointing.section
Patrick@336
   219
Patrick@336
   220
# ~~~~~~ pointing-c.categories
Patrick@336
   221
pointing-c.categories = element categories { pointing-c.categories.content }
Patrick@336
   222
Patrick@336
   223
pointing-c.categories.content =
iinov@476
   224
    pointing-c.category1,
iinov@476
   225
    pointing-c.category2,
iinov@476
   226
    (pointing-c.category3,
iinov@476
   227
     (pointing-c.category4, pointing-c.category5?)?)?
Patrick@336
   228
Patrick@336
   229
# ~~~~~~ pointing-c.categoryN
iinov@476
   230
pointing-c.category1 =
iinov@476
   231
    element category { attribute id { "1" }, pointing-c.category.content }
iinov@476
   232
pointing-c.category2 =
iinov@476
   233
    element category { attribute id { "2" }, pointing-c.category.content }
iinov@476
   234
pointing-c.category3 =
iinov@476
   235
    element category { attribute id { "3" }, pointing-c.category.content }
iinov@476
   236
pointing-c.category4 =
iinov@476
   237
    element category { attribute id { "4" }, pointing-c.category.content }
iinov@476
   238
pointing-c.category5 =
iinov@476
   239
    element category { attribute id { "5" }, pointing-c.category.content }
Patrick@336
   240
Patrick@336
   241
pointing-c.category.content = inlines
Patrick@336
   242
patrick@73
   243
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ matching ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   244
Patrick@161
   245
# ~~~~~~ matching
Patrick@169
   246
matching = element matching { matching.attributes, matching.content }
Patrick@169
   247
Patrick@169
   248
matching.attributes =
iinov@476
   249
    success.attribute?
iinov@476
   250
    & multiple.attribute?
iinov@476
   251
    & noshuffle.attribute?
iinov@476
   252
    & orientation.attribute?
patrick@75
   253
patrick@73
   254
matching.content =
iinov@476
   255
    matching.intruders?,
iinov@476
   256
    match,
iinov@476
   257
    match+
patrick@73
   258
Patrick@161
   259
# ~~~~~~ match
Patrick@161
   260
match = element match { match.content }
Patrick@161
   261
Patrick@161
   262
match.content =
iinov@476
   263
    match.item,
iinov@476
   264
    match.item
Patrick@161
   265
patrick@73
   266
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sort ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   267
patrick@73
   268
sort = element sort { sort.attributes, sort.content }
patrick@73
   269
patrick@73
   270
sort.attributes =
iinov@476
   271
    success.attribute?
iinov@476
   272
    & shuffle.attribute?
iinov@476
   273
    & orientation.attribute?
patrick@75
   274
patrick@73
   275
sort.content =
iinov@462
   276
    sort.intruders?,
iinov@461
   277
    comparison?,
iinov@461
   278
    sort.item,
iinov@461
   279
    sort.item+
patrick@73
   280
patrick@125
   281
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ categories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@125
   282
Patrick@310
   283
# ~~~~~~ category.head
Patrick@310
   284
category.head = element head { category.head.content }
Patrick@310
   285
Patrick@310
   286
category.head.content =
iinov@476
   287
    title
iinov@476
   288
    & shorttitle?
iinov@476
   289
    & subtitle*
Patrick@310
   290
patrick@125
   291
# ~~~~~~ categories
Patrick@168
   292
categories = element categories { categories.attributes, categories.content }
patrick@125
   293
Patrick@168
   294
categories.attributes =
iinov@476
   295
    success.attribute?
iinov@476
   296
    & multiple.attribute?
iinov@476
   297
    & noshuffle.attribute?
iinov@476
   298
    & orientation.attribute?
Patrick@310
   299
patrick@125
   300
categories.content =
iinov@476
   301
    categories.intruders?,
iinov@476
   302
    category,
iinov@476
   303
    category+
patrick@125
   304
patrick@125
   305
# ~~~~~~ category
patrick@125
   306
category = element category { category.content }
patrick@125
   307
patrick@125
   308
category.content =
iinov@476
   309
    category.head,
iinov@476
   310
    category.item*
patrick@125
   311
Coraline@438
   312
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wordsearch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@448
   313
Coraline@438
   314
wordsearch = element wordsearch {wordsearch.attributes, wordsearch.content }
Coraline@438
   315
Coraline@438
   316
wordsearch.attributes =
iinov@476
   317
    strict.attribute ?
iinov@476
   318
    & wordlist.attribute ?
Coraline@438
   319
Coraline@438
   320
wordlist.attribute = attribute wordlist { "hidden" | "right" | "left" }
Coraline@438
   321
Coraline@438
   322
wordsearch.content =
iinov@476
   323
    words
iinov@476
   324
    & grid
Coraline@438
   325
Coraline@438
   326
# ~~~~~~ words
Coraline@438
   327
words = element words {words.content}
Coraline@438
   328
words.content = words.item+
Coraline@438
   329
Coraline@438
   330
# ~~~~~~ grid
Coraline@438
   331
grid = element grid {grid.content}
Coraline@438
   332
grid.content = line+
Coraline@438
   333
Coraline@438
   334
line = element line {line.content}
Coraline@438
   335
line.content = cell+
Coraline@438
   336
Coraline@438
   337
cell = element cell {cell.content}
Coraline@438
   338
cell.content = xsd:token {pattern = "."}
Patrick@450
   339
Patrick@448
   340
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ flashcard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@448
   341
Patrick@448
   342
# ~~~~~~ flashcard
Patrick@448
   343
flashcard = element flashcard { flashcard.content }
Patrick@448
   344
Patrick@448
   345
flashcard.content =
iinov@476
   346
    side1,
iinov@476
   347
    side2
Patrick@448
   348
Patrick@448
   349
# ~~~~~~ side1
Patrick@448
   350
side1 = element side1 { side1.content }
Patrick@448
   351
Patrick@448
   352
side1.content =
Patrick@448
   353
    section+ | block+
Patrick@448
   354
Patrick@448
   355
# ~~~~~~ side2
Patrick@448
   356
side2 = element side2 { side2.content }
Patrick@448
   357
Patrick@448
   358
side2.content =
Patrick@448
   359
    instructions?,
Patrick@448
   360
    flashcard.engine,
Patrick@448
   361
    help?,
Patrick@448
   362
    answer?
Patrick@448
   363
Patrick@448
   364
# ~~~~~~ flashcard.engine
Patrick@448
   365
flashcard.engine =
Patrick@448
   366
    choices-radio
Patrick@448
   367
    | choices-check
Patrick@448
   368
    | blanks-fill
Patrick@448
   369
    | blanks-select
Patrick@448
   370
    | sort
Patrick@448
   371
Patrick@450
   372
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ coloring ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@450
   373
Patrick@450
   374
coloring = element coloring { coloring.attributes, coloring.content }
Patrick@450
   375
Patrick@450
   376
coloring.attributes =
Patrick@450
   377
    nomark.attribute?
Patrick@450
   378
nomark.attribute = attribute nomark { xsd:boolean }
Patrick@450
   379
Patrick@450
   380
coloring.content =
Patrick@450
   381
    palette
iinov@476
   382
    & canvas
iinov@476
   383
    & areas?
Patrick@450
   384
Patrick@450
   385
# ~~~~~~ palette
Patrick@450
   386
palette = element palette { palette.content }
Patrick@450
   387
Patrick@450
   388
palette.content =
Patrick@450
   389
    color+
Patrick@450
   390
Patrick@450
   391
# ~~~~~~ canvas
Patrick@450
   392
canvas = element canvas { canvas.attributes }
Patrick@450
   393
Patrick@450
   394
canvas.attributes =
Patrick@450
   395
    media.id.attribute
Patrick@450
   396
Patrick@450
   397
# ~~~~~~ areas
Patrick@450
   398
areas = element areas { areas.attributes }
Patrick@450
   399
Patrick@450
   400
areas.attributes =
Patrick@450
   401
    media.id.attribute
Patrick@450
   402
Patrick@450
   403
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@450
   404
Patrick@450
   405
# ~~~~~~ memory
Patrick@450
   406
memory = element memory { memory.attributes, memory.content }
Patrick@450
   407
Patrick@450
   408
memory.attributes =
Patrick@450
   409
    display.attribute?
Patrick@450
   410
    & delay.attribute?
Patrick@450
   411
display.attribute = attribute display { xsd:positiveInteger }
Patrick@450
   412
delay.attribute = attribute delay { xsd:positiveInteger }
Patrick@450
   413
Patrick@450
   414
memory.content =
iinov@476
   415
    memory.match,
iinov@476
   416
    memory.match+
Patrick@450
   417
Patrick@450
   418
# ~~~~~~ memory.match
Patrick@450
   419
memory.match = element match { memory-m.content }
Patrick@450
   420
Patrick@450
   421
memory-m.content =
Patrick@450
   422
    memory-m.item,
Patrick@450
   423
    memory-m.item,
Patrick@450
   424
    audio?
Patrick@450
   425
iinov@463
   426
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dictation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
iinov@463
   427
iinov@465
   428
dictation = element dictation { dictation.attributes, dictation.content }
iinov@465
   429
iinov@465
   430
dictation.attributes =
iinov@465
   431
    case_insensitive.attribute?
iinov@465
   432
case_insensitive.attribute = attribute case-insensitive { xsd:boolean }
iinov@463
   433
iinov@463
   434
dictation.content =
iinov@472
   435
    dictation.media,
iinov@465
   436
    dictation.p
iinov@463
   437
patrick@87
   438
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ production ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@87
   439
Coraline@407
   440
production = element production { production.content }
Coraline@407
   441
Coraline@407
   442
production.content = text
patrick@87
   443
patrick@73
   444
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ composite ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   445
patrick@77
   446
# ~~~~~~ composite
Patrick@161
   447
composite = element composite { composite.attributes, composite.content }
Patrick@161
   448
Patrick@161
   449
composite.attributes =
iinov@476
   450
    success.attribute?
iinov@476
   451
    & multipage.attribute?
Patrick@310
   452
multipage.attribute = attribute multipage { xsd:boolean }
patrick@75
   453
patrick@73
   454
composite.content =
iinov@476
   455
    subquiz,
iinov@476
   456
    subquiz+
patrick@77
   457
patrick@85
   458
# ~~~~~~ subquiz
patrick@85
   459
subquiz = element subquiz { subquiz.content }
patrick@77
   460
patrick@85
   461
subquiz.content =
iinov@476
   462
    instructions?,
iinov@476
   463
    engine,
iinov@476
   464
    help?,
iinov@476
   465
    answer?
patrick@73
   466
iinov@478
   467
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ keyboard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
iinov@478
   468
iinov@478
   469
# ~~~~~~ keyboard
iinov@478
   470
keyboard = element keyboard { keyboard.content }
iinov@478
   471
iinov@478
   472
keyboard.content =
iinov@478
   473
    keyboard.key+
iinov@478
   474
iinov@478
   475
# ~~~~~~ keyboard.key
iinov@478
   476
keyboard.key = element key { keyboard.key.content }
iinov@478
   477
iinov@478
   478
keyboard.key.content = xsd:token {pattern = "."}
iinov@478
   479
patrick@73
   480
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ help ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   481
patrick@73
   482
help = element help { help.content }
patrick@73
   483
patrick@73
   484
help.content =
iinov@476
   485
    (section+ | block+)?,
iinov@476
   486
    link*
patrick@73
   487
patrick@87
   488
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ answer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   489
patrick@87
   490
answer = element answer { answer.content }
patrick@73
   491
patrick@87
   492
answer.content =
iinov@476
   493
    (section+ | block+)?,
iinov@476
   494
    link*
patrick@73
   495
patrick@73
   496
patrick@73
   497
# =============================================================================
patrick@73
   498
#                                 BLOCK LEVEL
patrick@73
   499
# =============================================================================
patrick@73
   500
patrick@73
   501
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ block ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   502
iinov@476
   503
blanks.block =
iinov@476
   504
    (blanks.p | blanks.list | blanks.blockquote | blanks.speech | blanks.table
iinov@476
   505
     | blanks.media)
iinov@476
   506
blanks-m.block =
iinov@476
   507
    (blanks-m.p | blanks-m.list | blanks-m.blockquote | blanks-m.speech
iinov@476
   508
     | blanks-m.table | blanks-m.media)
iinov@476
   509
blanks-c.block =
iinov@476
   510
    (blanks-c.p | blanks-c.list | blanks-c.blockquote | blanks-c.speech
iinov@476
   511
     | blanks-c.table | blanks-c.media)
iinov@476
   512
correct.block =
iinov@476
   513
    (correct.p | correct.list | correct.blockquote | correct.speech
iinov@476
   514
     | correct.table | media)
iinov@476
   515
pointing.block =
iinov@476
   516
    (pointing.p | pointing.list | pointing.blockquote | pointing.speech
iinov@476
   517
     | pointing.table | media)
patrick@73
   518
patrick@73
   519
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ p ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   520
patrick@73
   521
blanks.p = element p { blanks.p.content }
Coraline@409
   522
blanks-m.p = element p { blanks-m.p.content }
Coraline@441
   523
blanks-c.p = element p { blanks-c.p.content }
Coraline@442
   524
correct.p = element p { correct.p.content }
Patrick@336
   525
pointing.p = element p { pointing.p.content }
iinov@463
   526
dictation.p = element p { dictation.p.content }
patrick@73
   527
patrick@73
   528
blanks.p.content =
iinov@463
   529
    blanks.inlines
Coraline@409
   530
blanks-m.p.content =
iinov@463
   531
    blanks-m.inlines
Coraline@441
   532
blanks-c.p.content =
iinov@463
   533
    blanks-c.inlines
Coraline@442
   534
correct.p.content =
iinov@463
   535
    correct.inlines
Patrick@336
   536
pointing.p.content =
iinov@463
   537
    pointing.inlines
iinov@463
   538
dictation.p.content =
iinov@463
   539
    dictation.inlines
patrick@73
   540
patrick@73
   541
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   542
patrick@73
   543
# ~~~~~~ list
iinov@476
   544
blanks.list =
iinov@476
   545
    element list {
iinov@476
   546
                block.head?,
iinov@476
   547
                ( (attribute type {"ordered"}?, blanks.item, blanks.item+) |
iinov@476
   548
                  (attribute type {"glossary"}, item.glossary+) ) }
iinov@476
   549
blanks-m.list =
iinov@476
   550
    element list {
iinov@476
   551
                block.head?,
iinov@476
   552
                ( (attribute type {"ordered"}?, blanks-m.item, blanks-m.item+) |
iinov@476
   553
                  (attribute type {"glossary"}, item.glossary+) ) }
iinov@476
   554
blanks-c.list =
iinov@476
   555
    element list {
iinov@476
   556
                block.head?,
iinov@476
   557
                ( (attribute type {"ordered"}?, blanks.item, blanks.item+) |
iinov@476
   558
                  (attribute type {"glossary"}, item.glossary+) ) }
iinov@476
   559
correct.list =
iinov@476
   560
    element list {
iinov@476
   561
                block.head?,
iinov@476
   562
                ( (attribute type {"ordered"}?, correct.item, correct.item+) |
iinov@476
   563
                  (attribute type {"glossary"}, item.glossary+) ) }
iinov@476
   564
pointing.list =
iinov@476
   565
    element list {
iinov@476
   566
                block.head?,
iinov@476
   567
                ( (attribute type {"ordered"}?, pointing.item, pointing.item+) |
iinov@476
   568
                  (attribute type {"glossary"}, item.glossary+) ) }
patrick@73
   569
patrick@73
   570
# ~~~~~~ item
patrick@73
   571
blanks.item = element item { blanks.item.content }
Coraline@441
   572
blanks-m.item = element item { blanks-m.item.content }
Coraline@441
   573
blanks-c.item = element item { blanks-c.item.content }
Coraline@442
   574
correct.item = element item { correct.item.content }
Patrick@336
   575
pointing.item = element item { pointing.item.content }
Patrick@450
   576
patrick@73
   577
Coraline@442
   578
blanks.item.content = blanks.inlines | blanks.block+
Coraline@442
   579
blanks-m.item.content = blanks-m.inlines | blanks-m.block+
Coraline@442
   580
blanks-c.item.content = blanks-c.inlines | blanks-c.block+
Coraline@442
   581
correct.item.content = correct.inlines | correct.block+
Coraline@442
   582
pointing.item.content = pointing.inlines | pointing.block+
patrick@73
   583
Patrick@313
   584
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ blockquote ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@313
   585
iinov@476
   586
blanks.blockquote =
iinov@476
   587
    element blockquote { blockquote.attributes, blanks.blockquote.content }
iinov@476
   588
blanks-m.blockquote =
iinov@476
   589
    element blockquote { blockquote.attributes, blanks-m.blockquote.content }
iinov@476
   590
blanks-c.blockquote =
iinov@476
   591
    element blockquote { blockquote.attributes, blanks-c.blockquote.content }
iinov@476
   592
correct.blockquote =
iinov@476
   593
    element blockquote { blockquote.attributes, correct.blockquote.content }
iinov@476
   594
pointing.blockquote =
iinov@476
   595
    element blockquote { blockquote.attributes, pointing.blockquote.content }
Patrick@313
   596
Patrick@313
   597
blanks.blockquote.content =
iinov@476
   598
    block.head?,
iinov@476
   599
    (blanks.p | speech | blanks.list)+,
iinov@476
   600
    attribution?
Coraline@409
   601
blanks-m.blockquote.content =
iinov@476
   602
    block.head?,
iinov@476
   603
    (blanks-m.p | speech | blanks-m.list)+,
iinov@476
   604
    attribution?
Coraline@441
   605
blanks-c.blockquote.content =
iinov@476
   606
    block.head?,
iinov@476
   607
    (blanks-c.p | speech | blanks-c.list)+,
iinov@476
   608
    attribution?
Coraline@442
   609
correct.blockquote.content =
iinov@476
   610
    block.head?,
iinov@476
   611
    (correct.p | speech | correct.list)+,
iinov@476
   612
    attribution?
Patrick@336
   613
pointing.blockquote.content =
iinov@476
   614
    block.head?,
iinov@476
   615
    (pointing.p | speech | pointing.list)+,
iinov@476
   616
    attribution?
Patrick@313
   617
Patrick@313
   618
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ speech ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@313
   619
Patrick@313
   620
# ~~~~~~ speech
Patrick@313
   621
blanks.speech = element speech { blanks.speech.content }
Coraline@409
   622
blanks-m.speech = element speech { blanks-m.speech.content }
Coraline@441
   623
blanks-c.speech = element speech { blanks-c.speech.content }
Coraline@442
   624
correct.speech = element speech { correct.speech.content }
Patrick@336
   625
pointing.speech = element speech { pointing.speech.content }
Patrick@313
   626
Patrick@313
   627
blanks.speech.content =
iinov@476
   628
    blanks.speaker?,
iinov@476
   629
    stage?,
iinov@476
   630
    (blanks.p | blanks.blockquote)+
Coraline@409
   631
blanks-m.speech.content =
iinov@476
   632
    blanks-m.speaker?,
iinov@476
   633
    stage?,
iinov@476
   634
    (blanks-m.p | blanks-m.blockquote)+
Coraline@441
   635
blanks-c.speech.content =
iinov@476
   636
    blanks-c.speaker?,
iinov@476
   637
    stage?,
iinov@476
   638
    (blanks-c.p | blanks-c.blockquote)+
Coraline@442
   639
correct.speech.content =
iinov@476
   640
    correct.speaker?,
iinov@476
   641
    stage?,
iinov@476
   642
    (correct.p | correct.blockquote)+
Patrick@336
   643
pointing.speech.content =
iinov@476
   644
    pointing.speaker?,
iinov@476
   645
    stage?,
iinov@476
   646
    (pointing.p | pointing.blockquote)+
Patrick@313
   647
Patrick@313
   648
# ~~~~~~ speaker
Patrick@313
   649
blanks.speaker = element speaker { blanks.speaker.content }
Coraline@409
   650
blanks-m.speaker = element speaker { blanks-m.speaker.content }
Coraline@441
   651
blanks-c.speaker = element speaker { blanks-c.speaker.content }
Coraline@442
   652
correct.speaker = element speaker { correct.speaker.content }
Patrick@336
   653
pointing.speaker = element speaker { pointing.speaker.content }
Patrick@313
   654
Patrick@313
   655
blanks.speaker.content = blanks.inlines
Coraline@409
   656
blanks-m.speaker.content = blanks-m.inlines
Coraline@441
   657
blanks-c.speaker.content = blanks-c.inlines
Coraline@442
   658
correct.speaker.content = correct.inlines
Patrick@336
   659
pointing.speaker.content = pointing.inlines
Patrick@313
   660
patrick@73
   661
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   662
Patrick@313
   663
# ~~~~~~ table
patrick@249
   664
blanks.table = element table { table.attributes, blanks.table.content }
Coraline@409
   665
blanks-m.table = element table { table.attributes, blanks-m.table.content }
Coraline@441
   666
blanks-c.table = element table { table.attributes, blanks-m.table.content }
Coraline@442
   667
correct.table = element table { table.attributes, correct.table.content }
Patrick@336
   668
pointing.table = element table { table.attributes, pointing.table.content }
patrick@73
   669
patrick@73
   670
blanks.table.content =
iinov@476
   671
    block.head?,
iinov@476
   672
    ((thead?, blanks.tbody+) | blanks.tr+),
iinov@476
   673
    blanks.table.caption?
Coraline@409
   674
blanks-m.table.content =
iinov@476
   675
    block.head?,
iinov@476
   676
    ((thead?, blanks-m.tbody+) | blanks-m.tr+),
iinov@476
   677
    blanks-m.table.caption?
Coraline@441
   678
blanks-c.table.content =
iinov@476
   679
    block.head?,
iinov@476
   680
    ((thead?, blanks-c.tbody+) | blanks-c.tr+),
iinov@476
   681
    blanks-c.table.caption?
Coraline@442
   682
correct.table.content =
iinov@476
   683
    block.head?,
iinov@476
   684
    ((thead?, correct.tbody+) | correct.tr+),
iinov@476
   685
    correct.table.caption?
Patrick@336
   686
pointing.table.content =
iinov@476
   687
    block.head?,
iinov@476
   688
    ((thead?, pointing.tbody+) | pointing.tr+),
iinov@476
   689
    pointing.table.caption?
patrick@73
   690
patrick@73
   691
# ~~~~~~ tbody
patrick@249
   692
blanks.tbody = element tbody { blanks.tbody.content }
Coraline@409
   693
blanks-m.tbody = element tbody { blanks-m.tbody.content }
Coraline@441
   694
blanks-c.tbody = element tbody { blanks-m.tbody.content }
Coraline@442
   695
correct.tbody = element tbody { correct.tbody.content }
Patrick@336
   696
pointing.tbody = element tbody { pointing.tbody.content }
patrick@73
   697
patrick@73
   698
blanks.tbody.content =
iinov@476
   699
    blanks.tr+
Coraline@409
   700
blanks-m.tbody.content =
iinov@476
   701
    blanks-m.tr+
Coraline@441
   702
blanks-c.tbody.content =
iinov@476
   703
    blanks-c.tr+
Coraline@442
   704
correct.tbody.content =
iinov@476
   705
    correct.tr+
Patrick@336
   706
pointing.tbody.content =
iinov@476
   707
    pointing.tr+
patrick@73
   708
patrick@249
   709
# ~~~~~~ tr
patrick@249
   710
blanks.tr = element tr { tr.attributes, blanks.tr.content }
Coraline@409
   711
blanks-m.tr = element tr { tr.attributes, blanks-m.tr.content }
Coraline@441
   712
blanks-c.tr = element tr { tr.attributes, blanks-c.tr.content }
Coraline@442
   713
correct.tr = element tr { tr.attributes, correct.tr.content }
Patrick@336
   714
pointing.tr = element tr { tr.attributes, pointing.tr.content }
patrick@73
   715
patrick@249
   716
blanks.tr.content =
iinov@476
   717
    (blanks.td | blanks.th)+
Coraline@409
   718
blanks-m.tr.content =
iinov@476
   719
    (blanks-m.td | blanks-m.th)+
Coraline@441
   720
blanks-c.tr.content =
iinov@476
   721
    (blanks-c.td | blanks-c.th)+
Coraline@442
   722
correct.tr.content =
iinov@476
   723
    (correct.td | correct.th)+
Patrick@336
   724
pointing.tr.content =
iinov@476
   725
    (pointing.td | pointing.th)+
patrick@73
   726
patrick@249
   727
# ~~~~~~ td, th
patrick@249
   728
blanks.td = element td { td.attributes, blanks.td.content }
patrick@249
   729
blanks.th = element th { td.attributes, blanks.td.content }
Coraline@409
   730
blanks-m.td = element td { td.attributes, blanks-m.td.content }
Coraline@409
   731
blanks-m.th = element th { td.attributes, blanks-m.td.content }
Coraline@441
   732
blanks-c.td = element td { td.attributes, blanks-c.td.content }
Coraline@441
   733
blanks-c.th = element th { td.attributes, blanks-c.td.content }
Coraline@442
   734
correct.td = element td { td.attributes, correct.td.content }
Coraline@442
   735
correct.th = element th { td.attributes, correct.td.content }
Patrick@336
   736
pointing.td = element td { td.attributes, pointing.td.content }
Patrick@336
   737
pointing.th = element th { td.attributes, pointing.td.content }
patrick@73
   738
patrick@249
   739
blanks.td.content =
iinov@476
   740
    blanks.inlines
iinov@476
   741
    | (blanks.p | blanks.media)+
Coraline@409
   742
blanks-m.td.content =
iinov@476
   743
    blanks-m.inlines
iinov@476
   744
    | (blanks-m.p | blanks-m.media)+
Coraline@441
   745
blanks-c.td.content =
iinov@476
   746
    blanks-c.inlines
iinov@476
   747
    | (blanks-c.p | blanks-c.media)+
Coraline@442
   748
correct.td.content =
iinov@476
   749
    correct.inlines
iinov@476
   750
    | (correct.p | media)+
Patrick@336
   751
pointing.td.content =
iinov@476
   752
    pointing.inlines
iinov@476
   753
    | (pointing.p | media)+
Patrick@313
   754
Patrick@313
   755
# ~~~~~~ table.caption
Patrick@313
   756
blanks.table.caption = element caption { blanks.caption.content }
Coraline@409
   757
blanks-m.table.caption = element caption { blanks-m.caption.content }
Coraline@441
   758
blanks-c.table.caption = element caption { blanks-c.caption.content }
Coraline@442
   759
correct.table.caption = element caption { correct.caption.content }
Patrick@336
   760
pointing.table.caption = element caption { pointing.caption.content }
Patrick@313
   761
Patrick@313
   762
blanks.caption.content =
iinov@476
   763
    blanks.inlines
iinov@476
   764
    | (blanks.p | speech | blanks.list | blockquote)+
Coraline@409
   765
blanks-m.caption.content =
iinov@476
   766
    blanks-m.inlines
iinov@476
   767
    | (blanks-m.p | speech | blanks-m.list | blockquote)+
Coraline@441
   768
blanks-c.caption.content =
iinov@476
   769
    blanks-c.inlines
iinov@476
   770
    | (blanks-c.p | speech | blanks-c.list | blockquote)+
Coraline@442
   771
correct.caption.content =
iinov@476
   772
    correct.inlines
iinov@476
   773
    | (correct.p | speech | correct.list | blockquote)+
Patrick@336
   774
pointing.caption.content =
iinov@476
   775
    pointing.inlines
iinov@476
   776
    | (pointing.p | speech | pointing.list | blockquote)+
patrick@73
   777
Patrick@174
   778
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ media ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@174
   779
Patrick@313
   780
# ~~~~~~ media
Patrick@313
   781
blanks.media = element media { media.attributes, blanks.media.content }
Coraline@409
   782
blanks-m.media = element media { media.attributes, blanks-m.media.content }
Coraline@441
   783
blanks-c.media = element media { media.attributes, blanks-c.media.content }
Coraline@442
   784
correct.media = element media { media.attributes, correct.media.content }
Patrick@336
   785
pointing.media = element media { media.attributes, pointing.media.content }
iinov@472
   786
dictation.media = element media { media.attributes, dictation.media.content }
Patrick@174
   787
Patrick@313
   788
blanks.media.content =
iinov@476
   789
    block.head?,
iinov@476
   790
    (blanks.image | audio | video)+,
iinov@476
   791
    blanks.media.caption?,
iinov@476
   792
    link?
Coraline@409
   793
blanks-m.media.content =
iinov@476
   794
    block.head?,
iinov@476
   795
    (blanks-m.image | audio | video)+,
iinov@476
   796
    blanks-m.media.caption?,
iinov@476
   797
    link?
Coraline@441
   798
blanks-c.media.content =
iinov@476
   799
    block.head?,
iinov@476
   800
    (image | audio | video)+,
iinov@476
   801
    blanks-c.media.caption?,
iinov@476
   802
    link?
Coraline@442
   803
correct.media.content =
iinov@476
   804
    block.head?,
iinov@476
   805
    (image | audio | video)+,
iinov@476
   806
    correct.media.caption?,
iinov@476
   807
    link?
Patrick@336
   808
pointing.media.content =
iinov@476
   809
    block.head?,
iinov@476
   810
    (image | audio | video)+,
iinov@476
   811
    pointing.media.caption?,
iinov@476
   812
    link?
iinov@472
   813
dictation.media.content =
iinov@476
   814
    audio
Patrick@174
   815
Patrick@174
   816
# ~~~~~~ blanks.image
Patrick@174
   817
blanks.image = element image { image.attributes, blanks.image.content }
Coraline@409
   818
blanks-m.image = element image { image.attributes, blanks-m.image.content }
Patrick@174
   819
Patrick@174
   820
blanks.image.content =
iinov@476
   821
    copyright?,
iinov@476
   822
    blanks.dropzone*
Coraline@409
   823
blanks-m.image.content =
iinov@476
   824
    copyright?,
iinov@476
   825
    blanks-m.dropzone*
Patrick@174
   826
Patrick@313
   827
# ~~~~~~ dropzone
iinov@476
   828
blanks.dropzone =
iinov@476
   829
    element dropzone { blanks.dropzone.attributes, blanks.dropzone.content }
iinov@476
   830
blanks-m.dropzone =
iinov@476
   831
    element dropzone { blanks-m.dropzone.attributes, blanks-m.dropzone.content }
Patrick@183
   832
Patrick@192
   833
blanks.dropzone.attributes =
iinov@476
   834
    x.attribute
iinov@476
   835
    & y.attribute
Patrick@411
   836
blanks-m.dropzone.attributes =
iinov@476
   837
    x.attribute
iinov@476
   838
    & y.attribute
iinov@476
   839
    & h.attribute
iinov@476
   840
    & w.attribute
Patrick@174
   841
Patrick@192
   842
blanks.dropzone.content =
iinov@476
   843
    blank
Coraline@409
   844
blanks-m.dropzone.content =
iinov@476
   845
    blank-m
Patrick@174
   846
Patrick@313
   847
# ~~~~~~ media.caption
iinov@476
   848
blanks.media.caption =
iinov@476
   849
    element caption { caption.attributes, blanks.caption.content }
iinov@476
   850
blanks-m.media.caption =
iinov@476
   851
    element caption { caption.attributes, blanks-m.caption.content }
iinov@476
   852
blanks-c.media.caption =
iinov@476
   853
    element caption { caption.attributes, blanks-c.caption.content }
iinov@476
   854
correct.media.caption =
iinov@476
   855
    element caption { caption.attributes, correct.caption.content }
iinov@476
   856
pointing.media.caption =
iinov@476
   857
    element caption { caption.attributes, pointing.caption.content }
Patrick@313
   858
patrick@73
   859
# ~~~~~~~~~~~~~~~~~~~~~~~~ choices.right, choices.wrong ~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   860
patrick@73
   861
choices.right = element right { choices.right.content }
patrick@73
   862
choices.wrong = element wrong { choices.right.content }
patrick@73
   863
patrick@73
   864
choices.right.content =
iinov@476
   865
    inlines
iinov@476
   866
    | ((p | image | (audio, image?) | video), help?, answer?)
patrick@73
   867
Coraline@409
   868
# ~~~~~~~~~~~~~~~~~~~~ blanks.intruders, blanks-m.intruders  ~~~~~~~~~~~~~~~~~~
patrick@73
   869
Patrick@342
   870
blanks.intruders = element intruders { blanks.intruders.content }
Coraline@409
   871
blanks-m.intruders = element intruders { blanks-m.intruders.content }
patrick@73
   872
Coraline@409
   873
blanks.intruders.content = blank+
Coraline@409
   874
blanks-m.intruders.content = blank-m+
patrick@73
   875
Coraline@442
   876
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ correct.intruders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Coraline@442
   877
Coraline@442
   878
correct.intruders = element intruders { correct.intruders.content }
Coraline@442
   879
Coraline@442
   880
correct.intruders.content = char+
Coraline@442
   881
Patrick@359
   882
# ~~~~~~~~~~~~~~~~~~~~~~~ matching.intruders, match.item ~~~~~~~~~~~~~~~~~~~~~~
patrick@73
   883
Patrick@359
   884
# ~~~~~~~ matching.intruders
Patrick@359
   885
matching.intruders = element intruders { matching.intruders.content }
Patrick@359
   886
Patrick@359
   887
matching.intruders.content =
iinov@476
   888
    match.item+
Patrick@359
   889
Patrick@359
   890
# ~~~~~~~ match.item
Patrick@161
   891
match.item = element item { match.item.content }
patrick@73
   892
Patrick@161
   893
match.item.content =
iinov@476
   894
    inlines
iinov@476
   895
    | (p, help?, answer?)
patrick@73
   896
iinov@462
   897
# ~~~~~~~~~~~~~~~~~~~~ sort.intruders, comparison, sort.item ~~~~~~~~~~~~~~~~~~
patrick@73
   898
iinov@461
   899
# ~~~~~~~ sort.intruders
iinov@461
   900
sort.intruders = element intruders { sort.intruders.content }
iinov@461
   901
iinov@461
   902
sort.intruders.content =
iinov@476
   903
    sort.item+
iinov@461
   904
iinov@462
   905
# ~~~~~~ comparison
iinov@462
   906
comparison = element comparison { comparison.content }
iinov@462
   907
iinov@462
   908
comparison.content = inlines
iinov@462
   909
patrick@73
   910
# ~~~~~~ sort.item
patrick@73
   911
sort.item = element item { sort.item.attributes, sort.item.content }
patrick@73
   912
patrick@73
   913
sort.item.attributes =
iinov@476
   914
    item.shuffle.attribute?
patrick@73
   915
item.shuffle.attribute = attribute shuffle { xsd:integer }
patrick@73
   916
Patrick@161
   917
sort.item.content =
iinov@476
   918
    inlines
iinov@476
   919
    | (p, help?, answer?)
patrick@73
   920
Patrick@344
   921
# ~~~~~~~~~~~~~~~~~~~~~ categories.intruders, category.item ~~~~~~~~~~~~~~~~~~~
patrick@125
   922
Patrick@344
   923
# ~~~~~~ categories.intruders
Patrick@344
   924
categories.intruders = element intruders { categories.intruders.content }
Patrick@342
   925
Patrick@344
   926
categories.intruders.content =
iinov@476
   927
    category.item+
Patrick@342
   928
Patrick@342
   929
# ~~~~~~ category.item
patrick@125
   930
category.item = element item { category.item.content }
patrick@125
   931
Patrick@161
   932
category.item.content =
iinov@476
   933
    inlines
iinov@476
   934
    | (p, help?, answer?)
patrick@125
   935
Coraline@438
   936
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ words.item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Coraline@438
   937
words.item = element item {words.item.content, words.item.attributes }
Patrick@450
   938
Coraline@438
   939
words.item.content = inlines
Coraline@438
   940
Coraline@438
   941
words.item.attributes =
iinov@476
   942
    startx
iinov@476
   943
    & starty
iinov@476
   944
    & endx
iinov@476
   945
    & endy
Coraline@438
   946
Coraline@438
   947
startx = attribute startx {xsd:token {pattern = "[a-zA-Z]+"}}
Coraline@438
   948
starty = attribute starty {xsd:token {pattern = "\d+"}}
Coraline@438
   949
endx = attribute endx {xsd:token {pattern = "[a-zA-Z]+"}}
Coraline@438
   950
endy = attribute endy {xsd:token {pattern = "\d+"}}
Coraline@438
   951
Patrick@450
   952
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ color ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@450
   953
Patrick@450
   954
color = element color { color.attributes }
Patrick@450
   955
Patrick@450
   956
color.attributes =
Patrick@450
   957
    color.code
Patrick@450
   958
    & color.coderef?
Patrick@450
   959
color.code = attribute code {xsd:token { pattern = "#(\d|\w){6}"}}
Patrick@450
   960
color.coderef = attribute coderef { list{xsd:token { pattern = "#(\d|\w){6}"}+}}
Patrick@450
   961
Patrick@450
   962
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memory-m.item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Patrick@450
   963
Patrick@450
   964
memory-m.item = element item { memory-m.item.content }
Patrick@450
   965
Patrick@450
   966
memory-m.item.content = image
Patrick@450
   967
patrick@73
   968
patrick@73
   969
# =============================================================================
patrick@73
   970
#                                 INLINE LEVEL
patrick@73
   971
# =============================================================================
patrick@73
   972
patrick@75
   973
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@75
   974
iinov@476
   975
blanks.inlines =
iinov@476
   976
    mixed {
iinov@476
   977
        sup* & sub*
iinov@476
   978
        & var*
iinov@476
   979
        & number*
iinov@476
   980
        & acronym*
iinov@476
   981
        & warning*
Patrick@293
   982
iinov@476
   983
        & highlight*
iinov@476
   984
        & emphasis*
iinov@476
   985
        & mentioned*
iinov@476
   986
        & literal*
iinov@476
   987
        & term*
iinov@476
   988
        & stage*
iinov@476
   989
        & name*
iinov@476
   990
        & foreign*
iinov@476
   991
        & date*
iinov@476
   992
        & math*
iinov@476
   993
        & quote*
iinov@476
   994
        & initial*
iinov@476
   995
        & note*
iinov@476
   996
        & link*
iinov@476
   997
        & anchor*
iinov@476
   998
        & index*
iinov@476
   999
        & image*
iinov@476
  1000
        & audio*
iinov@476
  1001
        & smil*
iinov@476
  1002
        & nowrap*
Patrick@293
  1003
iinov@476
  1004
        & blank*
iinov@476
  1005
    }
Patrick@288
  1006
iinov@476
  1007
blanks-m.inlines =
iinov@476
  1008
    mixed {
iinov@476
  1009
        sup* & sub*
iinov@476
  1010
        & var*
iinov@476
  1011
        & number*
iinov@476
  1012
        & acronym*
iinov@476
  1013
        & warning*
Coraline@409
  1014
iinov@476
  1015
        & highlight*
iinov@476
  1016
        & emphasis*
iinov@476
  1017
        & mentioned*
iinov@476
  1018
        & literal*
iinov@476
  1019
        & term*
iinov@476
  1020
        & stage*
iinov@476
  1021
        & name*
iinov@476
  1022
        & foreign*
iinov@476
  1023
        & date*
iinov@476
  1024
        & math*
iinov@476
  1025
        & quote*
iinov@476
  1026
        & initial*
iinov@476
  1027
        & note*
iinov@476
  1028
        & link*
iinov@476
  1029
        & anchor*
iinov@476
  1030
        & index*
iinov@476
  1031
        & image*
iinov@476
  1032
        & audio*
iinov@476
  1033
        & smil*
iinov@476
  1034
        & nowrap*
Coraline@409
  1035
iinov@476
  1036
        & blank-m*
iinov@476
  1037
    }
Coraline@409
  1038
iinov@476
  1039
blanks-c.inlines =
iinov@476
  1040
    mixed {
iinov@476
  1041
        sup* & sub*
iinov@476
  1042
        & var*
iinov@476
  1043
        & number*
iinov@476
  1044
        & acronym*
iinov@476
  1045
        & warning*
Coraline@441
  1046
iinov@476
  1047
        & highlight*
iinov@476
  1048
        & emphasis*
iinov@476
  1049
        & mentioned*
iinov@476
  1050
        & literal*
iinov@476
  1051
        & term*
iinov@476
  1052
        & stage*
iinov@476
  1053
        & name*
iinov@476
  1054
        & foreign*
iinov@476
  1055
        & date*
iinov@476
  1056
        & math*
iinov@476
  1057
        & quote*
iinov@476
  1058
        & initial*
iinov@476
  1059
        & note*
iinov@476
  1060
        & link*
iinov@476
  1061
        & anchor*
iinov@476
  1062
        & index*
iinov@476
  1063
        & image*
iinov@476
  1064
        & audio*
iinov@476
  1065
        & smil*
iinov@476
  1066
        & nowrap*
Coraline@441
  1067
iinov@476
  1068
        & blank-c*
iinov@476
  1069
    }
Coraline@441
  1070
iinov@476
  1071
correct.inlines =
iinov@476
  1072
    mixed {
iinov@476
  1073
        sup* & sub*
iinov@476
  1074
        & var*
iinov@476
  1075
        & number*
iinov@476
  1076
        & acronym*
iinov@476
  1077
        & warning*
Coraline@442
  1078
iinov@476
  1079
        & highlight*
iinov@476
  1080
        & emphasis*
iinov@476
  1081
        & mentioned*
iinov@476
  1082
        & literal*
iinov@476
  1083
        & term*
iinov@476
  1084
        & stage*
iinov@476
  1085
        & name*
iinov@476
  1086
        & foreign*
iinov@476
  1087
        & date*
iinov@476
  1088
        & math*
iinov@476
  1089
        & quote*
iinov@476
  1090
        & initial*
iinov@476
  1091
        & note*
iinov@476
  1092
        & link*
iinov@476
  1093
        & anchor*
iinov@476
  1094
        & index*
iinov@476
  1095
        & image*
iinov@476
  1096
        & audio*
iinov@476
  1097
        & smil*
iinov@476
  1098
        & nowrap*
Coraline@442
  1099
iinov@476
  1100
        & char*
iinov@476
  1101
    }
Coraline@442
  1102
iinov@476
  1103
pointing.inlines =
iinov@476
  1104
    mixed {
iinov@476
  1105
        sup* & sub*
iinov@476
  1106
        & var*
iinov@476
  1107
        & number*
iinov@476
  1108
        & acronym*
iinov@476
  1109
        & warning*
Patrick@293
  1110
iinov@476
  1111
        & highlight*
iinov@476
  1112
        & emphasis*
iinov@476
  1113
        & mentioned*
iinov@476
  1114
        & literal*
iinov@476
  1115
        & term*
iinov@476
  1116
        & stage*
iinov@476
  1117
        & name*
iinov@476
  1118
        & foreign*
iinov@476
  1119
        & date*
iinov@476
  1120
        & math*
iinov@476
  1121
        & quote*
iinov@476
  1122
        & initial*
iinov@476
  1123
        & note*
iinov@476
  1124
        & link*
iinov@476
  1125
        & anchor*
iinov@476
  1126
        & index*
iinov@476
  1127
        & image*
iinov@476
  1128
        & audio*
iinov@476
  1129
        & smil*
iinov@476
  1130
        & nowrap*
Patrick@293
  1131
iinov@476
  1132
        & point*
iinov@476
  1133
    }
patrick@75
  1134
iinov@476
  1135
dictation.inlines = mixed { warning* & dictation.hint* }
iinov@463
  1136
Coraline@441
  1137
# ~~~~~~~~~~~~~~~~~~~~~~~~~~ blank, blank-m, blank-c ~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
  1138
patrick@73
  1139
# ~~~~~~ blank
Patrick@216
  1140
blank = element blank { blank.attributes, blank.content }
Patrick@216
  1141
Patrick@216
  1142
blank.attributes =
iinov@476
  1143
    area.attribute?
iinov@476
  1144
    & long.attribute?
claire@381
  1145
area.attribute = attribute area { xsd:boolean }
patrick@73
  1146
patrick@73
  1147
blank.content =
iinov@476
  1148
    text
iinov@476
  1149
    | (s+, help?, answer?)
patrick@73
  1150
Coraline@409
  1151
# ~~~~~~ blank-m
Coraline@409
  1152
blank-m = element blank { blank-m.content }
Patrick@411
  1153
blank-m.content =
iinov@476
  1154
    p
iinov@476
  1155
    | math
iinov@476
  1156
    | image
iinov@476
  1157
    | audio
iinov@476
  1158
    | (s-m+, help?, answer?)
Patrick@450
  1159
Coraline@441
  1160
# ~~~~~~ blank-c
Coraline@441
  1161
blank-c = element blank { blank-c.attributes, blank-c.content }
Patrick@450
  1162
Coraline@441
  1163
blank-c.attributes = form.attribute?
Coraline@441
  1164
form.attribute = attribute form { 'radio' | 'check' }
Patrick@450
  1165
Coraline@441
  1166
blank-c.content = (blank-c.right | blank-c.wrong)+, help?, answer?
Coraline@441
  1167
blank-c.right = element right { inlines }
Patrick@450
  1168
blank-c.wrong = element wrong { inlines }
Coraline@409
  1169
patrick@73
  1170
# ~~~~~~ s
patrick@73
  1171
s = element s { s.content }
Coraline@409
  1172
s.content = text
patrick@73
  1173
Coraline@409
  1174
# ~~~~~~ s-m
Coraline@409
  1175
s-m = element s { s-m.content }
Patrick@411
  1176
s-m.content =
iinov@476
  1177
    p
iinov@476
  1178
    | math
iinov@476
  1179
    | image
iinov@476
  1180
    | audio
Patrick@450
  1181
Coraline@442
  1182
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Coraline@442
  1183
Coraline@442
  1184
char = element char { char.attributes, char.content }
Coraline@442
  1185
Coraline@442
  1186
char.attributes = function.attribute?
Coraline@442
  1187
function.attribute = attribute function { "accent" | "uppercase" }
Coraline@442
  1188
Coraline@442
  1189
char.content = text
patrick@73
  1190
Patrick@336
  1191
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ point ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patrick@73
  1192
Patrick@336
  1193
point = element point { point.attributes, point.content }
patrick@73
  1194
Patrick@336
  1195
point.attributes =
iinov@476
  1196
    point.ref.attribute?
Coraline@409
  1197
iinov@476
  1198
point.ref.attribute =
iinov@476
  1199
    attribute ref { "right" | "cat1" | "cat2" | "cat3" | "cat4" | "cat5" }
Patrick@336
  1200
Patrick@356
  1201
point.content = inlines
iinov@463
  1202
iinov@463
  1203
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dictation.hint ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
iinov@463
  1204
iinov@463
  1205
# ~~~~~~ dictation.hint
iinov@463
  1206
dictation.hint = element hint { dictation.hint.content }
iinov@463
  1207
iinov@463
  1208
dictation.hint.content =
iinov@463
  1209
    dictation.hint.w,
iinov@463
  1210
    mistake+
iinov@463
  1211
iinov@463
  1212
# ~~~~~~ dictation.hint.w
iinov@463
  1213
dictation.hint.w = element w { text }
iinov@463
  1214
iinov@463
  1215
# ~~~~~~ mistake
iinov@463
  1216
mistake = element mistake { mistake.attributes, mistake.content }
iinov@463
  1217
iinov@463
  1218
mistake.attributes =
iinov@476
  1219
    mistake.is.attribute?
iinov@463
  1220
mistake.is.attribute = attribute is { text }
iinov@463
  1221
iinov@463
  1222
mistake.content = inlines