OILS / tools / find / ast.py View on Github | oilshell.org

334 lines, 297 significant
1# Copyright 2019 Wilke Schwiedop. All rights reserved.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7"""
8ast.py: AST utilities for find.
9"""
10
11import stat
12
13from _devbuild.gen import find_asdl as asdl
14from _devbuild.gen import find_nt
15
16import tokenizer
17import parser
18
19#
20# path tests
21#
22def _name(glob):
23 return asdl.expr.PathTest(
24 asdl.pathAccessor_e.Filename,
25 asdl.predicate.GlobMatch(glob)
26 )
27def _iname(glob):
28 return asdl.expr.PathTest(
29 asdl.pathAccessor_e.Filename,
30 asdl.predicate.GlobMatch(glob, ignoreCase=True)
31 )
32def _lname(glob):
33 assert False
34def _ilname(glob):
35 assert False
36def _path(glob):
37 return asdl.expr.PathTest(
38 asdl.pathAccessor_e.FullPath,
39 asdl.predicate.GlobMatch(glob)
40 )
41def _ipath(glob):
42 return asdl.expr.PathTest(
43 asdl.pathAccessor_e.FullPath,
44 asdl.predicate.GlobMatch(glob, ignoreCase=True)
45 )
46def _regex(re):
47 return asdl.expr.PathTest(
48 asdl.pathAccessor_e.FullPath,
49 asdl.predicate.RegexMatch(re)
50 )
51def _iregex(re):
52 return asdl.expr.PathTest(
53 asdl.pathAccessor_e.FullPath,
54 asdl.predicate.RegexMatch(re, ignoreCase=True)
55 )
56def _readable():
57 return asdl.expr.PathTest(
58 asdl.pathAccessor_e.FullPath,
59 asdl.predicate.Readable()
60 )
61def _writable():
62 return asdl.expr.PathTest(
63 asdl.pathAccessor_e.FullPath,
64 asdl.predicate.Writable()
65 )
66def _executable():
67 return asdl.expr.PathTest(
68 asdl.pathAccessor_e.FullPath,
69 asdl.predicate.Executable()
70 )
71#
72# stat tests
73#
74def parse_number_predicate(n_str, factor=1):
75 if n_str[0] == '+':
76 return asdl.predicate.GE(int(n_str[1:]) * factor)
77 if n_str[0] == '-':
78 return asdl.predicate.LE(int(n_str[1:]) * factor)
79 return asdl.predicate.EQ(int(n_str) * factor)
80def _amin(n_str):
81 assert False
82def _anewer(f):
83 assert False
84def _atime(n_str):
85 return asdl.expr.StatTest(asdl.statAccessor_e.AccessTime, parse_number_predicate(n_str))
86def _cmin(n_str):
87 assert False
88def _cnewer(f):
89 assert False
90def _ctime(n_str):
91 return asdl.expr.StatTest(asdl.statAccessor_e.CreationTime, parse_number_predicate(n_str))
92def _mmin(n_str):
93 assert False
94def _mnewer(f):
95 assert False
96def _mtime(n_str):
97 return asdl.expr.StatTest(asdl.statAccessor_e.ModificationTime, parse_number_predicate(n_str))
98def _newerXY(): # TODO: read manpage
99 assert False
100def _used(n_str):
101 assert False
102def _empty():
103 return asdl.expr.StatTest(
104 asdl.statAccessor_e.Size,
105 asdl.predicate.EQ(0)
106 )
107def _size(n_str):
108 suffixMap = {
109 'b' : 512, # default
110 'c' : 1,
111 'w' : 2,
112 'k' : 1024**1,
113 'M' : 1024**2,
114 'G' : 1024**3,
115 }
116 if n_str[-1] in suffixMap:
117 factor = suffixMap[n_str[-1]]
118 n_str = n_str[:-1]
119 else:
120 factor = suffixMap['b']
121 return asdl.expr.StatTest(asdl.statAccessor_e.Size, parse_number_predicate(n_str, factor=factor))
122def _inum(n_str):
123 return asdl.expr.StatTest(asdl.statAccessor_e.Inode, parse_number_predicate(n_str))
124def _samefile(f):
125 assert False
126def _links(n_str):
127 return asdl.expr.StatTest(asdl.statAccessor_e.LinkCount, parse_number_predicate(n_str))
128def _perm(mode): # [+-/]mode
129 assert False
130def _type(t_str):
131 tMap = {
132 's' : stat.S_IFSOCK,
133 'l' : stat.S_IFLNK,
134 'f' : stat.S_IFREG,
135 'b' : stat.S_IFBLK,
136 'd' : stat.S_IFDIR,
137 'c' : stat.S_IFCHR,
138 'p' : stat.S_IFIFO,
139 }
140 t = tMap[t_str]
141 return asdl.expr.StatTest(
142 asdl.statAccessor_e.Filetype,
143 asdl.predicate.EQ(t)
144 )
145def _xtype(t_str):
146 assert False
147def _uid(uid_str):
148 uid = int(uid)
149 return asdl.expr.StatTest(
150 asdl.statAccessor_e.Uid,
151 asdl.predicate.EQ(uid)
152 )
153def _gid(gid_str):
154 gid = int(gid)
155 return asdl.expr.StatTest(
156 asdl.statAccessor_e.Gid,
157 asdl.predicate.EQ(gid)
158 )
159def _user(user):
160 return asdl.expr.StatTest(
161 asdl.statAccessor_e.Username,
162 asdl.predicate.StringMatch(user)
163 )
164def _group(group):
165 return asdl.expr.StatTest(
166 asdl.statAccessor_e.Groupname,
167 asdl.predicate.StringMatch(group)
168 )
169def _nouser():
170 assert False
171def _nogroup():
172 assert False
173def _fstype(fsType):
174 assert False
175#
176# actions
177#
178def _print():
179 return asdl.expr.PrintAction()
180def _print0():
181 # TODO verify fmt
182 return asdl.expr.PrintAction(format="%P\0")
183def _printf(fmt):
184 return asdl.expr.PrintAction(format=fmt)
185def _fprint(f):
186 return asdl.expr.PrintAction(file=f)
187def _fprint0(f):
188 # TODO verify fmt
189 return asdl.expr.PrintAction(file=f, format="%P\0")
190def _fprintf(f, fmt):
191 return asdl.expr.PrintAction(file=f, format=fmt)
192def _ls():
193 return asdl.expr.LsAction()
194def _fls(f):
195 return asdl.expr.LsAction(file=f)
196def _exec(*argv):
197 argv = list(argv)
198 batch = True if argv[-1] == '+' else False if argv[-1] == ';' else None
199 if batch is None:
200 assert False
201 return asdl.expr.ExecAction(batch=batch, dir=False, ok=False, argv=argv[:-1])
202def _execdir(*argv):
203 argv = list(argv)
204 batch = True if argv[-1] == '+' else False if argv[-1] == ';' else None
205 if batch is None:
206 assert False
207 return asdl.expr.ExecAction(batch=batch, dir=True, ok=False, argv=argv[:-1])
208def _ok(*argv):
209 argv = list(argv)
210 batch = True if argv[-1] == '+' else False if argv[-1] == ';' else None
211 if batch is None:
212 assert False
213 return asdl.expr.ExecAction(batch=batch, dir=False, ok=True, argv=argv[:-1])
214def _okdir(*argv):
215 argv = list(argv)
216 batch = True if argv[-1] == '+' else False if argv[-1] == ';' else None
217 if batch is None:
218 assert False
219 return asdl.expr.ExecAction(batch=batch, dir=True, ok=True, argv=argv[:-1])
220def _delete():
221 return asdl.expr.DeleteAction()
222def _prune():
223 return asdl.expr.PruneAction()
224def _quit():
225 return asdl.expr.QuitAction()
226
227exprMap = {
228 # atoms
229 tokenizer.TRUE : asdl.expr.True_,
230 tokenizer.FALSE : asdl.expr.False_,
231 # path tests
232 tokenizer.NAME : _name,
233 tokenizer.INAME : _iname,
234 tokenizer.LNAME : _lname,
235 tokenizer.ILNAME : _ilname,
236 tokenizer.PATH : _path,
237 tokenizer.IPATH : _ipath,
238 tokenizer.REGEX : _regex,
239 tokenizer.IREGEX : _iregex,
240 # stat tests
241 tokenizer.AMIN : _amin,
242 tokenizer.ANEWER : _anewer,
243 tokenizer.ATIME : _atime,
244 tokenizer.CMIN : _cmin,
245 tokenizer.CNEWER : _cnewer,
246 tokenizer.CTIME : _ctime,
247 tokenizer.MMIN : _mmin,
248 tokenizer.MNEWER : _mnewer,
249 tokenizer.MTIME : _mtime,
250 tokenizer.NEWERXY : _newerXY,
251# tokenizer.USED : _used,
252 tokenizer.EMPTY : _empty,
253 tokenizer.SIZE : _size,
254 tokenizer.READABLE : _readable,
255 tokenizer.WRITABLE : _writable,
256 tokenizer.EXECUTABLE : _executable,
257# tokenizer.INUM : _inum,
258# tokenizer.SAMEFILE : _samefile,
259# tokenizer.LINKS : _links,
260 tokenizer.PERM : _perm,
261 tokenizer.TYPE : _type,
262 tokenizer.XTYPE : _xtype,
263 tokenizer.UID : _uid,
264 tokenizer.GID : _gid,
265 tokenizer.USER : _user,
266 tokenizer.GROUP : _group,
267 tokenizer.NOUSER : _nouser,
268 tokenizer.NOGROUP : _nogroup,
269# tokenizer.FSTYPE : _fstype,
270 # actions
271 tokenizer.PRINT : _print,
272 tokenizer.PRINT0 : _print0,
273 tokenizer.PRINTF : _printf,
274 tokenizer.FPRINT : _fprint,
275 tokenizer.FPRINT0 : _fprint0,
276 tokenizer.FPRINTF : _fprintf,
277 tokenizer.EXEC : _exec,
278 tokenizer.EXECDIR : _execdir,
279 tokenizer.OK : _ok,
280 tokenizer.OKDIR : _okdir,
281 tokenizer.DELETE : _delete,
282 tokenizer.PRUNE : _prune,
283 tokenizer.QUIT : _quit,
284}
285
286def _start(children):
287 assert len(children) == 2
288 assert tokenizer.is_eof(children[1].typ)
289 return AST(children[0])
290def _concatenation(children):
291 assert len(children) >= 2
292 return asdl.expr.Concatenation(
293 [AST(c) for c in children if c.typ != tokenizer.COMMA]
294 )
295def _disjunction(children):
296 assert len(children) >= 2
297 return asdl.expr.Disjunction(
298 [AST(c) for c in children if c.typ != tokenizer.OR]
299 )
300def _conjunction(children):
301 assert len(children) >= 2
302 return asdl.expr.Conjunction(
303 [AST(c) for c in children if c.typ != tokenizer.AND]
304 )
305def _negation(children):
306 assert len(children) == 2
307 assert children[0].typ == tokenizer.BANG
308 return asdl.expr.Negation(AST(children[1]))
309def _group(children):
310 assert len(children) == 3
311 assert children[0].typ == tokenizer.LPAR
312 assert children[2].typ == tokenizer.RPAR
313 return AST(children[1])
314def _expr(children):
315 f = exprMap[children[0].typ]
316 return f(*(c.tok[0] for c in children[1:]))
317
318ntMap = {
319 find_nt.start : _start,
320 find_nt.concatenation : _concatenation,
321 find_nt.disjunction : _disjunction,
322 find_nt.conjunction : _conjunction,
323 find_nt.negation : _negation,
324 find_nt.group : _group,
325 find_nt.expr : _expr,
326}
327
328def AST(pnode):
329 if tokenizer.is_nonterminal(pnode.typ):
330 assert pnode.typ not in exprMap
331 return ntMap[pnode.typ](pnode.children)
332 else:
333 assert pnode.typ not in ntMap
334 return exprMap[pnode.typ]()