aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCamil Staps2015-07-03 23:39:40 +0200
committerCamil Staps2015-07-03 23:41:02 +0200
commitf0ed4df2b0e11ab66966a8395cd7d6d29c7a8efc (patch)
treeecdfbd232e1710f67c233c3e4281560f0344a10c
parentInstallation (diff)
Latex & Html output options
-rw-r--r--Logic.dcl23
-rw-r--r--Logic.icl134
-rw-r--r--LogicParser.icl16
-rw-r--r--README.md3
-rw-r--r--StringUtils.dcl4
-rw-r--r--StringUtils.icl10
-rw-r--r--index.html4
-rw-r--r--request.php2
8 files changed, 134 insertions, 62 deletions
diff --git a/Logic.dcl b/Logic.dcl
index 1a0821b..23ae191 100644
--- a/Logic.dcl
+++ b/Logic.dcl
@@ -23,7 +23,7 @@
*/
definition module Logic
-import StdEnv
+import StdEnv, StdMaybe
// Expressions
:: Expr = B Bool // A constant
@@ -47,6 +47,19 @@ import StdEnv
:: AtomOption :== (AtomName,Bool)
:: TruthTable = {exprs :: [Expr], options :: [[AtomOption]]}
+:: FilledTruthTable = {table :: TruthTable, values :: [[Maybe Bool]]}
+
+:: OutputOption = Plain | Html | LaTeX
+DefaultOutputOption :== Plain
+instance == OutputOption
+
+class show a :: OutputOption a -> String
+instance show Bool
+instance show Char
+instance show Op1
+instance show Op2
+instance show Expr
+instance show FilledTruthTable
isBool :: Expr -> Bool
isAtom :: Expr -> Bool
@@ -60,11 +73,6 @@ isOr :: Expr -> Bool
isImpl :: Expr -> Bool
isEquiv :: Expr -> Bool
-instance toString Op1
-instance toString Op2
-instance toString Expr
-instance toString TruthTable
-
instance == Op1
instance < Op1 // Maybe useful later if more unary operators are added
instance == Op2
@@ -87,6 +95,9 @@ sorted_subexprs :: (Expr -> [Expr]) // Similar, but roughly sorted by co
simple_truthtable :: Expr -> TruthTable // Simple truthtable: only the atomic expression and the expression itself
simple_truthtable_n :: [Expr] -> TruthTable // Simple truthtable with multiple expressions
truthtable :: Expr -> TruthTable // Truthtable from an expression
+truthtable_n :: [Expr] -> TruthTable // Truthtable with multiple expressions
+
+compute :: TruthTable -> FilledTruthTable // Fill in a truthtable
parse :: String -> Expr // Parse a string into an expression
diff --git a/Logic.icl b/Logic.icl
index dabc71d..97d8df5 100644
--- a/Logic.icl
+++ b/Logic.icl
@@ -23,7 +23,7 @@
*/
implementation module Logic
-import StdEnv, StringUtils
+import StdEnv, StdMaybe, StringUtils
isBool :: Expr -> Bool
isBool (B _) = True
@@ -73,50 +73,51 @@ apply2 x Or y = x || y
apply2 x Impl y = y || not x
apply2 x Equiv y = x == y
-instance toString Op1
+instance == OutputOption
where
- toString Not = "~"
+ (==) Plain Plain = True
+ (==) Html Html = True
+ (==) LaTeX LaTeX = True
+ (==) _ _ = False
-instance toString Op2
+instance show Bool
where
- toString And = "&"
- toString Or = "|"
- toString Impl = "->"
- toString Equiv = "<->"
+ show LaTeX True = "\\top"
+ show LaTeX False = "\\bot"
+ show _ b = toString b
-instance toString Expr
+instance show Char
where
- toString (B b) = toString b
- toString (Atom a) = toString a
- toString (App1 op e)
- | needs_parentheses (App1 op e) = toString op +++ "(" +++ toString e +++ ")"
- | otherwise = toString op +++ toString e
- toString (App2 e1 op e2) = e1` +++ " " +++ toString op +++ " " +++ e2`
- where
- e1`
- | needs_parentheses_left (App2 e1 op e2) = "(" +++ toString e1 +++ ")"
- | otherwise = toString e1
- e2`
- | needs_parentheses_right (App2 e1 op e2) = "(" +++ toString e2 +++ ")"
- | otherwise = toString e2
-
-instance toString TruthTable
+ show LaTeX c = " " +++ toString c
+ show _ c = toString c
+
+instance show Op1
where
- toString t=:{exprs,options}
- = row_b +++ join row_s [pad_right ' ' head len \\ head <- map toString exprs & len <- padlens] +++ row_e +++
- line_b +++ join line_s [toString (repeatn len '-') \\ len <- padlens] +++ line_e +++
- foldr (+++) "" [row_b +++ join row_s [pad_right ' ' (toStringOrEmpty val) len \\ val <- map (eval o substitute_all options`) exprs & len <- padlens] +++ row_e \\ options` <- options]
- where
- row_b = " " // Row / Line begin, end, separator
- row_e = " \n"
- row_s = " | "
- line_b = "-"
- line_e = "-\n"
- line_s = "-+-"
- padlens = map ((max 5) o strlen o toString) exprs // 5 is the length of False
- toStringOrEmpty :: [Bool] -> String
- toStringOrEmpty [] = ""
- toStringOrEmpty [b:bs] = toString b
+ show Plain Not = "~"
+ show Html Not = "&not;"
+ show LaTeX Not = "\\neg"
+
+instance show Op2
+where
+ show Plain And = "&"
+ show Plain Or = "|"
+ show Plain Impl = "->"
+ show Plain Equiv = "<->"
+ show Html And = "&and;"
+ show Html Or = "&or;"
+ show Html Impl = "&rarr;"
+ show Html Equiv = "&harr;"
+ show LaTeX And = "\\land"
+ show LaTeX Or = "\\lor"
+ show LaTeX Impl = "\\rightarrow"
+ show LaTeX Equiv = "\\leftrightarrow"
+
+instance show Expr
+where
+ show opt (B b) = show opt b
+ show opt (Atom a) = show opt a
+ show opt (App1 op e) = show opt op +++ show opt e
+ show opt (App2 e1 op e2) = show opt e1 +++ " " +++ show opt op +++ " " +++ show opt e2
instance == Op1
where
@@ -175,7 +176,7 @@ where
comp e1 e2
| isMember e1 (subexprs e2) = True
| isMember e2 (subexprs e1) = False
- | otherwise = strlen (toString e1) < strlen (toString e2)
+ | otherwise = strlen (show Plain e1) < strlen (show Plain e2)
// Does a the argument of a unary operator need parentheses?
needs_parentheses :: Expr -> Bool
@@ -256,6 +257,55 @@ simple_truthtable_n es = {exprs = removeDup ([Atom a \\ a <- flatten (map all_at
truthtable :: Expr -> TruthTable
truthtable e = {exprs = sorted_subexprs e ++ [e], options = all_atom_options e}
+truthtable_n :: [Expr] -> TruthTable
+truthtable_n es = {exprs = sort (removeDup (flatten ([[e:subexprs e] \\ e <- es]))), options = removeDup (flatten (map all_atom_options es))}
+
+compute :: TruthTable -> FilledTruthTable // Fill in a truthtable
+compute table=:{exprs,options} = {table=table, values=values}
+where
+ values = [[toMaybeBool val \\ val <- map (eval o substitute_all options`) exprs] \\ options` <- options]
+ toMaybeBool [] = Nothing
+ toMaybeBool [b:bs] = Just b
+
+instance show FilledTruthTable
+where
+ show :: OutputOption FilledTruthTable -> String
+ show opt t=:{table=table=:{exprs,options},values}
+ = begin +++
+ head_b +++
+ join head_s [pad_right (showOrNot head_i) header len \\ header <- map (show opt) exprs & len <- padlens] +++
+ head_e +++
+ line_b +++
+ join line_s [foldr (+++) "" (repeatn len (showOrNot line_i)) \\ len <- padlens] +++
+ line_e +++
+ foldr (+++) "" [row_b +++ join row_s [pad_right (showOrNot row_i) (showOrNot v) len \\ v <- r & len <- padlens] +++ row_e \\ r <- values] +++
+ end
+ where
+ padlens = map ((\l . maxList (map strlen [l,show opt True,show opt False])) o (show opt)) exprs
+ // Ideally, we would some kind of DOM writer for Html, but for this project this is sufficient (although not very readable)
+ (begin,end) = gen
+ gen
+ | opt == Plain = ("","")
+ | opt == Html = ("<table>", "</tbody></table>")
+ | opt == LaTeX = ("\\begin{tabular}{" +++ join "|" (repeatn (length exprs) "c") +++ "}", "\\end{tabular}")
+ (head_b,head_e,head_s,head_i) = head
+ head
+ | opt == Html = ("<thead><tr><th>", "</th></tr></thead><tbody>", "</th><th>", Nothing)
+ | otherwise = row
+ (row_b,row_e,row_s,row_i) = row
+ row
+ | opt == Plain = (" ", " \n", " | ", Just ' ')
+ | opt == Html = ("<tr><td>", "</td></tr>", "</td><td>", Nothing)
+ | opt == LaTeX = ("$", "$\\\\", "$&$", Nothing)
+ (line_b,line_e,line_s,line_i) = line
+ line
+ | opt == Plain = ("-", "-\n", "-+-", Just '-')
+ | opt == Html = ("", "", "", Nothing)
+ | opt == LaTeX = ("\\hline", "", "", Nothing)
+ showOrNot :: (Maybe a) -> String | show a
+ showOrNot Nothing = ""
+ showOrNot (Just a) = show opt a
+
NOT :== '~'
AND :== '&'
OR :== '|'
@@ -313,7 +363,7 @@ where
parse_stack` :: [Char] [Expr] -> Expr
parse_stack` [] [e] = e
parse_stack` [] [] = abort "Cannot parse: not enough expressoins on the stack"
- parse_stack` [] es = abort ("Cannot parse: too many expressions on the stack:\n" +++ join "\n" (map toString es) +++ "\n")
+ parse_stack` [] es = abort ("Cannot parse: too many expressions on the stack:\n" +++ join "\n" (map (show Plain) es) +++ "\n")
parse_stack` [AND:st] [e1:[e2:es]] = parse_stack` st [App2 e2 And e1:es]
parse_stack` [OR:st] [e1:[e2:es]] = parse_stack` st [App2 e2 Or e1:es]
parse_stack` [IMPL:st] [e1:[e2:es]] = parse_stack` st [App2 e2 Impl e1:es]
@@ -322,7 +372,7 @@ where
parse_stack` [c:st] es
| cIsAtom [c] = parse_stack` st [Atom (cToAtom [c]) : es]
| cIsBool [c] = parse_stack` st [B (cToBool [c]) : es]
- parse_stack` [c:st] es = abort ("Cannot parse: tried to perform an operation (" +++ toString c +++ ") with too few expressions on the stack:\n" +++ join "," (map toString es) +++ "\n")
+ parse_stack` [c:st] es = abort ("Cannot parse: tried to perform an operation (" +++ show Plain c +++ ") with too few expressions on the stack:\n" +++ join "," (map (show Plain) es) +++ "\n")
cIsOp :: [Char] -> Bool
cIsOp ['~'] = True
diff --git a/LogicParser.icl b/LogicParser.icl
index 320e2cc..fbf19ef 100644
--- a/LogicParser.icl
+++ b/LogicParser.icl
@@ -26,12 +26,18 @@ module LogicParser
import StdEnv, StdMaybe, ArgEnv, Logic
Start
-| argc < 1 = abort ("Usage: " +++ argv.[0] +++ " -b -nt <string>\n")
-| extended = toString (truthtable (parse argv.[2]))
-| otherwise = toString (simple_truthtable_n [parse argv.[n] \\ n <- [1..argc]])
-//| otherwise = toString ((if extended truthtable simple_truthtable) (parse argv.[1]))
+| isEmpty exprs = abort ("Usage: " +++ argv.[0] +++ " -b -nt [-e] [-html|-latex] <string>\n")
+| otherwise = show outputoption (compute (if extended truthtable_n simple_truthtable_n (map parse exprs)))
where
argc = size argv - 1
argv = getCommandLine
- extended = argv.[1] == "-e"
+
+ exprs = filter (\s . s.[0] <> '-') [argv.[n] \\ n <- [1..argc]]
+
+ extended = hasArg "-e"
+ outputoption
+ | hasArg "-html" = Html
+ | hasArg "-latex" = LaTeX
+ | otherwise = Plain
+ hasArg arg = or [arg == argv.[n] \\ n <- [0..argc]]
diff --git a/README.md b/README.md
index d52cb15..185406c 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ Logic toolbox in [Clean](http://wiki.clean.cs.ru.nl/Clean). Features include:
* Displaying truth tables
* Parsing strings to expressions
* A web frontend to access the Clean program through, so only server-side installation is necessary
+ * Different output options (Plain / ASCII art, HTML, LaTeX)
Read further for examples.
@@ -148,6 +149,8 @@ The option `-e` tells the parser to show the extended truth table. With this opt
True | False | True | False
True | True | True | True
+The parsers also recognises `-html` and `-latex` and will output an HTML or LaTeX table if these arguments are present.
+
## Web frontend
There is a simple web frontend in PHP and a basic HTML template which allows one to connect to the Clean application through his browser. The files for this are `index.html` and `request.php`, and a demo may be found on https://demo.camilstaps.nl/CleanLogic. For this to work, the `exec()` function should be enabled in your PHP configuration.
diff --git a/StringUtils.dcl b/StringUtils.dcl
index 5593c4c..22e80ad 100644
--- a/StringUtils.dcl
+++ b/StringUtils.dcl
@@ -27,8 +27,8 @@ import StdEnv
strlen :: String -> Int // Length of a String
-pad_right :: Char String Int -> String // Pad a String with Chars up to a length
-pad_left :: Char String Int -> String // Similar, but pad on the left
+pad_right :: String String Int -> String // Pad a String (@2) with another String (@1) up to a length
+pad_left :: String String Int -> String // Similar, but pad on the left
join :: String [String] -> String // Join a [String] with a String glue
diff --git a/StringUtils.icl b/StringUtils.icl
index 811b3d2..91e3d4f 100644
--- a/StringUtils.icl
+++ b/StringUtils.icl
@@ -31,15 +31,17 @@ where
s` :: [Char]
s` = fromString s
-pad_right :: Char String Int -> String
+pad_right :: String String Int -> String
pad_right c s l
| strlen s >= l = s
-| otherwise = s +++ toString (repeatn (l - strlen s) c)
+| strlen c == 0 = s
+| otherwise = foldl (+++) s (repeatn ((l - strlen s) / strlen c) c)
-pad_left :: Char String Int -> String
+pad_left :: String String Int -> String
pad_left c s l
| strlen s >= l = s
-| otherwise = toString (repeatn (l - strlen s) c) +++ s
+| strlen c == 0 = s
+| otherwise = foldr (+++) s (repeatn ((l - strlen s) / strlen c) c)
join :: String [String] -> String
join glue [] = ""
diff --git a/index.html b/index.html
index 48ad677..9a9c301 100644
--- a/index.html
+++ b/index.html
@@ -77,7 +77,7 @@
<div class="col-md-9">
<h2>Truth table</h2>
<p>Truth tables are generated with a server-side <a href="http://clean.cs.ru.nl/Clean" target="_blank">Clean</a> program.</p>
- <textarea class="form-control" id="truthtable"></textarea>
+ <div id="truthtable" class="table-responsive"></div>
</div>
</div>
</div>
@@ -94,7 +94,7 @@
expressions: $('#expressions').val().split("\n")
},
success: function (data) {
- $('#truthtable').val(data);
+ $('#truthtable').html(data).find('table').addClass('table table-striped table-condensed table-bordered table-hover');
}
});
}).trigger('click');
diff --git a/request.php b/request.php
index 594ae4f..2866ada 100644
--- a/request.php
+++ b/request.php
@@ -43,7 +43,7 @@ $expressions = array_map('escapeshellarg', $expressions);
$expressions = implode(' ', $expressions);
$extended = $extended ? '-e' : '';
-$call = './LogicParser -b -nt ' . $extended . ' ' . $expressions;
+$call = './LogicParser -b -nt -html ' . $extended . ' ' . $expressions;
$out = [];
exec($call, $out);