Skip to content

Instantly share code, notes, and snippets.

@pikhovkin
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pikhovkin/47a6073ef816d50fa0d4 to your computer and use it in GitHub Desktop.
Save pikhovkin/47a6073ef816d50fa0d4 to your computer and use it in GitHub Desktop.
Parser "if then else" expression
# coding: utf-8
from funcparserlib.lexer import make_tokenizer, Spec
from funcparserlib.parser import (maybe, many, eof, skip, oneplus, fwd,
name_parser_vars, memoize, SyntaxError)
from funcparserlib.util import pretty_tree
from funcparserlib.contrib.common import unarg, flatten, n, op, op_, sometoks
from funcparserlib.contrib.lexer import (make_comment, make_multiline_comment,
newline, space)
class Template(object):
def __init__(self, *args):
print self.__class__.__name__, args
self.args = args
class Expr(object):
def __init__(self, *args):
print self.__class__.__name__, args
self.args = args
class IF(Template):
pass
class THEN(Template):
pass
class ELSE(Template):
pass
def tokenize(str):
specs = [
space,
Spec('name', r'[A-Za-z\200-\377_][A-Za-z\200-\377_0-9]*'),
Spec('op', r'[;,\\\[\]:=\.\'"\(\)]'),
Spec('number', r'-?(\.[0-9]+)|([0-9]+(\.[0-9]*)?)')
]
useless = ['space']
t = make_tokenizer(specs)
return [x for x in t(str) if x.type not in useless]
def get_template():
"""
stmt -> (matched_stmt | unmathced_stmt)
matched_stmt -> ((if expr then matched_stmt else matched_stmt) | other)
unmathced_stmt -> ((if expr then stmt) | (if expr then matched_stmt else unmathced_stmt))
"""
id = sometoks(['name', 'number'])
expr = oneplus(id)
unarg2 = lambda f: lambda args: f(*args) if isinstance(args, list) else f(*[args])
matched_stmt = fwd()
unmatched_stmt = fwd()
_if = memoize(n('if'))
_then = memoize(n('then'))
_else = memoize(n('else'))
stmt = (matched_stmt | unmatched_stmt) >> unarg2(Template)
exp = expr >> unarg2(Expr)
if_m = _if + exp >> unarg2(IF)
then_m = _then + matched_stmt >> unarg2(THEN)
else_m = _else + matched_stmt >> unarg2(ELSE)
ifthenelse_m = if_m + then_m + else_m >> unarg2(Template)
matched_stmt.define((ifthenelse_m | exp) >> unarg2(Template))
then_unm = _then + stmt >> unarg2(THEN)
else_unm = _else + unmatched_stmt >> unarg2(ELSE)
ifthen_unm = if_m + then_unm >> unarg2(Template)
ifthenelse_unm = if_m + then_m + else_unm >> unarg2(Template)
unmatched_stmt.define((ifthen_unm | ifthenelse_unm) >> unarg2(Template))
return stmt
template = get_template()
def parse(seq):
return template.parse(seq)
def main():
sql = 'if A then if B then C else if D then E else 42'
parse(tokenize(sql))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment