インタネットベースのプログラミング言語HTML5
実行用のソースコードはこんな感じ。
window.log = function(msg) {console.log(msg)}; window.addEventListener('load', function() { var stack = [{vars:{}, funcs:{}}]; function topContext() { return stack[stack.length - 1]; } function readParam(node) { var ret = ''; for (var i = 0; i < node.childNodes.length; i++) { var child = node.childNodes[i]; if (child.nodeType == document.TEXT_NODE) { ret += child.nodeValue; } else if (child.nodeName == 'OUTPUT') { ret += topContext().vars[child.getAttribute('name')]; } } return ret; } function callFunc(name, args) { var vars = {}; var def = topContext().funcs[name]; var code; for (var i = 0; i < def.childNodes.length; i++) { var child = def.childNodes[i]; if (child.tagName == 'P') { vars[child.getAttribute('name')] = args.shift(); } else if (child.tagName == 'CODE') { code = child; } } stack.push({vars:vars, funcs:{}}); interprete(code); stack.pop(); } function interprete(node) { if (!node) node = document.body; if (node.nodeName == 'BODY') { for (var i = 0; i < node.childNodes.length; i++) { interprete(node.childNodes[i]); } } else if (node.nodeName == 'INPUT') { topContext().vars[node.name] = node.value; } else if (node.nodeName == 'FIELDSET') { val = readParam(node); topContext().vars[node.getAttribute('name')] = val; } else if (node.nodeName == 'VAR' || node.nodeName == 'OUTPUT') { } else if (node.nodeName == 'DFN') { topContext().funcs[node.getAttribute('title')] = node; } else if (node.nodeName == 'CODE') { for (var i = 0; i < node.childNodes.length; i++) { interprete(node.childNodes[i]); } } else if (node.nodeName == 'BLOCKQUOTE') { var commandName = node.getAttribute('cite'); var args = []; for (var i = 0; i < node.childNodes.length; i++) { var child = node.childNodes[i]; if (child.nodeName == 'P') { args.push(readParam(child)); } } if (window[commandName]) { // builtin function window[commandName].apply(window, args); } else { callFunc(commandName, args); } } else if (node.nodeName == 'DL') { var condition = topContext().vars[node.getAttribute('name')]; outer: for (var i = 0; i < node.childNodes.length; i++) { var child = node.childNodes[i]; if (child.nodeName == 'DT') { if (child.childNodes.length == 0 // default condition || child.innerHTML == condition) { for (var j = i + 1; j < node.childNodes.length; j++) { var grandChild = node.childNodes[j]; if (grandChild.nodeName == 'DD') { for (var k = 0; k < grandChild.childNodes.length; k++) { interprete(grandChild.childNodes[k]); break outer; } } } } } } } else if (node.nodeName == 'PROGRESS') { var counter = node.getAttribute('name') var min = node.getAttribute('value') || 0; var max = node.getAttribute('max'); for (var i = min; i <= max; i++) { topContext().vars[counter] = i; for (var j = 0; j < node.childNodes.length; j++) { interprete(node.childNodes[j]); } } } } if (document.body.getAttribute('autostart')) { interprete(); } });