aboutsummaryrefslogtreecommitdiff
path: root/syntax.pic
blob: 6c2a6f3c36eefed94953da564d171feaf8769acf (plain)
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
linewid = linewid/2;

define begin_group {
  [Start: Here;
}
define end_group {
  End: Here;] with .Start at Here;
  move to last [].End;
}

define terminal {
  begin_group();
  arrow;
  command ".FT TT";
  command ".DOC_PT_SIZE +4";
  circle $1;
  command ".DOC_PT_SIZE -4";
  command ".FT R";
  line;
  end_group();
}

define nonterminal {
  begin_group();
  arrow;
  command ".FT I";
  box $1;
  command ".FT R";
  line;
  end_group();
}

define keyword {
  begin_group();
  arrow;
  command ".FT TT";
  box $1;
  command ".FT R";
  line;
  end_group();
}

define empty {
  begin_group();
  # straight line, as long as a box would be
  line linewid+boxwid+linewid;
  end_group();
}

###
### repeat(block);
### Block must have labels `Start` and `End`.
###
define repeat {
  line from $1.End to $1.se - (0,circlerad*2);
  arrow to ($1.Start,Here) then to $1.Start;
  line from $1.End right linewid/2;
}

###
### repeat(block,terminal_symbol);
###
define repeat_with {
  command ".FT TT";
  command ".DOC_PT_SIZE +4";
  circle at bottom of $1 - (0,circlerad*2) $2;
  command ".DOC_PT_SIZE -4";
  command ".FT R";

  arrow from $1.End to ($1.End,last circle) then \
        to east of last circle;
  arrow from west of last circle to ($1.Start,last circle .e) then \
        to $1.Start;
  line from $1.End right linewid/2;
}

### begin_alt(base);
define begin_alt {
  line from $1.Start to $1.sw - (0,boxht);
  begin_group();
}

### end_alt(base);
define end_alt {
  end_group();
  # base might be smaller than alternative
  if (Here.x < $1.End.x) then {
    line to ($1.End,Here);
  }
  arrow to (Here,$1.End);
  # Extend end of base if it is smaller than alternative
  # and leave linewid/2 space for next alternative
  line from $1.End to Here + (linewid/2,0);
}

define begin_rule {
  move down;
  right;
  command ".FT I";
  {$1 at Here - (boxwid/2,0)}
  command ".FT R";
  begin_group();
  line;
}

define end_rule {
  arrow;
  end_group();
  move to last [].sw;
}