Repository navigation
Expand file tree
/
Copy pathnotes
More file actions
355 lines (305 loc) · 7.21 KB
/
Copy pathnotes
File metadata and controls
355 lines (305 loc) · 7.21 KB
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
Psuedo code/ notes:
Disclaimer: most of this is to help me think
a lot of it probably might not be exactly implemented
================================1/8/15===============
command_stream
{
char* buffer
int iterator = 0 // index of last char we read
}
make_command_stream( function_t getbyte, arg ):
while no error in getting character:
get a character
resize buffer if needed
store character in buffer
read_command:
notes:
read chars from stream into buffer
stop at a valid point or syntax err
when we can identify a full command
create struct
-talked about recursion and pipes
====1/9/15============================================
some notes on grammar
syntax:
comment:
- # allowable chars \n
whitespace(spc):
- [space, tab, newline] (check on newline?)
word:
-sequence of non spc chars
simple command(sc):
- word spc
- word (excluding "if", "while", "until") spc sc
compount command(cpd)
- if cc then cc fi
- if cc then cc else cc fi
- while cc do cc done
- until cc do cc done
I/O redirect(red)
- [empty]
- < word
- > word
- < word > word
command(c)
- [sc, cpl, cpd, ss] red
pipelines(pip):
- c
- c | (pip)
complete command(cpl):
- pip ;
- pip \n
- cpl cpl (maybe?)
subshell(ss):
- ( cpl )
example----------
ex)
echo "Stars"
i=0
while( i<=5 )
do
j=0
while( j<=i )
do
echo -n " *"
j++
done
echo ""
i++
done
note: this ex) is a little shitty cause of the vars, but treat "var=val" as a single word for now, also I left out spc's below, cause we'll maybe just eat them up when we build words and stuff
cpl
cpl
pip
c
sc
word( excluding logical)
echo
word
"Stars"
red
[empty]
cpl
pip
c
sc
i=o
red
[empty]
cpl
pip
c
cpd
while
cpl
pip
c
ss
(
cpl
pip
sc
word
i<=5
red
[empty]
)
do
...
red
[empty]
...
--------
===================1/10/15=================================================
very rough psuedocode
void append_to_token( char c, char* token )
{
if token is non null
if
}
// puts a bunch of tokens in cstrings into the command stream
make_command_stream( function_t getbyte, getbyte_arg)
{
char c
int max_size = 10
int cur_size = 0
char* token = (char*) malloc( max_size ) // token is a cstring
while( getting a byte into c returns valid )
{
switch c // might not actually be a switch statement later
case [a-zA-Z0-9!%+,-./:@^_]
if
append to token, resize if needed
break
case [space or tab]
if prev was a space
ignore ?
else
close the previous token
put it in the stream
make a new token
break
// i think it's worth it to make \n a token ? cause it's significant in the syntax
case [\n]
if the previous was \n ignore
// fall through
case [;]
case [|]
case [(]
case [)]
case [<]
case [>]
case [#]
close the prev token(put in a \0 char)
put it in the stream
put c in a new token, close it
put that in the stream too
make a new token
break
}
return the stream
}
// before this is called, s is a collection of c strings, each of which is one of
// [ word ][ \n ][ ; ][ | ][ ( ][ ) ][ < ][ > ]
// I'm gonna go with a shift-reduce implementation for now
// works like this: shift a token into dostuff region, reduce dostuff region, repeat
read_command_stream( command_stream_t s )
{
command* divider // points to second element (index 1) @ start
-> command* top // points to the top of command tree
int scope = 0 // where we are in base[]
command* base[ 5 ] // 5 for now, pointer to top of scope
// base[0] may replace top
int cond = 0
while divider isn't the end
{
// first look at new token to the left of divider that we just put on
if ( word -> first char is a wordcharacter )
{
if ( it matches "if" "while" or "until" )
{
if ( immediate left of this token is ';' or '\n' or '|' or '(' )
{
make a new command
point u.command[1] of the sequence command assoc. with
the immediate left token at this command
( I think it'll be base )
increment scope,
make an appropriate new conditional command while, if, until
zero out the u.command[] array
put in base[scope] realloc if necesary
// maybe sep function
// done?
}
else
// do nothing it's just a word then, fall through and continue
}
else if ( matches "done", "fi )
{
if( prev. token is ';' '\n' )
{
cond = 0 ;
maybe null out base[scope]
decrement scope
}
else
//do nothing, 'tis a word
}
else if ( matches "do" "then" "else")
{
continue
}
---- this is for nonlogical words
if ( immediate left command is simple command )
{
concat this token onto the word of that command
}
else
{
make a new simple command
put this token into the word of that command
if( this isn't the first command )
point base[scope] 's u.command[] at this by finding the first
non null element in that array and putting this there
else if ( this is the first command )
point base[0] at this
}
----
}
move the divider right one command
}
}
reduce_stack( stack_t stack )
{
command* top
}
===========1/11/15=========
REDO read_stream
read_command_stream( command_stream_t s )
{
command* divider // points to second element (index 1) @ start
-> command* top // points to the top of command tree
int scope = 0 // where we are in base[]
command* base[ 5 ] // 5 for now, pointer to top of scope
// base[0] may replace top
int cond = 0
command* last
while divider isn't the end
{
// first look at new token to the left of divider that we just put on
if ( last == null )
if ( word -> first char is a wordcharacter )
{
if ( it matches "if" "while" or "until" )
{
if ( immediate left of this token is ';' or '\n' or '|' or '(' )
{
make a new command
point u.command[1] of the sequence command assoc. with
the immediate left token at this command
( I think it'll be base )
increment scope,
make an appropriate new conditional command while, if, until
zero out the u.command[] array
put in base[scope] realloc if necesary
// maybe sep function
// done?
}
else
// do nothing it's just a word then, fall through and continue
}
else if ( matches "done", "fi )
{
if( prev. token is ';' '\n' )
{
cond = 0 ;
maybe null out base[scope]
decrement scope
}
else
//do nothing, 'tis a word
}
else if ( matches "do" "then" "else")
{
continue
}
---- this is for nonlogical words
if ( immediate left command is simple command )
{
concat this token onto the word of that command
}
else
{
make a new simple command
put this token into the word of that command
if( this isn't the first command )
point base[scope] 's u.command[] at this by finding the first
non null element in that array and putting this there
else if ( this is the first command )
point base[0] at this
}
----
}
move the divider right one command
}
}