Fix incorrect parenthesis
This commit is contained in:
parent
edd4f53a68
commit
2bdf936160
@ -39,6 +39,7 @@
|
|||||||
#:*operator-unicode-lookup-alist*
|
#:*operator-unicode-lookup-alist*
|
||||||
#:*operator-latex-lookup-alist*
|
#:*operator-latex-lookup-alist*
|
||||||
#:latex-var-name-transform
|
#:latex-var-name-transform
|
||||||
|
#:flatten-proposition
|
||||||
#:typeset-proposition
|
#:typeset-proposition
|
||||||
#:convert-truth-table-to-latex
|
#:convert-truth-table-to-latex
|
||||||
#:convert-truth-table-to-html
|
#:convert-truth-table-to-html
|
||||||
|
15
eval.lisp
15
eval.lisp
@ -29,6 +29,21 @@
|
|||||||
(:documentation "Condition representing an error that occurred during
|
(:documentation "Condition representing an error that occurred during
|
||||||
evaluation for a proposition."))
|
evaluation for a proposition."))
|
||||||
|
|
||||||
|
(defun operator-argument-count (oper)
|
||||||
|
"Return the minimum number of arguments that OPER takes as the first value,
|
||||||
|
and the maximum number (or nil for infinity) as a second value."
|
||||||
|
(case oper
|
||||||
|
(and (values 1 nil))
|
||||||
|
(or (values 1 nil))
|
||||||
|
(xor (values 1 nil))
|
||||||
|
(not (values 1 1))
|
||||||
|
(implies (values 2 2))
|
||||||
|
(converse (values 2 2))
|
||||||
|
(iff (values 2 2))
|
||||||
|
(nand (values 1 nil))
|
||||||
|
(nor (values 1 nil))
|
||||||
|
(t (error "unknown operator: ~S" oper))))
|
||||||
|
|
||||||
(defun logical-xor (&rest args)
|
(defun logical-xor (&rest args)
|
||||||
"Logical xor (not equal) each argument in turn with its following argument.
|
"Logical xor (not equal) each argument in turn with its following argument.
|
||||||
NOTE: This is NOT a macro, there is no short circuit evaluation (all arguments
|
NOTE: This is NOT a macro, there is no short circuit evaluation (all arguments
|
||||||
|
21
parse.lisp
21
parse.lisp
@ -108,26 +108,9 @@ proposition."))
|
|||||||
(open-paren most-positive-fixnum)
|
(open-paren most-positive-fixnum)
|
||||||
(t nil)))
|
(t nil)))
|
||||||
|
|
||||||
(defun operator-argument-count (oper)
|
|
||||||
"Return the minimum number of arguments that OPER takes as the first value,
|
|
||||||
and the maximum number (or nil for infinity) as a second value."
|
|
||||||
(case oper
|
|
||||||
(and (values 2 nil))
|
|
||||||
(or (values 2 nil))
|
|
||||||
(xor (values 2 nil))
|
|
||||||
(not (values 1 1))
|
|
||||||
(implies (values 2 2))
|
|
||||||
(converse (values 2 2))
|
|
||||||
(iff (values 2 2))
|
|
||||||
(nand (values 2 nil))
|
|
||||||
(nor (values 2 2))
|
|
||||||
(open-paren (values 0 0))
|
|
||||||
(t (error "unknown operator: ~S" oper))))
|
|
||||||
|
|
||||||
(defun unary-p (oper)
|
(defun unary-p (oper)
|
||||||
"Return whether OPER is a unary operator or not."
|
"Return whether OPER is a unary operator or not."
|
||||||
(when oper
|
(eq oper 'not))
|
||||||
(= 1 (operator-argument-count oper))))
|
|
||||||
|
|
||||||
(defun interpret-operand (oper-str)
|
(defun interpret-operand (oper-str)
|
||||||
"Return a symbol representing OPER-STR, or the string itself if it represents
|
"Return a symbol representing OPER-STR, or the string itself if it represents
|
||||||
@ -267,7 +250,7 @@ found variables."
|
|||||||
(error 'proposition-parse-error :message "no more operators"
|
(error 'proposition-parse-error :message "no more operators"
|
||||||
:position pos
|
:position pos
|
||||||
:proposition prop-str))
|
:proposition prop-str))
|
||||||
(let ((oper-args (operator-argument-count oper))
|
(let ((oper-args (if (unary-p oper) 1 2))
|
||||||
(cur-operands (list (pop operands))))
|
(cur-operands (list (pop operands))))
|
||||||
(when (not (car cur-operands))
|
(when (not (car cur-operands))
|
||||||
(error 'proposition-parse-error
|
(error 'proposition-parse-error
|
||||||
|
49
typeset.lisp
49
typeset.lisp
@ -117,11 +117,41 @@
|
|||||||
else
|
else
|
||||||
collect char)))
|
collect char)))
|
||||||
|
|
||||||
|
(defun flattenable-p (oper)
|
||||||
|
"Return t if OPER is able to be flattened. That is, it does not care a bout
|
||||||
|
argument ordering."
|
||||||
|
(multiple-value-bind (min max)
|
||||||
|
(operator-argument-count oper)
|
||||||
|
(declare (ignorable min))
|
||||||
|
;; currently, all unordered operators take any number of arguments max, and
|
||||||
|
;; all ordered operators have some max number of arguments (as a
|
||||||
|
;; proposition: an operator is unordered if and only if it takes any number
|
||||||
|
;; of arguments)
|
||||||
|
(not max)))
|
||||||
|
|
||||||
|
(defun flatten-proposition (prop)
|
||||||
|
"Flatten PROP, such that adjacent operators with the same precedence and with
|
||||||
|
no ordering (such as \"and\" or \"or\") are not surrounded by parenthesis when
|
||||||
|
typeset."
|
||||||
|
(if (consp prop)
|
||||||
|
(loop with my-oper = (car prop)
|
||||||
|
for raw-sub-expr in (cdr prop)
|
||||||
|
for sub-expr = (flatten-proposition raw-sub-expr)
|
||||||
|
when (and (flattenable-p my-oper)
|
||||||
|
(consp sub-expr)
|
||||||
|
(eq (car sub-expr) my-oper))
|
||||||
|
append (cdr sub-expr) into out-args
|
||||||
|
else
|
||||||
|
collect sub-expr into out-args
|
||||||
|
finally (return (cons my-oper out-args)))
|
||||||
|
prop))
|
||||||
|
|
||||||
(defun typeset-proposition (expr &key
|
(defun typeset-proposition (expr &key
|
||||||
(lookup-table *operator-ascii-lookup-alist*)
|
(lookup-table *operator-ascii-lookup-alist*)
|
||||||
var-name-transform
|
var-name-transform
|
||||||
(parent-prec most-positive-fixnum)
|
(parent-prec most-positive-fixnum)
|
||||||
latin-truths)
|
latin-truths
|
||||||
|
(flatten-prop t))
|
||||||
"Typeset the propositional expression EXPR to plain text. LOOKUP-TABLE should
|
"Typeset the propositional expression EXPR to plain text. LOOKUP-TABLE should
|
||||||
be a table mapping operators to their textual representation. VAR-NAME-TRANSFORM
|
be a table mapping operators to their textual representation. VAR-NAME-TRANSFORM
|
||||||
(if non-nil) should take a single string argument which is a variable name and
|
(if non-nil) should take a single string argument which is a variable name and
|
||||||
@ -147,10 +177,13 @@ use (it controls when parentheses are applied.)"
|
|||||||
(cdr (assoc 'false lookup-table))))
|
(cdr (assoc 'false lookup-table))))
|
||||||
;; expr is a compound expression
|
;; expr is a compound expression
|
||||||
(t
|
(t
|
||||||
(destructuring-bind (oper first-arg &rest args) expr
|
(destructuring-bind (oper first-arg &rest args)
|
||||||
|
(if flatten-prop
|
||||||
|
(flatten-proposition expr)
|
||||||
|
expr)
|
||||||
(let* ((our-prec (operator-precedence oper))
|
(let* ((our-prec (operator-precedence oper))
|
||||||
(oper-ascii (cdr (assoc oper lookup-table)))
|
(oper-ascii (cdr (assoc oper lookup-table)))
|
||||||
(prefix-suffix (if (< parent-prec our-prec)
|
(prefix-suffix (if (<= parent-prec our-prec)
|
||||||
(cons (cdr (assoc 'open-paren lookup-table))
|
(cons (cdr (assoc 'open-paren lookup-table))
|
||||||
(cdr (assoc 'close-paren lookup-table)))
|
(cdr (assoc 'close-paren lookup-table)))
|
||||||
'("" . ""))))
|
'("" . ""))))
|
||||||
@ -161,7 +194,8 @@ use (it controls when parentheses are applied.)"
|
|||||||
:lookup-table lookup-table
|
:lookup-table lookup-table
|
||||||
:var-name-transform var-name-transform
|
:var-name-transform var-name-transform
|
||||||
:latin-truths latin-truths
|
:latin-truths latin-truths
|
||||||
:parent-prec our-prec)
|
:parent-prec our-prec
|
||||||
|
:flatten-prop nil)
|
||||||
(cdr prefix-suffix))
|
(cdr prefix-suffix))
|
||||||
;; we have many arguments
|
;; we have many arguments
|
||||||
(loop for arg in args
|
(loop for arg in args
|
||||||
@ -171,19 +205,20 @@ use (it controls when parentheses are applied.)"
|
|||||||
:lookup-table lookup-table
|
:lookup-table lookup-table
|
||||||
:var-name-transform var-name-transform
|
:var-name-transform var-name-transform
|
||||||
:latin-truths latin-truths
|
:latin-truths latin-truths
|
||||||
:parent-prec our-prec)
|
:parent-prec our-prec
|
||||||
|
:flatten-prop nil)
|
||||||
into output
|
into output
|
||||||
finally
|
finally
|
||||||
(push (typeset-proposition first-arg
|
(push (typeset-proposition first-arg
|
||||||
:lookup-table lookup-table
|
:lookup-table lookup-table
|
||||||
:var-name-transform var-name-transform
|
:var-name-transform var-name-transform
|
||||||
:latin-truths latin-truths
|
:latin-truths latin-truths
|
||||||
:parent-prec our-prec)
|
:parent-prec our-prec
|
||||||
|
:flatten-prop nil)
|
||||||
output)
|
output)
|
||||||
(return (format nil "~A~{~A~^ ~}~A" (car prefix-suffix)
|
(return (format nil "~A~{~A~^ ~}~A" (car prefix-suffix)
|
||||||
output (cdr prefix-suffix))))))))))
|
output (cdr prefix-suffix))))))))))
|
||||||
|
|
||||||
|
|
||||||
(defun convert-truth-table-to-latex (table &key pretty-print latin-truths)
|
(defun convert-truth-table-to-latex (table &key pretty-print latin-truths)
|
||||||
"Convert TABLE, which should be a truth table as returned by
|
"Convert TABLE, which should be a truth table as returned by
|
||||||
`create-truth-table' to latex. If PRETTY-PRINT, add newlines to make the
|
`create-truth-table' to latex. If PRETTY-PRINT, add newlines to make the
|
||||||
|
Loading…
Reference in New Issue
Block a user