## to protect against loss of information whilst constructing patterns ${{ var workIsDone = false; window.onbeforeunload = confirmBrowseAway; function confirmBrowseAway() { if (!workIsDone) { return "Are you sure? If you leave this page now, your work will NOT be saved."; } }; }}$; ## to allow JS-EDEN to handle the Greek characters a-? ${{ parser.lexer.rules = [/^\*\//,/^./,/^\/\*/,/^[\n\r]/,/^./,/^\u0023\u0023/,/^\$\{\{/,/^\}\}\$/,/^([\n\r]|.)/,/^\\"/,/^"/,/^(.|\n)/,/^"/,/^\\./,/^'/,/^./,/^'/,/^\s+/,/^@/,/^[0-9]+(\.[0-9]+)?\b/,/^is\b/,/^delete\b/,/^insert\b/,/^append\b/,/^shift\b/,/^after\b/,/^if\b/,/^else\b/,/^for\b/,/^while\b/,/^do\b/,/^switch\b/,/^case\b/,/^default\b/,/^break\b/,/^continue\b/,/^return\b/,/^func\b/,/^proc\b/,/^auto\b/,/^para\b/,/^[a-zA-Z\u03B1-\u03C9_a-d][a-zA-Z\u03B1-\u03C9_0-9]*/,/^\?/,/^\/\//,/^<=/,/^>=/,/^/,/^==/,/^!=/,/^and\b/,/^or\b/,/^\|\|/,/^&&/,/^!/,/^=/,/^\+=/,/^-=/,/^\+\+/,/^--/,/^&/,/^\*/,/^\//,/^%/,/^-/,/^\+/,/^;/,/^\?/,/^:/,/^,/,/^~>/,/^\[/,/^\]/,/^\{/,/^\}/,/^\(/,/^\)/,/^\./,/^`/,/^\$[0-9]+/,/^\$/,/^#/,/^$/,/^./]; }}$; ## the instance of '##' in the above RE definition ## has been replaced by '^\u0023\u0023' ## this means that it can be accepted via the EDEN ## interface, but needs to be interpreted before ## Greek characters in the file can be interpreted. /* valrange α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω 03B0 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 03C0 00 01 02 03 04 05 06 07 08 09 */ ## ideally this extension to the parser should be more "call-by-need" - only implemented in the script factory environment ## from Tim Monks - procedure for manipulating REs in the search box: /* proc showObservables { ${{ $('#symbol-search > .side-bar-topic-title').click(); $('#observable-search').val(arguments[0]); }}$; } proc showFunctions { ${{ $('#functions > .side-bar-topic-title').click(); $('#functions-search').val(arguments[0]); }}$; } */ proc showObservables { ${{ $('.symbollist-search').val(arguments[0]); $('.symbollist-search').keyup(); }}$; } func split { ${{ var str = arguments[0]; var patt = arguments[1]; return str.split(patt); }}$; } ########### ## preliminary set up to this point ... ########### ## astr is the source string to be transformed: astr = ""; ## create a Div that displays the string colour-coded ## so as to reflect a selection of segments and a selected scriptvar segcolarr is ["red", "green", "brown", "seablue", "red", "green", "brown", "seablue","red", "green", "brown", "seablue","red", "green", "brown", "seablue" ]; currscriptvarix = 1; segcol is segcolarr[currscriptvarix]; fontsegbra is ""; fontsegket = ""; func sumls { para sls; auto i, result; result = 0; for (i=1; i<=sls#; i++) { result = result + sls[i]#; } return result; }; func mkxtr { para sls, lenmatch; auto i, j, result; result = [0]; for (i=1; i<=sls#; i++) { for (j=1; j<=sls[i]#; j++) result = result // [0]; if (result# <= sumls(sls) + (sls#-1)*lenmatch) { for (j=1; j<=lenmatch; j++) result = result // [j]; } } return result // [0]; }; strtomatch = ""; lenmatch is strtomatch#; matcharr is (strtomatch=="") ? [astr] : split(astr, strtomatch); xstr is mkxtr(matcharr, lenmatch); func mksegdispstr { para srcstr, selpatt, fbra, fket; auto i, selpattil, selpattir, result; result = ""; if ((srcstr#!=0) && (selpatt#>2)) { for (i=1; i<=srcstr#; i++) { selpattil = selpatt[i]; selpattir = selpatt[i+1]; if ((selpattil==0) && (selpattir==1)) { result = result // fbra // srcstr[i]; } else if ((selpattir==0) && (selpattil > selpattir)) { result = result // fket // srcstr[i]; } else result = result // srcstr[i]; } } return result; }; segdispstr is mksegdispstr(astr, xstr, fontsegbra, fontsegket); vertpos2 = 370; ## the Div segdisp lays out the left-hand corner of the display ## to show the pattern var id, match segment and template text segdisp is Div("", 10, vertpos2, 800, vertpos2, "
  Pattern var id: 
