I am Bored Posted February 8, 2015 Report Posted February 8, 2015 (edited) First off, I do intend to clean up this post a bit later and make the tool a bit more usable, but that will have to wait until I'm not asleep. First up, the sane code. Looks like pretty normal PHP to me. <? (locations 1_-1x3_1) // This is the key we give the user. $MDS_Key = "iab-quiz-key"; // This is the key used for the storage. $Storage_Key = "iabTestKey"; // All answers should be stored lowercase. $Questions = array( 1 => array( "What is this?", "clicky" ), 2 => array( "Who made this?", "orvid" ) ); // List of users who have completed the quiz. $usersFinished = mds_storage($Storage_Key, "toau", array()); if (uv("name") == "Orvid") { if (count($usersFinished) > 0) { echo "<p>The following users have completed the challenge:<br/>"; for ($i = 0; $i < count($usersFinished); $i++) { echo $usersFinished[$i] . "<br/>"; } echo "</p><br/><br/>"; } // Uncomment the next line to reset the storage to remove all users. //$usersFinished = array(); } if (mds_has_rpcq_keys($MDS_Key)) { // Uncomment the ne_xt line to reset your key sta_te for testing. //mds_take_rpcq_keys($MDS_Key); echo "You have already completed the quiz!"; } else { echo "<form method='post' action=''>"; $currentQuestion = 0; if (isset($input['page']) AND $input['page'] == "front") { $currentQuestion = 1; } else if (isset($input['q'])) { $currentQuestion = $input['q']; if (!isset($Questions[$currentQuestion])) $currentQuestion = 0; } if (isset($input['answer'])) { if ($Questions[$currentQuestion][1] == strtolower($input['answer'])) { // Check if this was the last question if (!isset($Questions[$currentQuestion + 1])) { // This was the last question, so add the users' name to our // list, and give them a key to prevent them from re-taking // the quiz. echo "<p>Congratulations! You've completed the quiz!</p>"; $currentQuestion = -1; $usersFinished[] = uv("name"); mds_give_rpcq_keys($MDS_Key); } else { // Not the last question, continue. echo "<p>You answered correctly!</p><br/><br/>"; $currentQuestion++; } } else { echo "<p>Incorrect! Try again!</p><br/><br/>"; } } if ($currentQuestion > 0 && isset($Questions[$currentQuestion])) { echo $Questions[$currentQuestion][0]; ?> <br /> <input type='text' id='answer' name='answer' value='' /><br /> <input type='hidden' name='q' value='<?=$currentQuestion?>' /> <input name='button' type='submit' value='Submit Answer' /> <script type="application/javascript"> $('#answer').focus(); </script> <? } else if ($currentQuestion != -1) { ?> Welcome!<br/> <input type="hidden" name="page" value="front" /> <input name="button" type="submit" value="Continue" /> <? } echo "</form>"; } ?> Now, the code to transform this into a form that MDScript will accept. This code could be trivially accomplished in most other languages with a regex engine, but I chose to write it in D. It is currently hard coded to a specific file, and is only really intended as a reference for those looking to write their own form of the tool. module main; import std.algorithm : any, filter, map; import std.array : array, join, split; import std.conv : to; import std.datetime : nsecs, StopWatch; import std.file : readText, write; import std.regex : ctRegex, regex, replaceAll; import std.stdio : writeln, writefln; import std.string : strip, toLower; enum InputFile = `F:\MD\ClickableQuiz.omds`; void main(string[] args) { processFile(InputFile); } template cRegex(string pattern, string flags) { debug enum cRegex = regex(pattern, flags); else alias cRegex = ctRegex!(pattern, flags); } __gshared contentEqualRegex = cRegex!(`\?>([^]*?)<\?=([^]*?)(?=\?>)`, "g"); __gshared contentRegex = cRegex!(`\?>([^]*?)<\?(?!=)`, "g"); __gshared storageRegex = cRegex!(`\$([a-zA-Z0-9_]+)\s*=\s*mds_storage\(([^]*?),\s*("[at]o[at]u")\s*,([^]*?)\)\s*;`, "g"); __gshared variableRegex = cRegex!(`\$([a-zA-Z0-9_]+)`, "g"); __gshared stringRegex = cRegex!(`"(?:\"|.)*?"`, "g"); __gshared commentRegex = cRegex!(`//.*?$`, "gm"); __gshared documentStartRegex = cRegex!(`^\s*<\?`, "g"); __gshared documentEndRegex = cRegex!(`\?>\s*$`, "g"); string generateRegexTree(string[] str) { static class Node { char leaf; Node[] children; this() { this.leaf = '\0'; } this(char c) { this.leaf = c; } static Node buildNode(string child, Node parent) { if (child == "") { auto n = new Node('\0'); parent.children ~= n; return n; } foreach (c; parent.children) { if (c.leaf == child[0]) return buildNode(child[1..$], c); } auto n = new Node(child[0]); parent.children ~= n; return buildNode(child[1..$], n); } string build() { string ret = ""; if (leaf != '\0') ret ~= leaf; bool hasEndNode = children.any!(c => c.leaf == '\0'); if (children.length == 1 && hasEndNode) hasEndNode = false; bool addGrouping = children.length > 1 || hasEndNode; if (addGrouping) ret ~= "(?:"; ret ~= children.filter!(c => c.leaf != '\0').map!(c => c.build()).join('|'); if (addGrouping) ret ~= ')'; if (hasEndNode) ret ~= "?"; return ret; } } Node root = new Node(); foreach (c; str) root.buildNode(c, root); return root.build(); } enum knownReservedWords = import("KnownReservedWords.txt").split('\n').map!(i => i.strip()).array; __gshared knownReservedWordsRegex = cRegex!(generateRegexTree(knownReservedWords), "gi"); void processFile(string inputFile) { auto sw = StopWatch(); auto txt = readText(inputFile); sw.start(); // First, extract the content sections. string[] contentSections; txt = txt.replaceAll!((match) { contentSections ~= match[1]; auto tmp = `echo @content[` ~ (contentSections.length - 1).to!string() ~ "];\r\n"; return tmp ~ `echo "" . (` ~ match[2] ~ ");\r\n"; })(contentEqualRegex); txt = txt.replaceAll!((match) { contentSections ~= match[1]; return `echo @content[` ~ (contentSections.length - 1).to!string() ~ "];\r\n"; })(contentRegex); // And remove the opening and closing tags of the document (if present). txt = txt.replaceAll(documentStartRegex, ""); txt = txt.replaceAll(documentEndRegex, ""); // Next, remap the variables, with special handling for storage. string[string] variableMap = [ "input": "@input", ]; txt = txt.replaceAll!((match) { if (match[1] in variableMap) throw new Exception("Already mapped variable '" ~ match[1] ~ "'!"); auto vIdx = `@va[` ~ variableMap.length.to!string() ~ `]`; auto tmp = vIdx ~ ` = mds_storage(` ~ match[2] ~ `, ` ~ match[3] ~ ");\r\n"; tmp ~= `if (!isset(@storage[` ~ vIdx ~ "]))\r\n"; tmp ~= "\t@storage[" ~ vIdx ~ `] = ` ~ match[4] ~ ";\r\n"; variableMap[match[1]] = `@storage[` ~ vIdx ~ `]`; return tmp; })(storageRegex); txt = txt.replaceAll!((match) { if (match[1] in variableMap) return variableMap[match[1]]; return (variableMap[match[1]] = `@va[` ~ variableMap.length.to!string() ~ `]`); })(variableRegex); // Now to deal with reserved words. txt = txt.replaceAll!((match) { return match[0].replaceAll!((match) { auto half = match[0].length / 2; return match[0][0..half] ~ `" . "` ~ match[0][half..$]; })(knownReservedWordsRegex); })(stringRegex); txt = txt.replaceAll!((match) { return match[0].replaceAll!((match) { auto half = match[0].length / 2; return match[0][0..half] ~ `_` ~ match[0][half..$]; })(knownReservedWordsRegex); })(commentRegex); sw.stop(); writefln("Took %s ms to format '%s'", cast(real)sw.peek().nsecs / 1_000_000f, inputFile); write(inputFile ~ ".html", contentSections.join("<!-- content separator -->")); write(inputFile ~ ".php", txt); } And, lastly, the content of KnownReservedWords.txt: call error ext fprintf inf ini is_a mod move open parse read split sprintf stat t_as t_sr try use val Have fun, and may all your vars be @va. Edited February 8, 2015 by I am Bored DARK DEMON 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.