Extension:WikiLogic/Syntax

From MediaWiki.org
Jump to navigation Jump to search
<?php
// WikiLogic v0.93a
// Extension for MediaWiki v1.6
// Written by en:w:User:Alfakim
// Released under GFDL
// 25 . 09 . 2006

// This extension is designed to make it easy to write logical strings with just a normal keyboard and no 'code'. It parses vernacular or abbreviated input into HTML character codes. It has an internal option to replace all or some of these codes with the insertion of predefined images. It can also convert into a LaTeX string, for copy-and-pasting between <math> tags, or a string of template-code and text, for copy-and-pasting into an edit box. Future upgrades to this extension could remove this copy-and-paste stage.

// Propositional, Quanitifier, Modal and Set Theory supported.
// Options are set below

// To activate the extension, include it from your LocalSettings.php
// with: require_once("extensions/WikiLogic.php");

// Define Hook
$wgExtensionFunctions[] = "wfLogicExtension";
function wfLogicExtension() {
    global $wgParser;
    $wgParser->setHook( "logic", "renderLogic" );
}

// Main Function
function renderLogic( $input, $argv ) {

$usetemplates = FALSE;
$uselatex = FALSE;

// Arguments
if ((strtolower($argv['output']) == "template") || (strtolower($argv['output']) == "templates"))
$usetemplates = TRUE;
if (strtolower($argv['output']) == "latex")
$uselatex = TRUE;

// Customise non-standard message format
$premsg = "<div style=\"margin: 1em; display: block; font-weight: bold; color: red; font-style: italic\">";
$promsg = "</div>";

// Remove trailing whitespace
$input = trim($input);

// Fail-safes
$errorstring = "*";
if (strlen($input) > 1024)
return ($premsg . "Error: Logic string exceeds 1024 characters." . $promsg);
if (($input == NULL) || (strlen($input) == 0))
return ($premsg . "Error: No input. Place input between the &lt;logic&gt; and &lt;/logic&gt; tags." . $promsg);
if (strpbrk($input, "*") != FALSE)
return ($premsg . "Error: Input may not contain: " . implode(", ", str_split($errorstring)) . "." . $promsg);

// Define character codes for each operator
$charset = "ISO-8859-1";
$logic = array(
"therefore" => "there4",
"syntacticturnstile" => "#x22A2",
"semanticturnstile" => "#x22A8",
"notequal" => "ne",
"and" => "and",
"or" => "or",
"cond" => "rarr",
"bicond" => "harr",
"all" => "forall",
"exist" => "exist",
"union" => "cup",
"intersect" => "cap",
"element" => "isin", "notelement" => "notin",
"subset" => "sube", "notsubset" => "#8840",
"psubset" => "sub", "notpsubset" => "nsub",
"empty" => "empty",
"box" => "#9647",
"diamond" => "loz",
"identical" => "equiv"
);

// Set this to true to substitute the actual characters for the codes in the final output
$decode = FALSE;

// Define LaTeX strings for each operator
if ($uselatex == TRUE)
{
$latex = array(
"therefore" => "",
"syntacticturnstile" => "",
"semanticturnstile" => "",
"notequal" => "",
"and" => "",
"or" => "",
"cond" => "",
"bicond" => "",
"all" => "",
"exist" => "",
"union" => "",
"intersect" => "",
"element" => "", "notelement" => "",
"subset" => "", "notsubset" => "",
"psubset" => "", "notpsubset" => "",
"empty" => "",
"box" => "",
"diamond" => "",
"identical" => ""
);
}

// Define templates for each operator
// NULL names will be replaced by the name of the array key
// Template names will be prefixed with $pretemplate (below)
if ($usetemplates == TRUE)
{
$pretemplate = "."
$template = array(
"therefore" => NULL,
"syntacticturnstile" => NULL,
"semanticturnstile" => NULL,
"notequal" => NULL,
"and" => NULL,
"or" => NULL,
"cond" => NULL,
"bicond" => NULL,
"all" => NULL,
"exist" => NULL,
"union" => NULL,
"intersect" => NULL,
"element" => NULL, "notelement" => NULL,
"subset" => NULL, "notsubset" => NULL,
"psubset" => NULL, "notpsubset" => NULL,
"empty" => NULL,
"box" => NULL,
"diamond" => NULL,
"identical" => NULL
);
}

// Define image names for each operator
// /////////////////// //
$customimages = FALSE;
// /////////////////// //
// NULL names will be replaced by the name of the array key
// Names without extensions will be appended with $imgext (below)
// Images are used instead of character codes only if $customimages is TRUE (below)
// Images must exist on your server at $imgpath
if ($customimages == TRUE)
{
$imgpath = "./logic/"
$imgext = ".png";
$image = array(
"therefore" => NULL,
"syntacticturnstile" => NULL,
"semanticturnstile" => NULL,
"notequal" => NULL,
"and" => NULL,
"or" => NULL,
"cond" => NULL,
"bicond" => NULL,
"all" => NULL,
"exist" => NULL,
"union" => NULL,
"intersect" => NULL,
"element" => NULL, "notelement" => NULL,
"subset" => NULL, "notsubset" => NULL,
"psubset" => NULL, "notpsubset" => NULL,
"empty" => NULL,
"box" => NULL,
"diamond" => NULL,
"identical" => NULL
);
}

// Give character codes HTML-readable prefix and suffix
foreach ($logic as $key => $charcode)
{
$logic[$key] = "&" . $charcode . ";";
}

// Custom images
// You must individually turn on the use of images for each operator, below.
if ($customimages == TRUE)
{
$customimage = array(
"therefore" => FALSE,
"syntacticturnstile" => FALSE,
"semanticturnstile" => FALSE,
"notequal" => FALSE,
"and" => FALSE,
"or" => FALSE,
"cond" => FALSE,
"bicond" => FALSE,
"all" => FALSE,
"exist" => FALSE,
"union" => FALSE,
"intersect" => FALSE,
"element" => FALSE, "notelement" => FALSE,
"subset" => FALSE, "notsubset" => FALSE,
"psubset" => FALSE, "notpsubset" => FALSE,
"empty" => FALSE,
"box" => FALSE,
"diamond" => FALSE,
"identical" => FALSE
};
}

// Parse images
if ($customimages == TRUE)
{
foreach ($image as $key => $value)
{
if ($value == NULL)
$image[$key] = $key;
}
foreach ($image as $key => $value)
{
if (strpos($value, ".") == FALSE)
$image[$key] = $value . $imgext;
}
// Set image widths to parameter, else default
if (($argv['width'] == NULL) || (strlen($argv['width']) == 0))
$width = "1em";
else
$width = $argv['width'];
$preimg = "<img src=\"" . $imgpath;
$proimg = "\" alt=\"\" style=\"width: " . $width . "\" />";
foreach ($image as $key => $path)
{
$image[$key] = $preimg . $path . $proimg;
}
}

// Parse templates
if ($usetemplates == TRUE)
{
foreach ($template as $key => $value)
{
if ($value == NULL)
$template[$key] = $key;
}
foreach ($template as $key => $value)
{
$template[$key] = "{{" . $pretemplate . $value . "}}";
}
}

// Use images if variable
if ($customimages == TRUE)
{
foreach ($image as $key => $value)
{
if (customimage[$key] == TRUE)
$logic[$key] = $value;
}
}

// Use LaTeX if parameter
if ($uselatex == TRUE)
{
foreach ($latex as $key => $value)
{
$logic[$key] = $value;
}
}

// Use Templates if parameter
if ($usetemplates == TRUE)
{
foreach ($template as $key => $value)
{
$logic[$key] = $value;
}
// Avoid interference with template code
$input = str_replace("{", "&lang;", $input);
$input = str_replace("}", "&rang;", $input);
}

// Parse input
$input = explode(" ", $input);

// Exchanges
// Any characters put through the escaping procedure below must have asterisks around them
$replacement = array(
"therefore" => "1",
"thus" => "1",
"so" => "1",
"turnstile1" => "2",
"syntacticturnstile" => "2",
"proof" => "2",
"semanticturnstile" => "3",
"turnstile2" => "3",
"turnstile" => "3",
"valid" => "3",
"notequal" => "4",
"*¬*=" => "4",
"unequal" => "4",
"~=" => "4",
"!=" => "4",
"different" => "4",
"and" => "5",
"&" => "5",
"+" => "5",
"^" => "5",
"or" => "6",
"v" => "6",
"conditional" => "7",
"implies" => "7",
"imply" => "7",
"then" => "7",
"if" => "",
"cond" => "7",
"material" => "7",
"--*>*" => "7",
"-*>*" => "7",
"==*>*" => "7",
"=*>*" => "7",
"bicond" => "8",
"biconditional" => "8",
"equivalent" => "8",
"iff" => "8",
"===" => "8",
"*<*=*>*" => "8",
"*<*-*>*" => "8",
"*<**>*" => "8",
"universal" => "9",
"univ" => "9",
"uni" => "9",
"un" => "9",
"A" => "9",
"qu" => "9",
"existential" => "10",
"exists" => "10",
"exist" => "10",
"exi" => "10",
"ex" => "10",
"E" => "10",
"qe" => "10",
"|_|" => "11",
"union" => "11",
"U" => "11",
"|^|" => "12",
"intersect" => "12",
"N" => "12",
"element" => "13",
"elem" => "13",
"€" => "13",
"member" => "13",
"part" => "13",
"in" => "13",
"*¬*element" => "14",
"*¬*elem" => "14",
"*¬*€" => "14",
"*¬*member" => "14",
"*¬*part" => "14",
"*¬*in" => "14",
"notelement" => "14",
"notelem" => "14",
"!€" => "14",
"notmember" => "14",
"notpart" => "14",
"notin" => "14",
"subset" => "15",
"contained" => "15",
"sub" => "15",
"*<*_" => "15",
"*¬*subset" => "16",
"*¬*contained" => "16",
"*¬*sub" => "16",
"*¬**<*_" => "16",
"notsubset" => "16",
"notcontained" => "16",
"notsub" => "16",
"!*<*_" => "16",
"propersubset" => "17",
"psubset" => "17",
"psub" => "17",
"*<*" => "17",
"*¬*propersubset" => "18",
"*¬*psubset" => "18",
"*¬*psub" => "18",
"*¬**<*" => "18",
"notpropersubset" => "18",
"notpsubset" => "18",
"notpsub" => "18",
"!*<*" => "18",
"0" => "19",
"zero" => "19",
"emptyset" => "19",
"empty" => "19",
"necessity" => "20",
"necessarily" => "20",
"always" => "20",
"box" => "20",
"square" => "20",
"*[**]*" => "20",
"L" => "20",
"possibly" => "21",
"possibility" => "21",
"sometimes" => "21",
"maybe" => "21",
"diamond" => "21",
"kite" => "21",
"lozenge" => "21",
"M" => "21",
"identical" => "22",
"exactly" => "22",
"same" => "22",
"identity" => "22",
"is" => "22"
);

// Fail-safes
// Escape variables, brackets, commas and ¬'s
foreach ($input as $term)
{
$spaced = "";
$input[key($input)] = $input[key($input)] . " ";
while ((strpbrk($input[key($input)], "¬(){}[]<>,abcdefghijklmnopqrstuvwxyz") != FALSE) && (strlen($input[key($input)]) > 1))
{
$pos = strlen($input[key($input)]) - strlen(strpbrk($input[key($input)], "¬(){}[]<>,abcdefghijklmnopqrstuvwxyz"));
$spaced = $spaced . substr($input[key($input)], 0, $pos);
// Do not escape non-variables
// Fail-safes for characters included in above exchanges
if (strpbrk(substr($input[key($input)], $pos, 1), "¬(){}[]<>") != FALSE)
$spaced = $spaced . "*" . substr($input[key($input)], $pos, 1) . "*";
else
$spaced = $spaced . " \\" . substr($input[key($input)], $pos, 1) . " ";
$input[key($input)] = substr($input[key($input)], ($pos + 1), ((strlen($input[key($input)]) - $pos)) - 1);
}
if ($spaced != "")
$input[key($input)] = $spaced . $input[key($input)];
}
// Collapse excessive whitespace to prime replacement
$input = implode(" ", $input);
$input = explode(" ", $input);
$input = " " . implode(" ", $input) . " ";

// Make replacement
$search = array_keys($replacement);
foreach ($search as $key => $value)
{
$search[$key] = " " . $value . " ";
}
$replace = array_values($replacement);
foreach ($replace as $key => $value)
{
$sreplace[$key] = " " . $value . " ";
}
$input = str_ireplace($search, $replace, $input);
$input = str_replace("*", " ", $input);
$input = explode(" ", $input);
$input = " " . implode(" ", $input) . " ";
$input = str_ireplace($search, $replace, $input);

// Add whitespace to avoid errors
$input = explode(" ", $input);
foreach ($logic as $key => $value)
{
$logic[$key] = " " . $value . " ";
}

$replacement = array(
"1" => $logic['therefore'],
"2" => $logic['syntacticturnstile'],
"3" => $logic['semanticturnstile'],
"4" => $logic['notequal'],
"5" => $logic['and'],
"6" => $logic['or'],
"7" => $logic['cond'],
"8" => $logic['bicond'],
"9" => $logic['all'],
"10" => $logic['exist'],
"11" => $logic['union'],
"12" => $logic['intersect'],
"13" => $logic['element'],
"14" => $logic['notelement'],
"15" => $logic['subset'],
"16" => $logic['notsubet'],
"17" => $logic['psubset'],
"18" => $logic['notpsubset'],
"19" => $logic['empty'],
"20" => $logic['box'],
"21" => $logic['diamond'],
"22" => $logic['identical']
);

// Conclude replacement
$search = array_keys($replacement);
$replace = array_values($replacement);
$input = str_replace($search, $replace, $input);

// Trim excessive whitespace
$input = implode(" ", $input);
$input = explode(" ", $input);
$input = " " . implode(" ", $input) . " ";

// Fix escaped characters and variables
$input = str_replace(" \\", "", $input);
$input = str_replace("\\", "", $input);
$input = str_replace("¬ ", " ¬", $input);
$input = str_replace("( ", "(", $input);
$input = str_replace(") ", ")", $input);
$input = str_replace("{ ", "{", $input);
$input = str_replace("} ", "}", $input);
$input = str_replace("[ ", "[", $input);
$input = str_replace("] ", "]", $input);
$input = str_replace("< ", "<", $input);
$input = str_replace("> ", ">", $input);

$output = trim($input);

if ($decode == TRUE)
$output = html_entity_decode($output, ENT_QUOTES, $charset);

return $output;

}