lep_parser.py
'''\
Logical Expression Recursive Descent Parser.
BNF:
expr = term
= term oper term
term = name
= '(' expr ')'
= not term
name = alpha
= alpha alnums
alnums = alnum
= alnum alnums
alnum = alpha
= number
oper = '|'
= '&'
= '^'
not = 'not'
alpha = 'A'..'Z'
= 'a'..'z'
number = '0'..'9'
'''
from lep_objects import *
class source (object):
'''Logical expression source text class.'''
lib = {}
def __init__ (self, t):
self.text = t
self.index = 0
def reset (self):
self.index = 0
return self()
def incr (self):
if len(self.text) <= self.index:
return self()
self.index += 1
return self()
def skip_ws (self):
ch = self()
while ch.isspace():
ch = self.incr()
return self()
def word (self, w):
n = len(w)
ix = self.index
w1 = self.text[ix:ix+n].upper()
w2 = w.upper()
if w1 == w2:
self.index += n
return True
return False
def __call__ (self):
ix = self.index
ch = self.text[ix:ix+1]
return ch
def __len__ (self):
return len(self.text)
def __str__ (self):
return self.text
def __repr__ (self):
s = '"%s"[%d]'
t = (self.text, self.index)
return s % t
def parse_operator (src):
'''Test: Operator.'''
ch = src.skip_ws()
if ch == '|':
src.incr()
return oper_or()
if ch == '&':
src.incr()
return oper_and()
if ch == '^':
src.incr()
return oper_xor()
if src.word('or'):
print 'oper.OR:'
return oper_or()
if src.word('and'):
print 'oper.AND:'
return oper_and()
if src.word('xor'):
print 'oper.XOR:'
return oper_xor()
if src.word('nor'):
print 'oper.NOR:'
return oper_nor()
if src.word('nand'):
print 'oper.NAND:'
return oper_nand()
raise SyntaxError('Operator expected! [@%d]' % src.index)
def parse_term (src):
'''Test: Term.'''
ch = src.skip_ws()
if ch == '(':
src.incr()
expr = parse_expression(src)
ch = src.skip_ws()
if ch != ')':
raise SyntaxError('Close parenthesis expected! [@%d]' % src.index)
src.incr()
print 'term.expr: %s' % expr
return expr
if src.word('not'):
print 'expr.NOT:'
op = oper_not()
t1 = parse_term(src)
print 'expr.t1: %s' % t1
return expression(op, t1, None)
if ch.isalpha():
name = ch
ch = src.incr()
while ch.isalnum():
name += ch
ch = src.incr()
if name in src.lib:
print 'term.name: %s (exists)' % name
return src.lib[name]
print 'term.name: %s (NEW)' % name
t = term(name)
src.lib[name] = t
return t
raise SyntaxError('Term expected! [@%d]' % src.index)
def parse_expression (src):
'''Test: Expression.'''
ch = src.skip_ws()
t1 = parse_term(src)
print 'expr.t1: %s' % t1
try:
op = parse_operator(src)
print 'expr.op: %s' % op
except SyntaxError:
return t1
t2 = parse_term(src)
print 'expr.t2: %s' % t2
return expression(op, t1, t2)
'''eof'''