summaryrefslogtreecommitdiff
path: root/appl/cmd/mash/mash.y
blob: 2417ef51f4a521869e7382111b5630b3e6caaa3b (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
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
%{
include	"mash.m";

#
#	mash parser.  Thread safe.
#
%}

%module Mashparse
{
	PATH:	con "/dis/lib/mashparse.dis";

	init:		fn(l: Mashlib);
	parse:	fn(e: ref Mashlib->Env);

	YYSTYPE: adt
	{
		cmd:		ref Mashlib->Cmd;
		item:		ref Mashlib->Item;
		items:	list of ref Mashlib->Item;
		flag:		int;
	};

	YYETYPE:	type ref Mashlib->Env;
}

%{
	lib:		Mashlib;

	Cmd, Item, Stab, Env:		import lib;
%}

%left				Lcase Lfor Lif Lwhile Loffparen	# low prec
%left				Lelse
%left				Lpipe
%left				Leqeq Lmatch Lnoteq
%right			Lcons
%left				Lcaret
%left				Lnot Lhd Ltl Llen
%type	<flag>	term
%type	<item>	item wgen witem word redir sword
%type	<items>	asimple list
%type	<cmd>	case cases cmd cmda cmds cmdt complex
%type	<cmd>	epilog expr cbrace cobrace obrace simple
%token	<item>	Lword
%token			Lbackq Lcolon Lcolonmatch Ldefeq Leq Lmatched Lquote
%token			Loncurly Lonparen Loffcurly Loffparen Lat
%token			Lgreat Lgreatgreat Lless Llessgreat
%token			Lfn Lin Lrescue
%token			Land Leof Lsemi
%token			Lerror

%%

script	: tcmds
		;

tcmds	: # empty
		| tcmds xeq
		;

xeq		: cmda
			{ $1.xeq(e.yyenv); }
		| Leof
		| error
		;

cmdt		: # empty
			{ $$ = nil; }
		| cmdt cmda
			{ $$ = Cmd.cmd2(Cseq, $1, $2); }
		;

cmda	: cmd term
			{ $$ = $1.mkcmd(e.yyenv, $2); }
		;

cmds		: cmdt
		| cmdt cmd
			{ $$ = Cmd.cmd2(Cseq, $1, $2.mkcmd(e.yyenv, 0)); }
		;

cmd		: simple
		| complex
		| cmd Lpipe cmd
			{  $$ = Cmd.cmd2(Cpipe, $1, $3); }
		;

simple	: asimple
			{ $$ = e.yyenv.mksimple($1); }
		| asimple Lcolon list cobrace
			{
				$4.words = e.yyenv.mklist($3);
				$$ = Cmd.cmd1w(Cdepend, $4, e.yyenv.mklist($1));
			}
		;

complex	: Loncurly cmds Loffcurly epilog
			{ $$ = $4.cmde(Cgroup, $2, nil); }
		| Lat Loncurly cmds Loffcurly epilog
			{ $$ = $5.cmde(Csubgroup, $3, nil); }
		| Lfor Lonparen sword Lin list Loffparen cmd
			{ $$ = Cmd.cmd1i(Cfor, $7, $3); $$.words = lib->revitems($5); }
		| Lif Lonparen expr Loffparen cmd
			{ $$ = Cmd.cmd2(Cif, $3, $5); }
		| Lif Lonparen expr Loffparen cmd Lelse cmd
			{ $$ = Cmd.cmd2(Cif, $3, Cmd.cmd2(Celse, $5, $7)); }
		| Lwhile Lonparen expr Loffparen cmd
			{ $$ = Cmd.cmd2(Cwhile, $3, $5); }
		| Lcase expr Loncurly cases Loffcurly
			{ $$ = Cmd.cmd2(Ccase, $2, $4.rotcases()); }
		| sword Leq list
			{ $$ = Cmd.cmdiw(Ceq, $1, $3); }
		| sword Ldefeq list
			{ $$ = Cmd.cmdiw(Cdefeq, $1, $3); }
		| Lfn word obrace
			{ $$ = Cmd.cmd1i(Cfn, $3, $2); }
		| Lrescue word obrace
			{ $$ = Cmd.cmd1i(Crescue, $3, $2); }
		| word Lcolonmatch word cbrace
			{
				$4.item = $3;
				$$ = Cmd.cmd1i(Crule, $4, $1);
			}
		;

cbrace	: Lcolon Loncurly cmds Loffcurly
			{ $$ = Cmd.cmd1(Clistgroup, $3); }
		| Loncurly cmds Loffcurly
			{ $$ = Cmd.cmd1(Cgroup, $2); }
		;

cobrace	: # empty
			{ $$ = Cmd.cmd1(Cnop, nil); }
		| cbrace
		;

obrace	: # empty
			{ $$ = nil; }
		| Loncurly cmds Loffcurly
			{ $$ = $2; }
		;

cases		: # empty
			{ $$ = nil; }
		| cases case
			{ $$ = Cmd.cmd2(Ccases, $1, $2); }
		;

case		: expr Lmatched cmda
			{ $$ = Cmd.cmd2(Cmatched, $1, $3); }
		;

asimple	: word
			{ $$ = $1 :: nil; }
		| asimple item
			{ $$ = $2 :: $1; }
		;

item		: witem
		| redir
		;

witem	: word
		| wgen
		;

wgen		: Lbackq Loncurly cmds Loffcurly
			{ $$ = Item.itemc(Ibackq, $3); }
		| Lquote Loncurly cmds Loffcurly
			{ $$ = Item.itemc(Iquote, $3); }
		| Lless Loncurly cmds Loffcurly
			{ $$ = Item.itemc(Iinpipe, $3); }
		| Lgreat Loncurly cmds Loffcurly
			{ $$ = Item.itemc(Ioutpipe, $3); }
		;

word		: Lword
		| word Lcaret word
			{ $$ = Item.item2(Icaret, $1, $3); }
		| Lonparen expr Loffparen
			{ $$ = Item.itemc(Iexpr, $2); }
		;

sword	: Lword
			{ $$ = $1.sword(e.yyenv); }
		;

list		: # empty
			{ $$ = nil; }
		| list witem
			{ $$ = $2 :: $1; }
		;

epilog	: # empty
			{ $$ = ref Cmd; $$.error = 0; }
		| epilog redir
			{ $$ = $1; $1.cmdio(e.yyenv, $2); }
		;

redir		: Lless word
			{ $$ = Item.itemr(Rin, $2); }
		| Lgreat word
			{ $$ = Item.itemr(Rout, $2); }
		| Lgreatgreat word
			{ $$ = Item.itemr(Rappend, $2); }
		| Llessgreat word
			{ $$ = Item.itemr(Rinout, $2); }
		;

term		: Lsemi
			{ $$ = 0; }
		| Leof
			{ $$ = 0; }
		| Land
			{ $$ = 1; }
		;

expr		: Lword
			{ $$ = Cmd.cmd1i(Cword, nil, $1); }
		| wgen
			{ $$ = Cmd.cmd1i(Cword, nil, $1); }
		| Lonparen expr Loffparen
			{ $$ = $2; }
		| expr Lcaret expr
			{ $$ = Cmd.cmd2(Ccaret, $1, $3); }
		| Lhd expr
			{ $$ = Cmd.cmd1(Chd, $2); }
		| Ltl expr
			{ $$ = Cmd.cmd1(Ctl, $2); }
		| Llen expr
			{ $$ = Cmd.cmd1(Clen, $2); }
		| Lnot expr
			{ $$ = Cmd.cmd1(Cnot, $2); }
		| expr Lcons expr
			{ $$ = Cmd.cmd2(Ccons, $1, $3); }
		| expr Leqeq expr
			{ $$ = Cmd.cmd2(Ceqeq, $1, $3); }
		| expr Lnoteq expr
			{ $$ = Cmd.cmd2(Cnoteq, $1, $3); }
		| expr Lmatch expr
			{ $$ = Cmd.cmd2(Cmatch, $1, $3); }
		;
%%

init(l: Mashlib)
{
	lib = l;
}

parse(e: ref Env)
{
	y := ref YYENV;
	y.yyenv = e;
	y.yysys = lib->sys;
	y.yystderr = e.stderr;
	yyeparse(y);
}

yyerror(e: ref YYENV, s: string)
{
	e.yyenv.report(s);
	e.yyenv.suck();
}

yyelex(e: ref YYENV): int
{
	return e.yyenv.lex(e.yylval);
}