aboutsummaryrefslogtreecommitdiffstats
path: root/doc/user/dia_synt
blob: 48f341b241014cd13cbd07c61896887c2732f306 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
@Section
    @Tag { dia_synt }
    @Title { Syntax diagrams }
@Begin
@PP
A variant of the @@Diag symbol, called {@Code "@SyntaxDiag"},
diagrams. @RawIndex { diagrams }
diagrams.syntax @SubIndex { syntax diagrams }
syntax.diagrams @Index { syntax diagrams }
railroad.diagrams @Index { railroad diagrams }
produces syntax diagrams (sometimes called railroad diagrams):
@CD @SyntaxDiag
    title { call-chain }
{
    @StartRight @Sequence
        A { @Optional @Sequence
                A { @BCell "super" }
                B { @CCell "!" }
          }
        B { @Loop
                A { @Sequence
                        A { @ACell identifier }
                        B { @Optional @Sequence
                                A { @CCell "(" }
                                B { @Loop
                                        A { @ACell expression }
                                        B { @CCell "," }
                                  }
                                C { @CCell ")" }
                          }
                  }
                B { @CCell "." }
          }
}
These are used to define the syntax of computer programming languages,
although they could be put to other uses.  We'll explain how to get
syntax diagrams first.  At the end of this section is an explanation of
how to change the formats of things, which people who use these diagrams
for other purposes will probably need to do.
@PP
A syntax diagram can be @I { right-moving }, which means it starts
at the left and heads right (like the example above), or it can be
@I { down-moving }, starting at the top and heading downwards.  The
@Code "@StartRight" and @Code "@StartDown" symbols are used at the start
of the diagram to say which of these directions is wanted:
@ID @OneRow @Code @Verbatim {
@SyntaxDiag
    title { call-chain }
{
    @StartRight ...
}
}
where @Code { ... } stands for the rest of the diagram, as we are about
to describe.  For completeness there are also @Code "@StartLeft" and
@Code "@StartUp" symbols, but diagrams never start off in these directions.
@PP
If you accidentally omit the starting symbol ({@Code "@StartRight"} or
whatever), you will get several error messages, the first of which
should mention @Code { diag_dirn }; it is trying to tell you, in a
cryptic way, that it doesn't know which direction you want to go in.
@PP
The @Code title option is optional; if given, the effect is as shown
(this option is also available with {@Code "@Diag"}).  Subsequent
examples will omit the enclosing {@Code "@SyntaxDiag { ... }"}.
@PP
The basic components of syntax diagrams are @I { category cells },
shown as boxes in the example above and obtained with the
@Code "@ACell" symbol; @I { keyword cells }, shown as curved boxes
and obtained with {@Code "@BCell"}; and @I { punctuation cells },
containing punctuation symbols small enough to be enclosed in circles,
and obtained with {@Code "@CCell"}.  After each symbol, place whatever
has to go inside the cell:
@ID @OneRow {
@Code @Verbatim { @StartRight @BCell loop }
|7ct
@SyntaxDiag {
@StartRight @BCell loop
}
}
Lout will insert the appropriate arrows, taking account of which
direction (right, up, left, or down) the diagram is currently
moving.  This is true for all the syntax diagram symbols; we
won't mention it again.
# @FootNote {
# This wonderfully useful effect is achieved by a dirty trick, one
# of whose consequences is that if you see an error message
# similar to `@Code { replacing unknown "@Case" option 0p by 1p }'
# it means you've forgotten the initial @Code "@StartRight" or
# whatever.
# }
@PP
Occasionally, instead of a cell one wants the horizontal or
vertical line to continue uninterrupted.  For this there is
the @Code "@Skip" symbol:
@ID @OneRow {
@Code @Verbatim { @StartDown @Skip }
|7ct
@SyntaxDiag {
@StartDown @Skip
}
}
Some examples of its use in practice appear below.
@PP
There are three main ways to build up larger syntax diagrams out
of smaller ones:  @I { sequencing }, @I { selection }, and
@I { looping }.  For sequencing there is the @Code "@Sequence" symbol:
@ID @OneRow {
@Code @Verbatim {
@StartRight @Sequence
    A { @BCell loop }
    B { @ACell statements }
    C { @BCell end }
}
||7ct
@SyntaxDiag {
@StartRight @Sequence
    A { @BCell loop }
    B { @ACell statements }
    C { @BCell end }
}
}
This is what the sequence looks like in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartUp A | @Cell @StartLeft A |
	      @Cell mr { 0i } @StartDown A }
{
@Rowa A {
@Sequence
    A { @BCell loop }
    B { @ACell statements }
    C { @BCell end }
}
} }
Whatever the direction, the arrows go from option @Code A to option @Code B
to option @Code C and so on.  You can have up to twelve items in the
sequence, in options @Code A to {@Code L}; if more than twelve are needed,
just place another sequence inside any one of these options:  where one
syntax diagram is allowed, any syntax diagram is allowed, provided there
is enough space on the page (Lout makes a total mess of any diagram that
is too wide to fit on the page).
@PP
After sequencing comes selection, which is obtained with the
@Code "@Select" symbol:
@ID @OneRow {
@Code @Verbatim {
@StartRight @Select
    A { @ACell asst }
    B { @ACell call-chain }
    C { @Sequence
           A { @BCell assert }
           B { @ACell condition }
      }
}
||7ct
@SyntaxDiag {
@StartRight @Select
    A { @ACell asst }
    B { @ACell call-chain }
    C { @Sequence
           A { @BCell assert }
           B { @ACell condition }
      }
}
}
This example shows right-moving selection of three alternatives,
the third being a sequence of things.  Here is the same example
in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartUp A | @Cell @StartLeft A |
	      @Cell mr { 0i } @StartDown A }
{
@Rowa A {
@Select
    A { @ACell asst }
    B { @ACell call-chain }
    C { @Sequence
           A { @BCell assert }
           B { @ACell condition }
      }
} } }
When building up complex diagrams like this, it pays to keep the indenting
perfect in the source document.  As with sequences, there can be
up to twelve alternatives, in options from @Code A to {@Code L}.
@PP
To say that something is @I optional is to select either that thing or
nothing:
@ID @OneRow {
@Code @Verbatim {
@StartRight @Select
    A { @Skip }
    B { @ACell parameters }
}
||7ct
@SyntaxDiag {
@StartRight @Select
    A { @Skip }
    B { @ACell parameters }
}
}
Since this case is so common, there is an @Code "@Optional" symbol for it:
@ID @OneRow {
@Code @Verbatim {
@StartRight @Optional
@ACell parameters
}
||7ct
@SyntaxDiag {
@StartRight @Optional
@ACell parameters
}
}
@Code "@Optional" is exactly like @Code "@Select" with option @Code A
set to @Code "@Skip" and option @Code B set to the syntax diagram
following the @Code "@Optional" symbol.  Here is the same example in
the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartUp A | @Cell @StartLeft A |
	      @Cell mr { 0i } @StartDown A }
{
@Rowa A {
@Optional @ACell parameters
} } }
There is another kind of `optional' layout, {@Code "@OptionalDiverted"}:
@ID @OneRow {
@Code @Verbatim {
@StartDown @OptionalDiverted
@Sequence
    A { @BCell creation }
    B { @ACell parameters }
}
||7ct
@SyntaxDiag {
@StartDown @OptionalDiverted @Sequence
    A { @BCell creation }
    B { @ACell parameters }
}
}
Here is the same example in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartRight A | @Cell @StartUp A |
	      @Cell mr { 0i } @StartLeft A }
{
@Rowa A {
@OptionalDiverted @Sequence
    A { @BCell creation }
    B { @ACell parameters }
} } }
The optional material goes in a direction perpendicular to what
it would have otherwise:  right-moving if previously up or down, and
down-moving if previously left or right.
@PP
Another, related symbol is {@Code "@Diverted"}; it is similar to
@Code "@OptionalDiverted" but without the path which produces nothing:
@ID @OneRow {
@Code @Verbatim {
@StartDown @Diverted @Sequence
    A { @BCell creation }
    B { @ACell parameters }
}
||7ct
@SyntaxDiag {
@StartDown @Diverted @Sequence
    A { @BCell creation }
    B { @ACell parameters }
}
}
Here is the same example in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartRight A | @Cell @StartUp A |
	      @Cell mr { 0i } @StartLeft A }
{
@Rowa A {
@Diverted @Sequence
    A { @BCell creation }
    B { @ACell parameters }
} } }
This symbol is a great aid to packing a big syntax diagram into a
compact shape.
@PP
A variant of the basic selection idea is when you want one thing
or another, or alternatively both in a particular order.  You can get
this with the @Code "@OneOrBoth" symbol, which takes exactly two
options, @Code "A" and {@Code "B"}:
@ID @OneRow {
@Code @Verbatim {
@StartRight @OneOrBoth
    A { @ACell type }
    B { @ACell body }
}
||7ct
@SyntaxDiag {
@StartRight @OneOrBoth
    A { @ACell type }
    B { @ACell body }
}
}
Although the concept extends to more than two options, the symbol
doesn't.  The summary at the end of this chapter shows the other
three directions.
@PP
That covers sequencing and selection; now for looping.  The @Code "@Loop"
symbol produces a loop, with option @Code A going forwards and option
@Code B centred and going backwards:
@ID @OneRow {
@Code @Verbatim {
@StartRight @Loop
    A { @Sequence
           A { @ACell identifier }
           B { @CCell : }
           C { @ACell type }
      }
    B { @CCell , }
}
||7ct
@SyntaxDiag {
@StartRight @Loop
    A { @Sequence
           A { @ACell identifier }
           B { @CCell : }
           C { @ACell type }
      }
    B { @CCell , }
}
}
Here is the same example in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartUp A | @Cell @StartLeft A |
	      @Cell mr { 0i } @StartDown A }
{
@Rowa A {
@Loop
    A { @Sequence
           A { @ACell identifier }
           B { @CCell : }
           C { @ACell type }
      }
    B { @CCell , }
} } }
One common case of looping is to have nothing on the way back.  We could
get this by placing @Code "@Skip" in option {@Code B} of {@Code "@Loop"},
but there is an even easier way, the {@Code "@Repeat"} symbol:
@ID @OneRow {
@Code @Verbatim {
@StartRight @Repeat
@ACell statement
}
||7ct
@SyntaxDiag {
@StartRight @Repeat
@ACell statement
}
}
Here is the same example in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartUp A | @Cell @StartLeft A |
	      @Cell mr { 0i } @StartDown A }
{
@Rowa A {
@Repeat
@ACell statement
} } }
Occasionally it looks better to have the empty returning arrow go on
the opposite side of the forward part; for that, there are
@Code "@LoopOpposite" and @Code "@RepeatOpposite" symbols:
@ID @OneRow {
@Code @Verbatim {
@StartRight @LoopOpposite
    A { @Sequence
           A { @ACell identifier }
           B { @CCell : }
           C { @ACell type }
      }
    B { @CCell , }
}
||7ct
@SyntaxDiag {
@StartRight @LoopOpposite
    A { @Sequence
           A { @ACell identifier }
           B { @CCell : }
           C { @ACell type }
      }
    B { @CCell , }
}
}
Here is the same example in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartUp A | @Cell @StartLeft A |
	      @Cell mr { 0i } @StartDown A }
{
@Rowa A {
@LoopOpposite
    A { @Sequence
           A { @ACell identifier }
           B { @CCell : }
           C { @ACell type }
      }
    B { @CCell , }
} } }
@Code "@RepeatOpposite" is particularly useful around a large
{@Code "@Select"}:
@ID @OneRow {
@Code @Verbatim {
@StartRight @RepeatOpposite
@Select
    A { @ACell asst }
    B { @ACell call-chain }
    C { @BCell return }
    D { @Sequence
           A { @BCell assert }
           B { @ACell condition }
      }
    E { @ACell conditional }
    F { @ACell selection }
    G { @ACell loop }
}
||7ct
@SyntaxDiag {
@StartRight @RepeatOpposite
@Select
    A { @ACell asst }
    B { @ACell call-chain }
    C { @BCell return }
    D { @Sequence
           A { @BCell assert }
           B { @ACell condition }
      }
    E { @ACell conditional }
    F { @ACell selection }
    G { @ACell loop }
}
}
since it clearly distinguishes the loop from the selection.
@PP
Finally, the @Code "@RepeatDiverted" symbol combines the two ideas
of repetition and diversion:
@ID @OneRow {
@Code @Verbatim {
@StartDown @RepeatDiverted
@ACell statement
}
||7ct
@SyntaxDiag {
@StartDown @RepeatDiverted
@ACell statement
}
}
Here is the same example in the other three directions:
@CD @OneRow @SyntaxDiag {
@Tbl
    mh { 1f }
    mv { 0i }
    iv { top }
    aformat { @Cell ml { 0i } @StartRight A | @Cell @StartUp A |
	      @Cell mr { 0i } @StartLeft A }
{
@Rowa A {
@RepeatDiverted
@ACell statement
} } }
There is no {@Code "@LoopDiverted"} symbol, for good reason.
@PP
Every syntax diagram, from the simplest to the most complex, has
one arrow going into it, and one coming out.  There are no exceptions
to this rule.  In most syntax diagrams, these two arrows lie on the
same (invisible) line and point in the same direction, and this is
the direction that we say the diagram is moving.  There are two symbols
that produce syntax diagrams that lack this second property.  Because
of this lack, these symbols cannot be used at arbitrary places in a
complex diagram; they can only be used instead of the @Code "@StartRight"
or @Code "@StartDown" symbols at the beginning of a diagram.  The first
symbol, {@Code "@StartRightDown"}, prints its option @Code A right-moving
and its option @Code B down-moving like this:
@ID @OneRow {
@Code @Verbatim {
@StartRightDown
    A { @ACell A }
    B { @ACell B }
}
||7ct
@SyntaxDiag {
@StartRightDown
    A { @ACell A }
    B { @ACell B }
}
}
The second symbol, {@Code "@StartRightRight"}, prints both options
right-moving like this:
@ID @OneRow {
@Code @Verbatim {
@StartRightRight
    A { @ACell A }
    B { @ACell B }
}
||7ct
@SyntaxDiag {
@StartRightRight
    A { @ACell A }
    B { @ACell B }
}
}
As usual, the options to these symbols may contain arbitrarily complex
syntax diagrams.
@PP
Finally, a few words about changing things.  The @Code "@SyntaxDiag"
symbol used the {@Code "@ANode"}, {@Code "@BNode"}, and {@Code "@CNode"}
symbols of @@Diag to construct its three types of cells.  In fact, the
@Code "@SyntaxDiag" symbol is nothing more than this:
@ID @OneRow @Code @Verbatim {
@Diag
    avalign { mark }
    avstrut { yes }
    amargin { 0.2f }
    aoutline { box }
    afont { Italic }
    bvalign { mark }
    bvstrut { yes }
    bmargin { 0.2f }
    boutline { curvebox }
    bfont { Bold }
    cvalign { mark }
    cvstrut { yes }
    cmargin { 0.2f }
    coutline { circle }
    chsize { 1f }
    arrowlength { 0.4f }
}
So any of the other @Code "@Diag" options can be used freely with
{@Code "@SyntaxDiag"}; and the format of the three cell types can be
changed by using @Code "@Diag" instead of {@Code "@SyntaxDiag"}, and
choosing new values for these (and other) options.  For example, if
you need four or five types of cell, just set some @Code { d } and
@Code { e } options and use @Code "@DCell" and @Code "@ECell" in
addition to {@Code "@ACell"}, {@Code "@BCell"}, and {@Code "@CCell"}.
@PP
If there are more than five cell types, it is necessary to fall back
on the {@Code "@XCell"} symbol, which produces a cell without nominating
any particular cell type.  After @Code "@XCell" there must be a regular
@Code "@Diag" node, like this:
@ID @OneRow {
@Code @Verbatim {
@StartRight @XCell @Ellipse INIT
}
|7ct
@SyntaxDiag {
@StartRight @XCell @Ellipse INIT
}
}
This way there is no limit to the number of different kinds of cells.
Also, since (for example) @Code "@ACell" is merely an abbreviation for
@ID @OneRow @Code @Verbatim { @XCell @ANode }
any node options may follow {@Code "@ACell"}, {@Code "@BCell"},
{@Code "@CCell"}, {@Code "@DCell"}, and {@Code "@ECell"}.  The
appearance of the arrows can be changed in the usual way, by
setting options as has been done above for {@Code "arrowlength"}.
@PP
There are three options specifically related to syntax diagrams:
@ID @OneRow @Code @Verbatim {
@SyntaxDiag
    syntaxgap { 0.35f }
    syntaxbias { 1.0f }
    syntaxradius { 0.3f }
}
The @Code syntaxgap option determines the spacing between the various
elements; changing it causes the syntax diagrams to be set tighter or
looser in a consistent way.  The default value shown is 0.35 times the
current font size.  The @Code syntaxbias and @Code syntaxradius
options affect the appearance of curved lines, as in @Code "@RVLCurve"
and its relatives.  These options are also available with {@Code "@Diag"},
and in the setup file.  Note however that these options cannot be given to
individual elements in a syntax diagram, only to the diagram as a whole.
@End @Section