Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Advanced command line pattern parser.

  • Loading branch information...
commit 16ddf2526993db1f198814a8940389b4aaf3f8b3 1 parent 8fc4137
@pcapriotti authored
Showing with 57 additions and 3 deletions.
  1. +5 −3 cli.py
  2. +52 −0 pledger/pattern.py
View
8 cli.py
@@ -1,6 +1,8 @@
from argparse import ArgumentParser
+from pledger.account import Account
from pledger.report import reports
from pledger.filter import Filter, BeginFilter, EndFilter
+from pledger.pattern import PatternParser
from pledger.parser import Parser
from pledger.sorting import MapSorting, ExpressionSorting
from pledger.rule import RuleCollection
@@ -33,9 +35,9 @@ def run_cli():
report_factory = reports.get(args.report)
if report_factory is None:
raise Exception("no such report " + args.report)
- filters = [Filter.matches(re.compile(pattern)) for pattern in args.patterns]
- if filters:
- filter &= reduce(Filter.__or__, filters)
+ if args.patterns:
+ pattern_parser = PatternParser(args.patterns)
+ filter &= pattern_parser.parse_filter()
filename = args.filename and args.filename[0] or None
if filename is None:
View
52 pledger/pattern.py
@@ -0,0 +1,52 @@
+from filter import Filter
+import re
+
+class PatternParser(object):
+ def __init__(self, tokens):
+ self.tokens = tokens
+ self.pos = 0
+
+ def parse_filter(self):
+ last_operator = Filter.__or__
+ result = None
+ negated = False
+
+ while self.has_tokens():
+ token = self.get()
+ if token == '(':
+ filter = self.parse_filter()
+ result = self.combine(result, filter, last_operator, negated)
+ last_operator = Filter.__or__
+ negated = False
+ elif token == ')':
+ return result
+ elif token == 'and':
+ last_operator = Filter.__and__
+ negated = False
+ elif token == 'or':
+ last_operator = Filter.__or__
+ negated = False
+ elif token == 'not':
+ negated = True
+ else:
+ filter = Filter.matches(re.compile(token))
+ result = self.combine(result, filter, last_operator, negated)
+ last_operator = Filter.__or__
+ negated = False
+
+ return result
+
+ def combine(self, f1, f2, op, neg):
+ if neg: f2 = ~f2
+ if f1:
+ return op(f1, f2)
+ else:
+ return f2
+
+ def get(self):
+ result = self.tokens[self.pos]
+ self.pos += 1
+ return result
+
+ def has_tokens(self):
+ return self.pos < len(self.tokens)

0 comments on commit 16ddf25

Please sign in to comment.
Something went wrong with that request. Please try again.