Match segment :
Template text :
"); ## picture is [segdisp]; showObservables("astr|curr|seg|font|strtom|len|match|xstr|vertpos2"); ## showFunctions("sum|mkx|mkseg"); ################################## ## mkpattable Div includes radio buttons for Greek chars ## also includes table displaying script var, patt varid ## template, match str and pattern resulting ## for defining scriptvar func unicode { ${{ var x = arguments[0]; return String.fromCharCode(x + 944); }}$; }; scriptvar is fontsegbra + unicode(currscriptvarix) + fontsegket; ## for defining pattvarid allgkch is ["α","β","γ","δ","ε","ζ","η","θ","ι","κ","λ","μ","ν","ξ","ο"]; func subststar { ${{ var s = arguments[0]; var lsgkch = arguments[1]; var i, gkch, repstr; for (i=0; i0) ? x1[0] : ""; if (x1.length>0) { for (i=1; i 1; βpresent is split(pattstr,"β")# > 1; γpresent is split(pattstr,"γ")# > 1; δpresent is split(pattstr,"δ")# > 1; εpresent is split(pattstr,"ε")# > 1; ζpresent is split(pattstr,"ζ")# > 1; ηpresent is split(pattstr,"η")# > 1; θpresent is split(pattstr,"θ")# > 1; ιpresent is split(pattstr,"ι")# > 1; κpresent is split(pattstr,"κ")# > 1; λpresent is split(pattstr,"λ")# > 1; μpresent is split(pattstr,"μ")# > 1; νpresent is split(pattstr,"ν")# > 1; ξpresent is split(pattstr,"ξ")# > 1; οpresent is split(pattstr,"ο")# > 1; prefixpattvarid is ((αpresent) ? "α" : "") // ((βpresent) ? "β" : "") // ((γpresent) ? "γ" : "") // ((δpresent) ? "δ" : "") // ((εpresent) ? "ε" : "") // ((ζpresent) ? "ζ" : "") // ((ηpresent) ? "η" : "") // ((θpresent) ? "θ" : "") // ((ιpresent) ? "ι" : "") // ((κpresent) ? "κ" : "") // ((λpresent) ? "λ" : "") // ((μpresent) ? "μ" : "") // ((νpresent) ? "ν" : "") // ((ξpresent) ? "ξ" : "") // ((οpresent) ? "ο" : ""); pattvarid is prefixpattvarid // "_" // subststar(scriptvarid, allgkch); ## for defining createdstr func compose { ${{ var x1 = arguments[0]; var y1 = arguments[1]; var fcol = arguments[2]; var i, result; if (x1.length < 1) { result = ""; } else { result = x1[0]; for (i=1; i \u03B1     \u03B2     \u03B3     \u03B4     \u03B5     \u03B6     \u03B7     \u03B8     \u03B9     \u03BA     \u03BB     \u03BC     \u03BD     \u03BE     \u03BF    
Script Variable Pattern Var id Template Match Pattern
" + scriptvar + "
" + pattvarid + "
" + segdispstr + "
" + strtomatch + "
" + createdstr + "
" ); ## picture is [segdisp, mkpatttable]; showObservables("mkp|segdisps|.*pres|pref|pattv|patts|scriptva|all|cre|vertpos$"); ## showFunctions("compose|substst|mkstr|unic"); ## defining the auxscriptdisp where context for pattern is specified auxscriptdisp is Div("scriptdiv", 810, vertpos2, 1700, vertpos2, "
  
