~psmay/+junk/mskp-parser.dev

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
for { init var i 0 ; test [i < 10]; iter ++ i } {
	print i;
};

// This is valid syntax, but it doesn't syntactically bind the members of a
// chain together.
if [i < 3] {
	statement1;
	statement2;
};
elseif [i < 5] {
	statement3;
	statement4;
};
else {
	statement5;
	statement6;
};

/* The most orthographic way to do the same is probably this, which uses XSL's
 * idiom and has a form corresponding to (choose (when)+ (otherwise)?)
*/
choose {
	when [i < 3] {
		statement1;
		statement2;
	};
	when [i < 5] {
		statement3;
		statement4;
	};
	otherwise {
		statement5;
		statement6;
	};
};

/* Another suggestion has the elses nested in the if but only at the end; in
 * the form (if statements* (elseif)+ (else)?). It's not as intuitive for C
 * programmers. */
if [i < 3] {
	statement1;
	statement2;
elseif [i < 5]
	{
		statement3;
		statement4;
	};
else
	{
		statement5;
		statement6;
	};
};


// It would be possible with a right-associative infix grouping to make the
// production using else as the operator.
//	- (if C S...) evaluates C, which is a conditional. If C evaluates to truth,
//	run statements S and then return a successful result. Otherwise, return
//	unsuccessful.
//	- (unless C S...) is identical to (if) except that the complement of C is
//	used instead of C.
//	- (just S...) is identical to (if (true) S...).
//	- (else A B), or [A else B], runs A (which is some form of if). If A yields
//	a success result, yield a success result. Otherwise, run B (which is also
//	some form of if) and return its result.

$rinfix[
	(if [i < 3] {
		statement1;
		statement2;
	})
	else (if [i < 5] {
		statement3;
		statement4;
	})
	else (just {
		statement5;
		statement6;
	})
];

// $rinfix here represents a right-associating infix grouping. For example,
//	$rinfix[A B C D E F G] ->
//	$rinfix[A B C D $rinfix[E F G]] ->
//	$rinfix[A B $rinfix[C D $rinfix[E F G]]] ->
//	[A B [C D [E F G]]] ->
//	(B A (D C (F E G)))

// The above would thus be equivalent to this:

else
	(if [i < 3] (statement1) (statement2))
	(else
		(if [i < 5] (statement3) (statement4))
		(just (statement5) (statement6))
	)
;

// If identical nests are optimized out, this would result:

else
	(if [i < 3] (statement1) (statement2))
	(if [i < 5] (statement3) (statement4))
	(just (statement5) (statement6))
;

// which itself is orthogonal to the choose-when-otherwise example, with the
// words replaced by else, if, and just, respectively. I think I prefer the
// choose form. The keywords might be changed though:

which {
	test [i < 3] {
		statement1; statement2;
	};
	test [i < 5] {
		statement3; statement4;
	};
	none {
		statement5; statement6;
	};
};

// And just because we want to test the parser with qualified names:

qualified test;

q:which {
	q:test [i < 3] {
		statement1;
		statement2
	};
	q:test [i < 5] {
		statement3;
		statement4
	};
	q:none {
		statement5;
		statement6
	};
};

// We recently added a new block type.
for `each n; in aggreg' {
	do something;
};

// Some examples with tags:

tag examples;

// Basic
foo(a b c);
+(a b c);
>(a b c);
// Square
foo[a b c];
+[a b c];
>[a b c];
// Block
foo{a b; c d};
foo:{a b; c d};
+{a b; c d};
+:{a b; c d};
// Q-Block
foo`a b; c d';
foo:`a b; c d';
+`a b; c d';
+:`a b; c d';