1# Pikchr Grammar
2
3This file describes the grammar of the input files to Pikchr.  Keywords
4and operators are shown in **bold**.  Non-terminal symbols are shown
5in *italic*.  Special token classes are shown in ALL-CAPS.  A grammar
6symbol followed by "*" means zero-or-more.  A grammar symbol
7followed by "?" means zero-or-one.  Parentheses are used for grouping.
8Two grammar symbols within "(..|..)" means one or the other.
9 Marks of the form
10"[▶info](./grammar.md)" are links to more information and are
11not part of the grammar.
12
13The following special token classes are recognized:
14
15  *  NEWLINE  →  A un-escaped newline character, U+000A.
16     A backslash followed by zero or more whitespace characters
17     and then a U+000A character is interpreted as ordinary whitespace,
18     not as a NEWLINE.
19
20  *  LABEL  →  An object or place label starting with an
21     upper-case ASCII letter and continuing with zero or more
22     ASCII letters, digits, and/or underscores.  A LABEL always starts
23     with an upper-case letter.
24
25  *  VARIABLE  →  A variable name consisting of a lower-case
26     ASCII letter or "$" or "@" and followed by zero or more
27     ASCII letters, digits, and/or underscores.  VARIABLEs may
28     contain upper-case letters, but they never begin with an upper-case.
29     In this way, VARIABLEs are distinct from LABELs.
30
31  *  NUMBER  →  A numeric literal.  The value can be a decimal
32     integer, a floating point value, or a hexadecimal literal
33     starting with "0x".  Decimal and floating point values can
34     optionally be followed by a two-character unit designator that is
35     one of:  "in", "cm", "px", "pt", "pc", or "mm".  There can be
36     no whitespace in between the numeric portion of the constant and
37     the unit.
38
39  *  ORDINAL  →  A non-zero integer literal followed by one of the
40     suffixes "st", "nd", "rd", or "th".  Examples: "1st", "2nd",
41    "3rd", "4th", "5th", and so forth.   As a special case, "first"
42     is accepted as an alternative spelling of "1st".
43
44  *  STRING  →  A string literal that begins and ends with
45     double-quotes (U+0022).  Within the string literal, a double-quote
46     character can be escaped using backslash (U+005c).  A backslash
47     can also be used to escape a backslash.  No other escape sequences
48     are recognized.
49
50  *  COLORNAME →  One of the 140 official HTML color names, in
51     any mixture of upper and lower cases.  The value of a COLORNAME is
52     an integer which is the 24-bit RGB value of that color.  Two
53     additional color names of "None" and "Off" are also recognized and
54     have a value of -1.
55
56  *  CODEBLOCK →   All tokens contained within nested {...}.  This
57     is only used as the body of a "define" statement.
58
59There are many non-terminals in the grammar, but a few are more important.
60If you are new to the Pikchr language, begin by focusing on these
61six:
62
63  *  *statement* →  A Pikchr script is just a list of statements.
64
65  *  *attribute* →  Each graphic object is configured with zero or
66     more attributes.
67
68  *  *object* →  A reference to a prior graphic object.
69
70  *  *place* →  A specific point associated with an *object*.
71
72  *  *position* →  Any (2-D) point in space.  An (x,y) pair.
73
74  *  *expr* →  A scalar expression.
75
76
77A complete input file to Pikchr consists of a single *statement-list*.
78
79## *statement-list*: [▶info](./stmtlist.md)
80
81  * *statement*?
82  * *statement-list* NEWLINE *statement*?
83  * *statement-list* **;** *statement*?
84
85## *statement*:  [▶info](./stmt.md)
86  * *object-definition*
87  * LABEL **:** *object-definition*
88  * LABEL **:** *place*
89  * *direction*
90  * VARIABLE *assignment-op* *expr*
91  * **define** VARIABLE CODEBLOCK     [▶info](./macro.md)
92  * **print** *print-argument* (**,** *print-argument*)\*
93  * **assert (** *expr* **==** *expr* **)**
94  * **assert (** *position* **==** *position* **)**
95
96
97## *direction*:
98  * **right**
99  * **down**
100  * **left**
101  * **up**
102
103## *assignment-op*:
104  * **=**
105  * **+=**
106  * **-=**
107  * **\*=**
108  * **/=**
109
110## *print-argument*:
111  * *expr*
112  * STRING
113
114## *object-definition*:
115  * *object-class* *attribute*\*
116  * STRING *text-attribute*\* *attribute*\*
117  * **[** *statement-list* **]** *attribute*\*
118
119## *object-class*:
120  * **arc**
121  * **arrow**
122  * **box**          [▶info](./boxobj.md)
123  * **circle**       [▶info](./circleobj.md)
124  * **cylinder**     [▶info](./cylinderobj.md)
125  * **dot**
126  * **ellipse**      [▶info](./ellipseobj.md)
127  * **file**         [▶info](./fileobj.md)
128  * **line**
129  * **move**
130  * **oval**         [▶info](./ovalobj.md)
131  * **spline**
132  * **text**
133
134## *attribute*:
135  * *path-attribute*              [▶info](./pathattr.md)
136  * *location-attribute*          [▶info](./locattr.md)
137  * STRING *text-attribute*\*     [▶info](./annotate.md)
138  * **same**
139  * **same as** *object*
140  * *numeric-property* *new-property-value*
141  * **dashed** *expr*?
142  * **dotted** *expr*?
143  * **color** *color-expr*
144  * **fill** *color-expr*
145  * **behind** *object*      [▶info](./behind.md)
146  * **cw**
147  * **ccw**
148  * **<-**                [▶info](./arrowdir.md)
149  * **->**                [▶info](./arrowdir.md)
150  * **<->**            [▶info](./arrowdir.md)
151  * **invis**|**invisible**  [▶info](./invis.md)
152  * **thick**                [▶info](./thickthin.md)
153  * **thin**                 [▶info](./thickthin.md)
154  * **solid**                [▶info](./thickthin.md)
155  * **chop**                 [▶info](./chop.md)
156  * **fit**                  [▶info](./fit.md)
157
158## *color-expr*: [▶info](./colorexpr.md)
159  * *expr*
160
161## *new-property-value*:  [▶info](./newpropval.md)
162  * *expr*
163  * *expr* **%**
164
165## *numeric-property*:  [▶info](./numprop.md)
166  * **diameter**
167  * **ht**
168  * **height**
169  * **rad**
170  * **radius**
171  * **thickness**
172  * **width**
173  * **wid**
174
175## *text-attribute*:  [▶info](./textattr.md)
176  * **above**
177  * **aligned**
178  * **below**
179  * **big**
180  * **bold**
181  * **center**
182  * **italic**
183  * **ljust**
184  * **rjust**
185  * **small**
186
187## *path-attribute*:   [▶info](./pathattr.md)
188  * **from** *position*
189  * **then**? **to** *position*
190  * **then**? **go**? *direction* *line-length*?
191  * **then**? **go**? *direction* **until**? **even with** *position*
192  * (**then**|**go**) *line-length*? **heading** *compass-angle*
193  * (**then**|**go**) *line-length*? *compass-direction*
194  * **close**
195
196## *line-length*:  [▶info](./linelen.md)
197
198  * *expr*
199  * *expr* **%**
200
201## *compass-angle*:   [▶info](./compassangle.md)
202
203  * *expr*
204
205## *compass-direction*:
206  * **n**
207  * **north**
208  * **ne**
209  * **e**
210  * **east**
211  * **se**
212  * **s**
213  * **south**
214  * **sw**
215  * **w**
216  * **west**
217  * **nw**
218
219## *location-attribute*: [▶info](./locattr.md)
220  * **at** *position*
221  * **with** *edgename* **at** *position*
222  * **with** *dot-edgename* **at** *position*
223
224## *position*:  [▶info](./position.md)
225
226  *  *expr* **,** *expr*
227  *  *place*
228  *  *place* **+** *expr* **,** *expr*
229  *  *place* **-** *expr* **,** *expr*
230  *  *place* **+ (** *expr* **,** *expr* **)**
231  *  *place* **- (** *expr* **,** *expr* **)**
232  *  **(** *position* **,** *position* **)**
233  *  **(** *position* **)**
234  *  *fraction* **of the way between** *position* **and** *position*
235  *  *fraction* **way between** *position* **and** *position*
236  *  *fraction* **between** *position* **and** *position*
237  *  *fraction* **<** *position* **,** *position* **>**
238  *  *distance* *which-way-from* *position*
239
240## *fraction*:
241  *  *expr*
242
243## *distance*
244  *  *expr*
245
246## *which-way-from*:
247
248  *  **above**
249  *  **below**
250  *  **right of**
251  *  **left of**
252  *  **n of**
253  *  **north of**
254  *  **ne of**
255  *  **e of**
256  *  **east of**
257  *  **se of**
258  *  **s of**
259  *  **south of**
260  *  **sw of**
261  *  **w of**
262  *  **west of**
263  *  **nw of**
264  *  **heading** *compass-angle* **from**
265
266## *place*:      [&#9654;info](./place.md)
267
268  *  *object*
269  *  *object* *dot-edgename*
270  *  *edgename* **of** *object*
271  *  ORDINAL **vertex of** *object*
272
273## *object*:
274  *  LABEL
275  *  *object* **.** LABEL
276  *  *nth-object* **of**|**in** *object*
277
278## *nth-object*:
279
280  *  ORDINAL *object-class*
281  *  ORDINAL **last** *object-class*
282  *  ORDINAL **previous** *object-class*
283  *  **last** *object-class*
284  *  **previous** *object-class*
285  *  **last**
286  *  **previous**
287  *  ORDINAL **[]**
288  *  ORDINAL **last []**
289  *  ORDINAL **previous []**
290  *  **last []**
291  *  **previous []**
292
293## *dot-edgename*:
294  * **.n**
295  * **.north**
296  * **.t**
297  * **.top**
298  * **.ne**
299  * **.e**
300  * **.east**
301  * **.right**
302  * **.se**
303  * **.s**
304  * **.south**
305  * **.bot**
306  * **.bottom**
307  * **.sw**
308  * **.w**
309  * **.west**
310  * **.left**
311  * **.nw**
312  * **.c**
313  * **.center**
314  * **.start**
315  * **.end**
316
317## *edgename*:
318  * **n**
319  * **north**
320  * **ne**
321  * **e**
322  * **east**
323  * **se**
324  * **s**
325  * **south**
326  * **sw**
327  * **w**
328  * **west**
329  * **nw**
330  * **t**
331  * **top**
332  * **bot**
333  * **bottom**
334  * **left**
335  * **right**
336  * **c**
337  * **center**
338  * **start**
339  * **end**
340
341
342## *expr*:
343
344  *  NUMBER
345  *  VARIABLE
346  *  COLORNAME
347  *  *place* **.x**
348  *  *place* **.y**
349  *  *object* *dot-property*
350  *  **(** *expr* **)**
351  *  *expr* **+** *expr*
352  *  *expr* **-** *expr*
353  *  *expr* **\*** *expr*
354  *  *expr* **/** *expr*
355  *  **-** *expr*
356  *  **+** *expr*
357  *  **abs (** *expr* **)**
358  *  **cos (** *expr* **)**
359  *  **dist (** *position* **,** *position* **)**
360  *  **int (** *expr* **)**
361  *  **max (** *expr* **,** *expr* **)**
362  *  **min (** *expr* **,** *expr* **)**
363  *  **sin (** *expr* **)**
364  *  **sqrt (** *expr* **)**
365
366## *dot-property*:
367
368  * **.color**
369  * **.dashed**
370  * **.diameter**
371  * **.dotted**
372  * **.fill**
373  * **.ht**
374  * **.height**
375  * **.rad**
376  * **.radius**
377  * **.thickness**
378  * **.wid**
379  * **.width**
380