KGRKJGETMRETU895U-589TY5MIGM5JGB5SDFESFREWTGR54TY
Server : Apache/2.4.62
System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64
User : www ( 80)
PHP Version : 8.3.8
Disable Function : NONE
Directory :  /domains/markrose/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /domains/markrose/mg.html
<HTML> 
<HEAD>
<meta http-equiv="content-type" content="text-html; charset=utf-8">
<TITLE>mg - Minimalism Gadget</TITLE>

<style>
	h2
		{color:#A60000;}
	h3
		{color:#C08700;}
	h4
		{color:#C08700;}
	h5
		{color:#C08700;}
	h6
		{color:#C08700;}
	tt
		{color:#A60000;
		font-weight:bold;
		font-family:"Gentium";}
	
</style>

</HEAD> 

<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<form action="" name="theform">
<script language="javascript" type="text/javascript">

// Script (C) 2018 by Mark Rosenfelder.

var theform;
var lex;
var ord;


// Random int from 0 to n
function randomInt(max) 
{
  return Math.floor(Math.random() * max) ; 
}

// Return the word portion of a lexeme (before the :)
function theword(s) 
{
	var i = s.indexOf(':');
	if (i == -1) return s;
	return s.substr(0,i);
}

// Return the category of a lexeme (just after the :)
function thehead(s) 
{
	var spp = s.split(":")
	if (spp.length < 2) return s;
	
	var shpp = spp[1].split(" ");
	return shpp[0];
}

// Search lexicon for items that want a following x
function wanters(lex, x) 
{
	var out = new Array();

	for (var r = 0; r < lex.length; r++) {
	    var partz = lex[r].split(":");
	    if (partz.length == 1) continue;

	    var catz = partz[1].split(" ");
	    if (catz.length == 1) continue;

	    if (catz[0] == "A" && countA >= 2) continue;

	    if (catz[1] == x)
		out.push(lex[r]);
	}

	return out;
}

// Create a terminal node from a string
function TermS(s, h)
{
	var node = {head:"XP", term:true, left:"a" };
	node.head = h;
	node.left = s;
	return node;
}

// Create a terminal node from a lexeme
function Term(lx)
{
	return TermS( lx, thehead(lx) );
}

// Create a trace node based on another node
function Trace(b, h)
{
	return TermS( "&lt;<i>" + showterms(b).substr(1) + "</i>&gt;:" + h, h);
}

// Find a word in the lexicon and return it as a node
function FindNode(tgt) 
{
	for (var r = 0; r < lex.length; r++) {
	    if (theword(lex[r]) == tgt) 
	        return Term(lex[r]);
	}

	return null;	    
}

// Add to the output
function report(s) 
{
	var text = document.getElementById("mytext")

	text.innerHTML = text.innerHTML + s;
}

var indent = 0;

// Output an entire tree
function showtree(tree)
{	
	var s = "";

	if (tree.term) {
	    var lx = tree.left;
	    s += "<br>";
	    for (i = 0; i < indent; i++) 
		s += "&nbsp;&nbsp;&nbsp;&nbsp;";
	    s += tree.head + ":" + theword(lx);
	} else {
	    s += "<br>";
	    for (i = 0; i < indent; i++) 
		s += "&nbsp;&nbsp;&nbsp;&nbsp;";
	    s += tree.head;
	    indent++;
	    s += showtree(tree.left);
	    s += showtree(tree.right);
	    indent -= 1;
	}
	return s;
}

// Output only the terminals
function showterms(tree) 
{
	var s = "";

	if (tree.term) {
	    w = theword(tree.left);
	    if (w.charAt(0) != '&' && w!= "Past" && w != "Pres" && w != "Q" && w != "ø")
		s += " " + w;
	} else {
	    s += showterms(tree.left);
	    s += showterms(tree.right);
	}
	return s;
}

// Check the order of a/b from the order table.
// Return true iff we should place b first.
function Rev(a, b, h)
{
	var ab = a.head + " " + b.head;
	var ba = b.head + " " + a.head;

	// Look through ord to see if we have this ordering
	for (var i = 0; i < ord.length; i++) {
	    var s = ord[i];
	    var ss = s.split(":");
	    if (ss[0] == ab || ss[0] == ba) {
		if (ss.length == 1 || ss[1] == h)
		    return ss[0] == ba;
	    }
	}	    

	return false;
}

// Create a node from two compatible nodes
function Merge(a, b, h)
{
	var node = {head:"XP", term:false, left:"a", right:"b"};
	node.head = h;

	if (Rev(a, b, h)) {
	    node.left = b;
	    node.right = a;
	} else {
	    node.left = a;
	    node.right = b;
	}

        Agree(a, b);
	DoCase(a, b);

	report("<p><b>Merge " + h + "</b>: " + showtree(node));

	return node;
}

// Search a tree for any node of type h
//	want D
//	[P on [D [D the] [N mat]]]
// returns [D the]
function Find(tree, h) 
{
	if (tree.term) {
	    var lx = tree.left;
	    if (thehead(lx) == h) return tree;
	} else {
	    var n = Find(tree.left, h);
	    if (n != null) return n;
	    n = Find(tree.right, h);
	    if (n != null) return n;
	}
	
	return null;
}

// Search for the parent of node n
function FindParent(tree, tgt) 
{
	if (tree.term) return null;

	if (tree.left == tgt || tree.right == tgt) return tree;

	var n = FindParent(tree.left, tgt);
	if (n != null) return n;
	n = FindParent(tree.right, tgt);
	if (n != null) return n;

	return null;
}

// Find the *container* of any node marked h.
//	want D
//	[P on [D [D the] [N mat]]]
// returns P 
function Finddad(tree, h)
{
	if (tree.term) return null;

	if (tree.left.head == h || tree.right.head == h) return tree;

	var n = Finddad(tree.left, h);
	if (n != null) return n;
	var n = Finddad(tree.right, h);
	if (n != null) return n;

	return null;
}

var onleft = false;

// Find the *container* of a *terminal* node marked h.
//	want D
//	[P on [D [D the] [N mat]]]
// returns D 
function FindDadOfTerm(tree, h)
{
	if (tree.term) return null;

	if (tree.left.head == h && tree.left.term) {
	    onleft = true; 
	    return tree;
	}
	if (tree.right.head == h && tree.right.term) {
	    onleft = false; 
	    return tree;
	}

	var n = FindDadOfTerm(tree.left, h);
	if (n != null) return n;
	var n = FindDadOfTerm(tree.right, h);
	if (n != null) return n;

	return null;
}

// Copy features to a noun modifier
// Example:
//	cats:N:p
//	this:D N:p these
// change D to these
function Agree(mod, tree)
{
	if (!mod.term) return false;

	if (mod.head != "A" && mod.head != "D") return false;

    	var n = Find(tree, "N");
    	if (n == null) return false;
	
	npp = n.left.split(":");
	if (npp.length < 3) return false;

	return Inflect(mod, npp[2]);
}

// Handle case assignment for pronouns
function DoCase(mod, n)
{
	if (n.head != "D") return;
	if (mod.head != "V" && mod.head != "P") return;

    	var n = Find(n, "N");
	if (n == null) return;

	npp = n.left.split(":");
	if (npp.length < 4) return;

	var f = npp[3];
	if (mod.head == "P" && npp.length == 5)
	    f = npp[4];

        n.left = f + ":" + npp[1] + ":" + npp[2] + ":" + npp[3];
}

// Copy tense + number to verb
// Example:
//      cat:N:s
//	Past:T VP:Past
//	sit:V P D:Pasts sat Pastp sat Prog sitting …
// change verb to sat
function Tense(tree) 
{
    var t = Find(tree, "T");
    var v = Find(tree, "V");
    var n = Find(tree, "N");

    if (t == null || v == null || n == null) return false;
    tpp = t.left.split(":");

    // If there's a modal, it has no features to copy; we're done
    if (tpp.length < 3) return false;
    var feat = tpp[2];
    
    npp = n.left.split(":");
    if (npp.length > 2) feat += npp[2];

    return Inflect(v, feat);
}

// Given a verb and the desired form, change the verb to that form.
// Example:
//	form = Prog
//	sit:V P D:s sits Past sat Prog sitting Perf sat
// change "sit" to "sitting"
function Inflect(v, form) 
{
	var vl = v.left;
	var vpp = vl.split(":");
	if (vpp.length < 3) return;
 
	var vforms = vpp[2].split(" ");
	for (var i = 0; i < vforms.length; i += 2) {
	    if (vforms[i] == form) {
		v.left = vforms[i+1] + ":" + vpp[1] + ":" + vpp[2];
		return true;
	    }
	}

	return false;
}

// Get a word of type target
function getnode(target) 
{
	// Find all lexemes of the target category
	var s = "<p>Candidate " + target + ": ";
	var candz = new Array();

	for (var j = 0; j < lex.length; j++) {
	    var lx = lex[j];
	    if (thehead(lx) == target) {
		candz.push(lx);
		s += theword(lx) + " ";
	    }
	}

	// Randomly select one
	var m = randomInt(candz.length);

	var node = Term(candz[m]);
	s += "<br>Selecting " + showtree(node);
	report(s);	

	return node;
}

// Given a lexeme, set the specifer.  E.g. 
//	sleep:V P D:Press sleeps
// the specifier is D.

function setSpec(lx)
{
	var partz = lx.split(":");
	if (partz.length > 1) {
	    var catz = partz[1].split(" ");
	    if (catz.length > 2)
	        return catz[2];
	}

	return "";
}

// Get a word that wants type target
function getWant(target) 
{
	var s = "<p>Words that want " + target + ": ";
	var w = wanters(lex, target);
	if (w.length == 0) 
	    return null;

	for (var i = 0; i < w.length; i++)
	    s += theword(w[i]) + " ";

    	var m = 0;
	if (w.length > 1)
	    m = randomInt(w.length);

	var node = Term(w[m]);
	s += "<br>Selecting " + showtree(node);
	report(s);

	return node;
}

var hasAux = false;

// Optionally apply an auxiliary
function Aux(tree, tgt) 
{
	// Find the auxiliary in the lexicon
	for (var r = 0; r < lex.length; r++) {
	    var partz = lex[r].split(":");
	    if (partz.length == 1) continue;

	    var catz = partz[1].split(" ");
	    if (catz.length > 1 && catz[0] == "Aux" && catz[1] == tgt) {
		// Bingo.  Add it to the tree
		var ct = "V";
		if (catz[1] == "Neg") ct = "Neg";
		var lx = partz[0] + ":" + ct + " VP:" + partz[2];
		var a = Term(lx);
		
		// Apply inflection to the verb
		var v = Find(tree, "V");
		Inflect(v, tgt);

		if (ct == "V")
		    hasAux = true;

		return Merge(a, tree, "VP");
	    }
	}
	return tree;
}

var countA = 0;
var theObj = null;

// Put together a tree of type target, starting with a noun
function gettree(target)
{
	// Get an N node
	var subtarg = "N";
	var b = getnode(subtarg);
	countA = 0;
	if (theObj == null)
	    theObj = b;

	// Pronouns automatically get a null D
	var npp = b.left.split(":");
	if (npp.length > 3) {
	    subtarg = "D";
	    var d = TermS("ø:" + subtarg, subtarg);
	    b = Merge(d, b, subtarg);
	}
	
	// Some nodes want *two* nodes
	var spc = "";

	// Repeat building process till we have a tree of type target		
	for (var h = subtarg; h != target; ) {
	
	    // Find a node that wants h
	    // But: some nodes want a third argument
	    if (spc != "") {
		var tmp = spc;
		spc = "";
	    	var a = gettree(tmp);
		b = Merge(a, b, "VP");

		b = special(b, false);

		h = b.head;
	    } else {
	        var a = getWant(h);
		if (a == null) {
		    report("<p><b>No words found</b> that want " + h + ".  Check the lexicon!");
		    return b;
		}
		    
		spc = setSpec(a.left);
		var h = a.head;
		if (h == "A") {
		    h = b.head; // kludgy
		    countA += 1;
		}

	        b = Merge(a, b, h);
	    }
	}
	
	return b;
}

// Move a subtree, extending the entire tree with it.
function Move(tree, h, newh)
{
	var t = tree.left;
	var tgt = Finddad(tree, h);
	if (t == null || tgt == null) return tree;

	// Find the target node, remembering what side it's on
	var onleft = tgt.left.head == h;
	var tn;
	if (onleft) tn = tgt.left;
	else tn = tgt.right;

	// Create trace node
	var tr = Trace(tn, h);
	if (onleft) tgt.left = tr;
	else tgt.right = tr;
	
	// Extend tree with moved  node
	return Merge(tn, tree, newh);
}

// Given a node a, replace it with [b a].
// Leave a trace where b was.
// Warning: won't work if a is the highest node (a == tree)
function Prepend(tree, a, b)
{
	var ad = FindParent(tree, a);
	var bd = FindParent(tree, b);
	
	// Merge a and b
	var ab = Merge(b, a, a.head);

	// Fix up a's parent to point to merged node
	if (ad.left.head == a.head)
	    ad.left = ab;
	else
	    ad.right = ab;

	// Leave the trace, if b was already in the tree
	if (bd != null) {
	    var tr = Trace(b, b.head);
  	    if (bd.left.head == b.head)
	    	bd.left = tr;
	    else
	    	bd.right = tr;	
	}

    	report(showtree(tree));
}

// Special rules
// First set is for gettree; second set is for process
function special(tree, skip)
{
	var sp = theform.spec.value.split("\n");
	for (var i = 0; i < sp.length; i++) {
	    spr = sp[i];

	    if (spr == "+") 
		skip = !skip;

	    if (skip) continue;

	    spp = spr.split(":");
	    if (spp.length < 3) continue;

	    // Randomization
	    var pct = parseInt(spp[0], 10);
	    if (pct == 0) continue;
	    if (pct < 100 && randomInt(100) > pct) continue;
	
	    // Individual conditions
	    var cpp = spp[1].split(" ");
	    var stop = false;
	    for (var j = 0; !stop && j < cpp.length; j++) {
	        var cond = cpp[j];
		if (cond == "!Aux")
	            stop = hasAux;
		if (cond == "Aux")
	            stop = !hasAux;
		if (cond == "Neg")
		    stop = Find(tree, "Neg") == null;
		if (cond == "Tø") {
		    var t = Find(tree, "T");
		    stop = t == null || showterms(t).substr(1) != "";
	    	}
		if (cond == "ObjPron") {
		    var np = FindParent(tree, theObj);
		    var d = Find(np, "D");
		    stop = d == null || d.left != "ø:D"; 
		    if (!stop) {
			var dp = FindParent(tree, np);
			report( "<b>dp is " + dp.head );
			if (dp != null && dp.head == "P")
			    stop = true;
		    }
		}
		if (cond == "Q") {
		    var q = Find(tree, "C");
		    stop = q == null || theword(q.left) != "Q";
		}
		if (cond == "NegQ") {
		    var n = Find(tree, "Neg");
		    if (n != null) 
			stop = false;
		    else {
		    	var q = Find(tree, "C");
			stop = q == null || theword(q.left) != "Q";
		    }
		}
	    }
	    if (stop) continue;

	    var ru = spp[2];
	    report( "<p>Special rule: <b>" + ru + "</b>");

	    if (ru == "Aux") {
		tree = Aux(tree, spp[3]);
	    }
	    if (ru == "Q") {
 		var c = TermS("Q:C", "C");
		tree = Merge(c, tree, "CP");
	    }
	    if (ru.charAt(0) == "^") {
		ru = ru.substring(1);
		tree = Move(tree, ru, spp[3]);
	    }
	    if (ru == "OV") {
		var v = Find(tree, "V");
		var o = FindParent(tree, theObj);
		Prepend(tree, v, o);
	    }
	    if (ru == "AuxMove") {  // Could this be done with Prepend?
		var t = Find(tree, "T");
		var v = Find(tree, "V");

		var a = TermS(v.left, "V");
		var tt = Merge(a, t, "T");
		tree.left = tt;

		v.left = "&lt;<i>" + showterms(v).substr(1) + "</i>&gt;:V";

        	report(showtree(tree));
	    }
	    if (ru.indexOf('+') != -1) {
		// Term movement
		ndd = ru.split("+");
		var ah = ndd[0];
		var bh = ndd[1];

		var a = Find(tree, ah);
	
		var b;
		var bd = null;
		if (bh == bh.toLowerCase()) {
		    // bh gives an actual word
		    b = FindNode(bh);
		} else {
		    // bh is a node
		    b = Find(tree, bh);
		    var bd = FindDadOfTerm(tree, bh);
		}

		Prepend(tree, a, b);
	    }
	    if (ru.indexOf('«') != -1) {
		// Node movement - may only work for English C<T
		// given either [T1 [T2 VP]]
		//           or [T1 [T2 [V T3]]]
		// b is T2, bd is T1
		ndd = ru.split("«");
		var ah = ndd[0];
		var bh = ndd[1];

		var a = Find(tree, ah);
		var b = Find(tree, bh);
		var bd = FindParent(tree, b);

		if (bd.right.head == "V" || bd.left.head == "V") {
		    b = bd;
		}

		Prepend(tree, a, b);
	    }

	}

	return tree;
}

// User hit the Generate button
function process()
{
	//Read parameters
	theform = document.theform;

	// Read the lexicon
	var s = theform.lex.value;
	lex = s.split("\n");

	// Read constituent order table
	s = theform.ord.value;
	ord = s.split("\n");

	var text = document.getElementById("mytext")
	text.innerHTML = "<p><b>Building tree</b>";

	// Get ourselves a TP
	hasAux = false;
	theObj = null;
	var tree = gettree("T");

	// Failure condition - the rules are bad
	if (tree.head != "T") return; 

	// Apply special rules
	tree = special(tree, true);

	// Correct tense/number
	if (Tense(tree)) 
	    report( "<p>Corrected <b>Verb</b>: " + showtree(tree) );

	// Final output goes *first*
	var s = "<b>Generated sentence</b><i> " + showterms(tree) + "</i>";	
	if (tree.head == "CP")
	    s += "?"
	else
	    s += ".";
	text.innerHTML = s + text.innerHTML;
}

function helpme() 
{
	window.open("mghelp.html"); 
}


// Replace a textarea with the given array
function string2text(data, field)
{
	var s = "";
	for (var i = 0; i < data.length; i++) {
		s += data[i];
		if (i < data.length - 1) s += "\n";
	}

	document.getElementById(field).innerHTML = s;
}

function french() 
{
	var data = [
"le:D N:sf la pm les pf les",
"il:N:sn:le:lui",
"elle:N:sf:la:elle",
"ils:N:pm:les:eux",
"elles:N:pf:les:elles",
"chat:N:sm",
"chats:N:pm",
"souris:N:sf",
"souris:N:pf",
"chien:N:sm",
"chiens:N:pm",
"vache:N:sf",
"vaches:N:pf",
"dormir:V P D:Pressf dort Pressm dort Prespf dorment Prespm dorment Perf dormi",
"aimer:V D D:Pressf aime Pressm aime Prespf aiment Prespm aiment Perf aimé",
"voir:V D D:Pressf voit Pressf voit Prespf voient Prespm voient Perf vu",
"avoir:Aux Perf:Pressf a Pressm a Prespm ont Prespf ont",
"sur:P D",
"beau:A N:sf belle pm beaux pf belles",
"laid:A N:sf laide pm laids pf laides",
"rouge:A N:pm rouges pf rouges",
"vert:A N:sf verte pm verts pf vertes",
"brun:A N:sf brune pm bruns pf brunes",
"mignon:A N:sf mignonne pm mignons pf mignonnes",
"fou:A N:sf folle pm foux pf folles",
"Pres:T VP:Pres",
"pas:Aux Neg",
"ne:Neg"];

	string2text(data, "lex");

data = [ "D N", "N A", "V P", "V N:V", "N V:VP", "T VP", "P D", "C T", "V VP", "Neg VP" ];

	string2text(data, "ord");

data = [ "33::Aux:Perf", "33::Aux:Neg", "+", 
	 "100:Aux Tø:AuxMove", "100::^D:TP", "100:!Aux Neg:T+V", "100:Neg:V+ne", "100:ObjPron:OV" ];

	string2text(data, "spec" );
}


</script>

<table width="100%">
<tr><td bgcolor="#EEC25A">
<h2><br>&nbsp;&nbsp;<a href="kit.html"><img src="chomsky.gif" border=0 align="absmiddle" height="53" width="60"></a>&nbsp;mg</h2></td></tr>
</td></tr>
</table>

<i>This is a Javascript program which allows you to define the lexicon for a Minimalist grammar and build a random sentence node by node.  Press Generate to test, and Help for documentation.

<p>Also see: <A href="markov.html">Markov generator</a>; <a href="ggg.html">Generative Grammar Gadget</a>; <a href="gtg.html">Generative Tree Gadget<a>.

<p>&#8212;Mark Rosenfelder, 2018</i>

<hr>

<table width="100%">

<tr>
<td>
Lexicon:
<br><textarea id="lex" name="lex" rows="10" cols="50">
the:D N
her:D N
his:D N
this:D N:p these
that:D N:p those
he:N:s:him
she:N:s:her
cat:N:s
cats:N:p
dog:N:s
dogs:N:p
frog:N:s
frogs:N:p
mouse:N:s
mice:N:p
mat:N:s
mats:N:p
sit:V P D:Press sits Pasts sat Pastp sat Prog sitting Perf sat
sleep:V P D:Press sleeps Pasts slept Pastp slept Prog sleeping Perf slept
hate:V D D:Press hates Pasts hated Pastp hated Prog hating Perf hated
love:V D D:Press loves Pasts loved Pastp loved Prog loving Perf loved
chase:V D D:Press chases Pasts chased Pastp chased Prog chasing Perf chased
have:Aux Perf:Press has Past had Pastp had Prog having Perf had
be:Aux Prog:Press is Presp are Pasts was Pastp were Prog being Perf been
do:V:Press does Pasts did Pastp did
not:Aux Neg
on:P D
by:P D
near:P D
big:A N
fat:A N
Past:T VP:Past
Pres:T VP:Pres
must:T VP
may:T VP
can:T VP</textarea>
</td>
<td width="30px">&nbsp;</td>

<td>
Order:
<br><textarea id="ord" name="ord" rows="10" cols="20">
D N
A N
V P
V N:V
N V:VP
T VP
P D
C T
V VP
Neg VP
</textarea>
</td>



<td>
Special:
<br><textarea id="spec" name="spec" rows="10" cols="35">
33::Aux:Perf
25::Aux:Prog
25::Aux:Neg
+
100:Aux Tø:AuxMove
100::^D:TP
25::Q
100:!Aux NegQ Tø:T+do
100:Q:C«T
</textarea> 
</td>


<td>
<p><input type="button" value="Generate" onClick="process();">

<p><input type="button" value="Help me!" onClick="helpme();">

<p><input type="button" value="French" onClick="french();">

</td>
</tr></table>

<hr>

<h3>Output</h3>
<br><div id="mytext"> </div>


</form>

<hr>

<center><A HREF="default.html"><img src="homeg.gif" border=0 alt="Home"></A></center>

</body>
</html>


Anon7 - 2021