"); pattcontext = ""; picture is [segdisp, mkpatttable, auxscriptdisp]; showObservables("auxs|pattc"); ############ ## The substantive state information is defined at this point ## need actions and buttons for maintenance - versions here use JQuery ## actions are essentially the same (?) but one is EDEN, one JS /* proc maintainforinput { ${{ $("#scriptvid")[0].value = root.lookup("scriptvarid").cached_value; $("#matchseg")[0].value = root.lookup("strtomatch").cached_value; $("#srcstring")[0].value = root.lookup("astr").cached_value; $("#auxscript")[0].value = root.lookup("pattcontext").cached_value; $("#selscriptvar")[0].children[root.lookup("currscriptvarix").cached_value-1].checked = "true"; }}$; }; */ ${{ window.updatescriptvar = function updatescriptvar(ix) { (root.lookup("currscriptvarix")).assign(ix, this).value(); $("#selscriptvar")[0].children[ix-1].checked = true; $("#scriptvid")[0].value = root.lookup("scriptvarid").cached_value; $("#matchseg")[0].value = root.lookup("strtomatch").cached_value; $("#srcstring")[0].value = root.lookup("astr").cached_value; $("#auxscript")[0].value = root.lookup("pattcontext").cached_value; } }}$; ## useful to call maintainforinput at this point to initialise display ## maintainforinput(); ############ ## eventual display content is: ## picture is [segdisp, mkpatttable, update1, update2, update3, recordpatt, resetpatt, auxscriptdisp, recordcontext, toggleinterpret]; ## defining the buttons that manage the display: ## update1, update2, update3, recordpatt, ## resetpatt, recordcontext, toggleinterpret update1 is Button("setval1", "Update patt id", 320, vertpos2+13, true); update2 is Button("setval2", "Update match", 320, vertpos2 + 53, true); update3 is Button("setval3", "Update template", 20, vertpos2+100, true); ## update buttons simply register in EDEN the string values latent in display proc updateval1 : setval1_clicked { if (setval1_clicked) { ${{ (root.lookup("scriptvarid")).assign($("#scriptvid")[0].value, this).value(); }}$; maintainforinput(); } }; proc updateval2 : setval2_clicked { if (setval2_clicked) { ${{ (root.lookup("strtomatch")).assign($("#matchseg")[0].value, this).value(); }}$; maintainforinput(); } }; proc updateval3 : setval3_clicked { if (setval3_clicked) { ${{ (root.lookup("astr")).assign($("#srcstring")[0].value, this).value(); }}$; maintainforinput(); } } ## picture is [segdisp, mkpatttable, auxscriptdisp, update1, update2, update3]; ## the record context button processes the script entered via auxscriptdisp recordcontext is Button("recctxt", "Record\ncontext", 760, vertpos2+13, true); ## updatectxt needs auxiliary functions strtols, getlscomp and mkobsdefexp ## original updatectxt seems to have an unnecessary use of both ## local and contextual EDEN observables for pattcontextarr ## cf. pattcntxtarr in 26th Sept which is not in the local scope ## opt for local here but of course may be desirable to expose via script ## cf discussion around line 1050 in 26th Sept version ## also using .length in EDEN context - unnec / undesirable func strtols { ${{ var nls = arguments[0]; var result = new Array(); return result = nls.split("\n"); }}$; } ## pattcntxtarr is strtols(pattcontext); func mkobsdefexp { ${{ var n = arguments[0]; var obseq, obs, defexp; obseq = n.match(/^([^=]*)=\s*/)[0]; obs = n.match(/^([^=\s]*)\s*=\s*/)[1]; ## console.log(obs); defexp = n.replace(/^[^=]*=[\s]*/,""); defexp = defexp.replace(/\s*;$/,""); return [obs, defexp]; }}$; } ## helper function addressing problems of parsing lsfn(par)[i] expression ## to specify components of list returned by a function func getlscomp { return $1[$2]; } /* ## old version unnecessarily complicated semantically? proc updatectxt : recctxt_clicked { auto pattcontextarr, i, obs, defexp; if (recctxt_clicked) { ${{ (root.lookup("pattcontext")).assign($("#auxscript")[0].value, this).value(); }}$; pattcontextarr = strtols(pattcontext); ## writeln("From updatectxt:\n"); for (i=1; i<=pattcontextarr#; i++) { ## writeln(pattcontextarr[i]); obs = getlscomp(mkobsdefexp(pattcontextarr[i]),1); if (pattcontextarr[i]#>1){ defexp = getlscomp(mkobsdefexp(pattcontextarr[i]),2); ## writeln(defexp); ## writeln(subststar(defexp,allgkch)); } execute(obs // " = " // subststar(defexp, allgkch) // ";"); } maintainforinput(); } }; */ proc updatectxt : recctxt_clicked { if (recctxt_clicked) { ${{ (root.lookup("pattcontext")).assign($("#auxscript")[0].value, this).value(); }}$; execute(pattcontext); maintainforinput(); } }; ## picture is [segdisp, mkpatttable, auxscriptdisp, update1, update2, update3, recordcontext]; ## updating current pattern instance is associated with updating context allgkchtrigger is [α,β,γ,δ,ε,ζ,η,θ,ι,κ,λ,μ,ν,ξ,ο]; pattinstance is subststar(pattstr, allgkch, allgkchtrigger); ## actions to manage the list of recorded patterns ## requires control over whether EDEN interpretation is ventured ## defining toggleinterpret readytointerpret = 0; toggleinterpret is Button("settointerpret", (!readytointerpret) ? "Interpret OFF" : "Interpret ON", 600, vertpos2+13, true); ## without the if-clause it seems that this procedure can be triggered ## when the button is redrawn, whether or not it's been clicked proc setforinterpret : settointerpret_clicked { if (settointerpret_clicked) { readytointerpret = 1 - readytointerpret; maintainforinput(); } } ## picture is [segdisp, mkpatttable, auxscriptdisp, update1, update2, update3, recordcontext, toggleinterpret]; recordpatt is Button("recpatt", "Record pattern", 490, vertpos2+13, true); ## needs pattlist in place: pattlist = []; proc updatepattlist : recpatt_clicked { if (recpatt_clicked) { execute(pattvarid + " is [pattcontext, pattstr];"); ## writeln("pattlist = pattlist // [" + pattvarid + "];"); execute("pattlist = pattlist // [" + pattvarid + "];"); writeln(pattlist); if (readytointerpret) { ## execute(pattcontext); execute(pattinstance); ## assumes that pattinstance is executable! ## maybe good idea to link this action to status of 'Interpret ON' } maintainforinput(); } } ## picture is [segdisp, mkpatttable, auxscriptdisp, update1, update2, update3, recordcontext, toggleinterpret, recordpatt]; resetpatt is Button("resetpattls", "Reset pattern list " // pattlist#, 550, vertpos2+53, pattlist#!=0); proc resetpattlist : resetpattls_clicked { if (resetpattls_clicked) { pattlist = []; maintainforinput(); } } picture is [segdisp, mkpatttable, auxscriptdisp, update1, update2, update3, recordcontext, toggleinterpret, recordpatt, resetpatt]; showObservables("upd|rec|setv|allgkcht|patti|pattl|ready|togg|reset"); ## showFunctions("strtols|getlscomp|mkobsdefexp");