From 9798dca05fabf5c7e0a47afc586c3d5a1da7befe Mon Sep 17 00:00:00 2001 From: Paul Scurek Date: Wed, 7 Aug 2013 00:16:20 +0000 Subject: [PATCH 1/3] Trac 15018: added recover_formula, recover_formula_internal, prefix_to_infix, and to_infix_internal to logicparser.py --- src/sage/logic/logicparser.py | 249 +++++++++++++++++++++++++++++++++- 1 file changed, 242 insertions(+), 7 deletions(-) diff --git a/src/sage/logic/logicparser.py b/src/sage/logic/logicparser.py index 649979827af..9cbc7c5ebdd 100644 --- a/src/sage/logic/logicparser.py +++ b/src/sage/logic/logicparser.py @@ -3,12 +3,12 @@ A parse tree of a boolean formula is a nested list, where each branch is either a single variable, or a formula composed of either two variables and a binary -operator or one variable and a unary operator. The function parse() produces +operator or one variable and a unary operator. The function parse produces a parse tree that is simplified for the purposes of more efficient truth value -evaluation. The function polish_parse() produces the full parse tree of a boolean +evaluation. The function polish_parse produces the full parse tree of a boolean formula which is used in functions related to proof and inference. That is, -parse() is meant to be used with functions in the logic module that perform -semantic operations on a boolean formula, and polish_parse() is to be used with +parse is meant to be used with functions in the logic module that perform +semantic operations on a boolean formula, and polish_parse is to be used with functions that perform syntactic operations on a boolean formula. AUTHORS: @@ -18,6 +18,9 @@ - Paul Scurek (2013-08-01): added polish_parse, cleaned up python code, updated docstring formatting +- Paul Scurek (2013-08-06): added recover_formula, recover_formula_internal, + prefix_to_infix, to_infix_internal + EXAMPLES: Find the parse tree and variables of a string representation of a boolean formula:: @@ -150,6 +153,231 @@ def polish_parse(s): return vars_order return tree +def recover_formula(prefix_tree): + r""" + Recover the formula from a parse tree in prefix form. + + INPUT: + + - ``prefix_tree`` -- a list. This is a full syntax parse + tree in prefix form. + + OUTPUT: + + The formula as a string + + EXAMPLES: + + This example illustrates the recovery of a formula from a parse tree. + + :: + + sage: import sage.logic.propcalc as propcalc + sage: import sage.logic.logicparser as logicparser + sage: t = ['->', ['&', 'a', ['~', ['~', 'c']]], ['~', ['|', ['~', 'c'], 'd']]] + sage: logicparser.recover_formula(t) + '(a&~~c)->~(~c|d)' + + :: + + sage: f = propcalc.formula("a&(~~c|d)") + sage: logicparser.recover_formula(f.full_tree()) + 'a&(~~c|d)' + + :: + + sage: r = ['~', 'a'] + sage: logicparser.recover_formula(r) + '~a' + + :: + + sage: s = ['d'] + sage: logicparser.recover_formula(s) + 'd' + + .. NOTES:: + + The function :func:`polish_parse` may be passed as an argument, + but :func:`tree_parse` may not unless the parameter ``polish`` + is set equal to True. + + AUTHORS: + + - Paul Scurek (2013-08-06) + """ + formula = '' + if not isinstance(prefix_tree, list): + raise Exception, "recover_formula takes a parse tree as input" + else: + formula = apply_func(prefix_tree, recover_formula_internal) + if prefix_tree[0] == '~' or len(prefix_tree) == 1: + return formula + else: + return formula[1:-1] + +def recover_formula_internal(prefix_tree): + r""" + Recover the formula from a parse tree in prefix form. + + INPUT: + + - ``prefix_tree`` -- a list. This is a simple tree + with at most one operator in prefix form. + + OUTPUT: + + The formula as a string + + EXAMPLES: + + This example illustrates recovering the formula from a parse tree. + + :: + + sage: import sage.logic.logicparser as logicparser + sage: import sage.logic.propcalc as propcalc + sage: t = ['->', 'a', 'b'] + sage: logicparser.recover_formula_internal(t) + '(a->b)' + + :: + + sage: r = ['~', 'c'] + sage: logicparser.recover_formula_internal(r) + '~c' + + :: + + sage: s = ['d'] + sage: logicparser.recover_formula_internal(s) + 'd' + + We can pass :func:`recover_formula_internal` as an argument in :func:`apply_func`. + + :: + + sage: f = propcalc.formula("~(d|c)<->(a&~~~c)") + sage: logicparser.apply_func(f.full_tree(), logicparser.recover_formula_internal) + '(~(d|c)<->(a&~~~c))' + + .. NOTE:: + + This function is for internal use by logicparser.py. The function + recovers the formula of a simple parse tree in prefix form. A + simple parse tree contains at most one operator. + + + The function :func:`polish_parse` may be passed as an argument, + but :func:`tree_parse` may not unless the parameter ``polish`` + is set equal to True. + + AUTHORS: + + - Paul Scurek (2013-08-06) + """ + if len(prefix_tree) == 3: + return '(' + prefix_tree[1] + prefix_tree[0] + prefix_tree[2] + ')' + else: + return ''.join(prefix_tree) + +def prefix_to_infix(prefix_tree): + r""" + Convert a parse tree from prefix form to infix form. + + INPUT: + + - ``prefix_tree`` -- a list. This is a full syntax parse + tree in prefix form. + + OUTPUT: + + A list containing the tree in infix form + + EXAMPLES: + + This example illustrates converting a prefix tree to an infix tree. + + :: + + sage: import sage.logic.logicparser as logicparser + sage: import sage.logic.propcalc as propcalc + sage: t = ['|', ['~', 'a'], ['&', 'b', 'c']] + sage: logicparser.prefix_to_infix(t) + [['~', 'a'], '|', ['b', '&', 'c']] + + :: + + sage: f = propcalc.formula("(a&~b)<->~~~(c|d)") + sage: logicparser.prefix_to_infix(f.full_tree()) + [['a', '&', ['~', 'b']], '<->', ['~', ['~', ['~', ['c', '|', 'd']]]]] + + .. NOTES:: + + The function :func:`polish_parse` may be passed as an argument, + but :func:`tree_parse` may not unless the parameter ``polish`` + is set equal to True. + + AUTHORS: + + - Paul Scurek (2013-08-06) + """ + if not isinstance(prefix_tree, list): + raise Exception, "prefix_to_infix takes a parse tree as input" + return apply_func(prefix_tree, to_infix_internal) + +def to_infix_internal(prefix_tree): + r""" + Convert a simple parse tree from prefix form to infix form. + + INPUT: + + - ``prefix_tree`` -- a list. This is a simple parse tree + in prefix form with at most one operator. + + OUTPUT: + + The tree in infix form as a list. + + EXAMPLES: + + This example illustrates converting a simple tree from prefix to infix form. + + :: + + sage: import sage.logic.logicparser as logicparser + sage: import sage.logic.propcalc as propcalc + sage: t = ['|', 'a', 'b'] + sage: logicparser.to_infix_internal(t) + ['a', '|', 'b'] + + We can pass :func:`to_infix_internal` as an argument in :func:`apply_func`. + + :: + + sage: f = propcalc.formula("(a&~b)<->~~~(c|d)") + sage: logicparser.apply_func(f.full_tree(), logicparser.to_infix_internal) + [['a', '&', ['~', 'b']], '<->', ['~', ['~', ['~', ['c', '|', 'd']]]]] + + .. NOTES:: + + This function is for internal use by logicparser.py. It converts a simple + parse tree from prefix form to infix form. A simple parse tree contains + at most one operator. + + The function :func:`polish_parse` may be passed as an argument, + but :func:`tree_parse` may not unless the parameter ``polish`` + is set equal to True. + + AUTHORS: + + - Paul Scurek (2013-08-06) + """ + if prefix_tree[0] != '~' and len(prefix_tree) == 3: + return [prefix_tree[1], prefix_tree[0], prefix_tree[2]] + else: + return prefix_tree + def tokenize(s): r""" Return the tokens and the distinct variables appearing in a boolean formula s. @@ -398,13 +626,20 @@ def apply_func(tree, func): sage: logicparser.apply_func(t, f) ['|', ['&', 'c', 'a'], ['&', 'b', 'a']] """ - if type(tree[1]) is ListType and type(tree[2]) is ListType: + # used when full syntax parse tree is passed as argument + if len(tree) == 1: + return func(tree) + # used when full syntax parse tree is passed as argument + elif len(tree) == 2: + rval = apply_func(tree[1], func) + return func([tree[0], rval]) + elif isinstance(tree[1], list) and isinstance(tree[2], list): lval = apply_func(tree[1], func) rval = apply_func(tree[2], func) - elif type(tree[1]) is ListType: + elif isinstance(tree[1], list): lval = apply_func(tree[1], func) rval = tree[2] - elif type(tree[2]) is ListType: + elif isinstance(tree[2], list): lval = tree[1] rval = apply_func(tree[2], func) else: From 22ec4763abe587e5be7a75c836e5d63857c62bec Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 19 Dec 2013 22:25:37 -0800 Subject: [PATCH 2/3] Minor review tweaks. --- src/sage/logic/logicparser.py | 74 +++++++++++++++++------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/sage/logic/logicparser.py b/src/sage/logic/logicparser.py index 9cbc7c5ebdd..9e5c15778ad 100644 --- a/src/sage/logic/logicparser.py +++ b/src/sage/logic/logicparser.py @@ -120,7 +120,7 @@ def parse(s): def polish_parse(s): r""" - Return the full syntax parse tree from a boolean formula s. + Return the full syntax parse tree from a boolean formula ``s``. INPUT: @@ -128,11 +128,12 @@ def polish_parse(s): OUTPUT: - The full syntax parse tree as a nested list + The full syntax parse tree as a nested list. EXAMPLES: - This example illustrates how to find the full syntax parse tree of a boolean formula. + This example illustrates how to find the full syntax parse tree + of a boolean formula. :: @@ -159,12 +160,12 @@ def recover_formula(prefix_tree): INPUT: - - ``prefix_tree`` -- a list. This is a full syntax parse - tree in prefix form. + - ``prefix_tree`` -- a list; this is a full syntax parse + tree in prefix form OUTPUT: - The formula as a string + The formula as a string. EXAMPLES: @@ -196,11 +197,11 @@ def recover_formula(prefix_tree): sage: logicparser.recover_formula(s) 'd' - .. NOTES:: + .. NOTE:: The function :func:`polish_parse` may be passed as an argument, but :func:`tree_parse` may not unless the parameter ``polish`` - is set equal to True. + is set to ``True``. AUTHORS: @@ -208,13 +209,12 @@ def recover_formula(prefix_tree): """ formula = '' if not isinstance(prefix_tree, list): - raise Exception, "recover_formula takes a parse tree as input" - else: - formula = apply_func(prefix_tree, recover_formula_internal) - if prefix_tree[0] == '~' or len(prefix_tree) == 1: - return formula - else: - return formula[1:-1] + raise ValueError("the input must be a parse tree as a list") + + formula = apply_func(prefix_tree, recover_formula_internal) + if prefix_tree[0] == '~' or len(prefix_tree) == 1: + return formula + return formula[1:-1] def recover_formula_internal(prefix_tree): r""" @@ -222,12 +222,12 @@ def recover_formula_internal(prefix_tree): INPUT: - - ``prefix_tree`` -- a list. This is a simple tree - with at most one operator in prefix form. + - ``prefix_tree`` -- a list; this is a simple tree + with at most one operator in prefix form OUTPUT: - The formula as a string + The formula as a string. EXAMPLES: @@ -253,7 +253,8 @@ def recover_formula_internal(prefix_tree): sage: logicparser.recover_formula_internal(s) 'd' - We can pass :func:`recover_formula_internal` as an argument in :func:`apply_func`. + We can pass :func:`recover_formula_internal` as an argument + in :func:`apply_func`. :: @@ -263,14 +264,13 @@ def recover_formula_internal(prefix_tree): .. NOTE:: - This function is for internal use by logicparser.py. The function - recovers the formula of a simple parse tree in prefix form. A + This function is for internal use by :mod:`logicparser`. The function + recovers the formula of a simple parse tree in prefix form. A simple parse tree contains at most one operator. - The function :func:`polish_parse` may be passed as an argument, but :func:`tree_parse` may not unless the parameter ``polish`` - is set equal to True. + is set to ``True``. AUTHORS: @@ -287,12 +287,12 @@ def prefix_to_infix(prefix_tree): INPUT: - - ``prefix_tree`` -- a list. This is a full syntax parse - tree in prefix form. + - ``prefix_tree`` -- a list; this is a full syntax parse + tree in prefix form OUTPUT: - A list containing the tree in infix form + A list containing the tree in infix form. EXAMPLES: @@ -312,18 +312,18 @@ def prefix_to_infix(prefix_tree): sage: logicparser.prefix_to_infix(f.full_tree()) [['a', '&', ['~', 'b']], '<->', ['~', ['~', ['~', ['c', '|', 'd']]]]] - .. NOTES:: + .. NOTE:: The function :func:`polish_parse` may be passed as an argument, but :func:`tree_parse` may not unless the parameter ``polish`` - is set equal to True. + is set to ``True``. AUTHORS: - Paul Scurek (2013-08-06) """ if not isinstance(prefix_tree, list): - raise Exception, "prefix_to_infix takes a parse tree as input" + raise TypeError("the input must be a parse tree as a list") return apply_func(prefix_tree, to_infix_internal) def to_infix_internal(prefix_tree): @@ -341,7 +341,8 @@ def to_infix_internal(prefix_tree): EXAMPLES: - This example illustrates converting a simple tree from prefix to infix form. + This example illustrates converting a simple tree from prefix + to infix form. :: @@ -359,15 +360,15 @@ def to_infix_internal(prefix_tree): sage: logicparser.apply_func(f.full_tree(), logicparser.to_infix_internal) [['a', '&', ['~', 'b']], '<->', ['~', ['~', ['~', ['c', '|', 'd']]]]] - .. NOTES:: + .. NOTE:: - This function is for internal use by logicparser.py. It converts a simple - parse tree from prefix form to infix form. A simple parse tree contains - at most one operator. + This function is for internal use by :mod:`logicparser`. It converts + a simple parse tree from prefix form to infix form. A simple parse + tree contains at most one operator. The function :func:`polish_parse` may be passed as an argument, but :func:`tree_parse` may not unless the parameter ``polish`` - is set equal to True. + is set to ``True``. AUTHORS: @@ -375,8 +376,7 @@ def to_infix_internal(prefix_tree): """ if prefix_tree[0] != '~' and len(prefix_tree) == 3: return [prefix_tree[1], prefix_tree[0], prefix_tree[2]] - else: - return prefix_tree + return prefix_tree def tokenize(s): r""" From 521ba42dc81c1ebe1a13e0c9acff72cdcced6727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 11 May 2014 11:58:03 +0200 Subject: [PATCH 3/3] change raise syntax to python3 style --- src/sage/logic/logicparser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/logic/logicparser.py b/src/sage/logic/logicparser.py index 9e5c15778ad..d3a45baa4ab 100644 --- a/src/sage/logic/logicparser.py +++ b/src/sage/logic/logicparser.py @@ -423,7 +423,7 @@ def tokenize(s): # check to see if '-', '<' or '>' are used incorrectly elif s[i] in '<->': msg = "'%s' can only be used as part of the operators '<->' or '->'." % (s[i]) - raise SyntaxError, msg + raise SyntaxError(msg) if len(tok) > 0: toks.append(tok) i += skip @@ -453,7 +453,7 @@ def tokenize(s): msg = 'invalid variable name ' + tok msg += ": identifiers must begin with a letter and contain only " msg += "alphanumerics and underscores" - raise NameError, msg + raise NameError(msg) toks.append(')') return toks, vars_order