comparison cmd2.py @ 146:9ffb01d8876f

streamlining parsing
author catherine@dellzilla
date Thu, 20 Nov 2008 14:21:11 -0500
parents 0e0fc729e1a2
children cda32481187c
comparison
equal deleted inserted replaced
145:0e0fc729e1a2 146:9ffb01d8876f
189 pass 189 pass
190 190
191 def __init__(self, *args, **kwargs): 191 def __init__(self, *args, **kwargs):
192 cmd.Cmd.__init__(self, *args, **kwargs) 192 cmd.Cmd.__init__(self, *args, **kwargs)
193 self.history = History() 193 self.history = History()
194 self.terminatorPattern = (pyparsing.oneOf(self.terminators) ^ (pyparsing.Literal('\nEOF') + pyparsing.lineEnd))('terminator')
194 for p in (self.terminatorPattern, self.pipePattern, self.redirectInPattern, self.redirectOutPattern, self.punctuationPattern): 195 for p in (self.terminatorPattern, self.pipePattern, self.redirectInPattern, self.redirectOutPattern, self.punctuationPattern):
195 p.ignore(pyparsing.sglQuotedString) 196 p.ignore(pyparsing.sglQuotedString)
196 p.ignore(pyparsing.dblQuotedString) 197 p.ignore(pyparsing.dblQuotedString)
197 p.ignore(self.commentGrammars) 198 p.ignore(self.commentGrammars)
198 p.ignore(self.commentInProgress) 199 p.ignore(self.commentInProgress)
204 result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in self.shortcuts.items()) 205 result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in self.shortcuts.items())
205 self.stdout.write("Single-key shortcuts for other commands:\n%s\n" % (result)) 206 self.stdout.write("Single-key shortcuts for other commands:\n%s\n" % (result))
206 207
207 commentGrammars = pyparsing.Or([pyparsing.pythonStyleComment, pyparsing.cStyleComment]) 208 commentGrammars = pyparsing.Or([pyparsing.pythonStyleComment, pyparsing.cStyleComment])
208 commentInProgress = pyparsing.Literal('/*') + pyparsing.SkipTo(pyparsing.stringEnd) 209 commentInProgress = pyparsing.Literal('/*') + pyparsing.SkipTo(pyparsing.stringEnd)
209 210 terminators = [';', '\n\n']
210 specialTerminators = {'/*': pyparsing.Literal('*/')('terminator') }
211 terminatorPattern = ((pyparsing.Literal(';') ^ pyparsing.Literal('\n\n'))
212 ^ (pyparsing.Literal('\nEOF') + pyparsing.lineEnd))('terminator')
213 argSeparatorPattern = pyparsing.Word(pyparsing.printables)('command') \ 211 argSeparatorPattern = pyparsing.Word(pyparsing.printables)('command') \
214 + pyparsing.SkipTo(pyparsing.StringEnd())('args') 212 + pyparsing.SkipTo(pyparsing.StringEnd())('args')
215 filenamePattern = pyparsing.Word(pyparsing.alphanums + '#$-_~{},.!:\\/') 213 filenamePattern = pyparsing.Word(pyparsing.alphanums + '#$-_~{},.!:\\/')
216 integerPattern = pyparsing.Word(pyparsing.nums).setParseAction( lambda s,l,t: [ int(t[0]) ] ) 214 integerPattern = pyparsing.Word(pyparsing.nums).setParseAction( lambda s,l,t: [ int(t[0]) ] )
217 pipePattern = pyparsing.Literal('|')('pipe') + pyparsing.restOfLine('pipeTo') 215 pipePattern = pyparsing.Literal('|')('pipe') + pyparsing.restOfLine('pipeTo')
219 + pyparsing.Optional(filenamePattern)('outputTo') 217 + pyparsing.Optional(filenamePattern)('outputTo')
220 redirectInPattern = pyparsing.Literal('<')('input') \ 218 redirectInPattern = pyparsing.Literal('<')('input') \
221 + pyparsing.Optional(filenamePattern)('inputFrom') 219 + pyparsing.Optional(filenamePattern)('inputFrom')
222 punctuationPattern = pipePattern ^ redirectInPattern ^ redirectOutPattern 220 punctuationPattern = pipePattern ^ redirectInPattern ^ redirectOutPattern
223 221
222 def p2(self, s, assumeComplete=False):
223 '''
224 >>> c = Cmd()
225 >>> print c.p2('barecommand').dump()
226 >>> print c.p2('command with args').dump()
227 >>> print c.p2('command with args and terminator; and suffix').dump()
228 >>> print c.p2('command with args, terminator;sufx | piped').dump()
229 >>> print c.p2('simple | piped').dump()
230 >>> print c.p2('output into > afile.txt').dump()
231 >>> print c.p2('output into;sufx | pipethrume plz > afile.txt').dump()
232 >>> print c.p2('output to paste buffer >> ').dump()
233 '''
234 outputParser = pyparsing.oneOf(['>>','>'])('output')
235 terminatorParser = pyparsing.oneOf(self.terminators)('terminator')
236 (pyparsing.stringEnd ^ pyparsing.oneOf(self.terminators) ^ '\nEOF' ^ '|' ^ outputParser)('terminator')
237 statementParser = pyparsing.Combine(pyparsing.Word(pyparsing.printables)('command') +
238 pyparsing.SkipTo(terminatorParser ^ '\nEOF' ^ '|' ^ outputParser ^ pyparsing.stringEnd)('args') +
239 pyparsing.Optional(terminatorParser)
240 )('statement')
241 parser = statementParser + \
242 pyparsing.SkipTo(outputParser ^ '|' ^ pyparsing.stringEnd)('suffix') + \
243 pyparsing.Optional('|' + pyparsing.SkipTo(outputParser ^ pyparsing.stringEnd)('pipeDest')) + \
244 pyparsing.Optional(outputParser + pyparsing.SkipTo(pyparsing.stringEnd)('outputDest'))
245 self.commentGrammars.ignore(pyparsing.sglQuotedString).ignore(pyparsing.dblQuotedString).setParseAction(lambda x: '')
246 self.commentInProgress.ignore(pyparsing.sglQuotedString).ignore(pyparsing.dblQuotedString).ignore(pyparsing.cStyleComment)
247 parser.ignore(pyparsing.sglQuotedString).ignore(pyparsing.dblQuotedString).ignore(self.commentGrammars).ignore(self.commentInProgress)
248 return parser.parseString(s)
249
224 def parsed(self, s, assumeComplete=False): 250 def parsed(self, s, assumeComplete=False):
251 pass
225 ''' 252 '''
226 >>> c = Cmd() 253 >>> c = Cmd()
227 >>> r = c.parsed('quotes "are > ignored" < inp.txt') 254 >>> r = c.parsed('quotes "are > ignored" < inp.txt')
228 >>> r.statement, r.input, r.inputFrom, r.output, r.outputFrom 255 >>> r.statement, r.input, r.inputFrom, r.output, r.outputFrom
229 ('quotes "are > ignored" ', '<', 'inp.txt', '', '') 256 ('quotes "are > ignored" ', '<', 'inp.txt', '', '')
265 result['parseable'] = result.after 292 result['parseable'] = result.after
266 else: 293 else:
267 # does not catch output marks 294 # does not catch output marks
268 if (not assumeComplete) and (command in self.multilineCommands): 295 if (not assumeComplete) and (command in self.multilineCommands):
269 return result # don't bother with the rest, we're still collecting input 296 return result # don't bother with the rest, we're still collecting input
270 result['statement'] = result['unterminated'] = result.before
271 result += parseSearchResults(self.punctuationPattern, s) 297 result += parseSearchResults(self.punctuationPattern, s)
298 result['statement'] = result['unterminated'] = result.before
272 result += parseSearchResults(self.pipePattern, result.parseable) 299 result += parseSearchResults(self.pipePattern, result.parseable)
273 result += parseSearchResults(self.redirectInPattern, result.parseable) 300 result += parseSearchResults(self.redirectInPattern, result.parseable)
274 result += parseSearchResults(self.redirectOutPattern, result.parseable) 301 result += parseSearchResults(self.redirectOutPattern, result.parseable)
275 result += parseSearchResults(self.argSeparatorPattern, result.statement) 302 result += parseSearchResults(self.argSeparatorPattern, result.statement)
276 if self.caseInsensitive: 303 if self.caseInsensitive: