Index: trunk/extensions/ParserPlayground/tests/parserTests.pegjs |
— | — | @@ -0,0 +1,114 @@ |
| 2 | +/** |
| 3 | + * PEG.js grammar for reading MediaWiki parser tests files |
| 4 | + * 2011-07-20 Brion Vibber <brion@pobox.com> |
| 5 | + */ |
| 6 | + |
| 7 | +testfile = |
| 8 | + chunk+ |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | +eol = "\n" |
| 13 | + |
| 14 | +whitespace = [ \t]+ |
| 15 | + |
| 16 | +ws = whitespace |
| 17 | + |
| 18 | +rest_of_line = c:([^\n]*) eol |
| 19 | +{ |
| 20 | + return c.join(''); |
| 21 | +} |
| 22 | + |
| 23 | +line = (!"!!") line:rest_of_line |
| 24 | +{ |
| 25 | + return line; |
| 26 | +} |
| 27 | + |
| 28 | +text = lines:line* |
| 29 | +{ |
| 30 | + return lines.join('\n'); |
| 31 | +} |
| 32 | + |
| 33 | +chunk = |
| 34 | + comment / |
| 35 | + article / |
| 36 | + test / |
| 37 | + line |
| 38 | + |
| 39 | + |
| 40 | + |
| 41 | +comment = |
| 42 | + "#" text:rest_of_line |
| 43 | +{ |
| 44 | + return { |
| 45 | + type: 'comment', |
| 46 | + comment: text |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +empty = |
| 51 | + eol / |
| 52 | + ws eol |
| 53 | +{ |
| 54 | + return { |
| 55 | + type: 'empty' |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +article = |
| 62 | + start_article title:line start_text text:text end_article |
| 63 | +{ |
| 64 | + return { |
| 65 | + type: 'article', |
| 66 | + title: title, |
| 67 | + text: text |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +start_article = |
| 72 | + "!!" ws? "article" ws? eol |
| 73 | + |
| 74 | +start_text = |
| 75 | + "!!" ws? "text" ws? eol |
| 76 | + |
| 77 | +end_article = |
| 78 | + "!!" ws? "endarticle" ws? eol |
| 79 | + |
| 80 | + |
| 81 | +test = |
| 82 | + start_test |
| 83 | + title:text |
| 84 | + sections:section* |
| 85 | + end_test |
| 86 | +{ |
| 87 | + var test = { |
| 88 | + type: 'test', |
| 89 | + title: title |
| 90 | + }; |
| 91 | + for (var i = 0; i < sections.length; i++) { |
| 92 | + var section = sections[i]; |
| 93 | + test[section.name] = section.text; |
| 94 | + } |
| 95 | + return test; |
| 96 | +} |
| 97 | + |
| 98 | +section = |
| 99 | + "!!" ws? (!"end") name:(c:[a-zA-Z0-9]+ { return c.join(''); }) rest_of_line |
| 100 | + text:text |
| 101 | +{ |
| 102 | + return { |
| 103 | + name: name, |
| 104 | + text: text |
| 105 | + }; |
| 106 | +} |
| 107 | + |
| 108 | +/* the : is for a stray one, not sure it should be there */ |
| 109 | + |
| 110 | +start_test = |
| 111 | + "!!" ws? "test" ":"? ws? eol |
| 112 | + |
| 113 | +end_test = |
| 114 | + "!!" ws? "end" ws? eol |
| 115 | + |
Index: trunk/extensions/ParserPlayground/tests/parserTests.js |
— | — | @@ -0,0 +1,130 @@ |
| 2 | +/** |
| 3 | + * Initial parser tests runner for experimental JS parser |
| 4 | + * |
| 5 | + * This pulls all the parserTests.txt items and runs them through the JS |
| 6 | + * parser and JS HTML renderer. Currently no comparison is done on output, |
| 7 | + * as a direct string comparison won't be very encouraging. :) |
| 8 | + * |
| 9 | + * Needs smarter compare, as well as search-y helpers. |
| 10 | + * |
| 11 | + * 2011-07-20 <brion@pobox.com> |
| 12 | + */ |
| 13 | + |
| 14 | +var fs = require('fs'), |
| 15 | + path = require('path'); |
| 16 | + |
| 17 | +// @fixme wrap more or this setup in a common module |
| 18 | + |
| 19 | +// Fetch up some of our wacky parser bits... |
| 20 | + |
| 21 | +var basePath = path.join(path.dirname(process.cwd()), 'modules'); |
| 22 | +function _require(filename) { |
| 23 | + return require(path.join(basePath, filename)); |
| 24 | +} |
| 25 | + |
| 26 | +function _import(filename, symbols) { |
| 27 | + var module = _require(filename); |
| 28 | + symbols.forEach(function(symbol) { |
| 29 | + global[symbol] = module[symbol]; |
| 30 | + }) |
| 31 | +} |
| 32 | + |
| 33 | +// For now most modules only need this for $.extend and $.each :) |
| 34 | +global.$ = require('jquery'); |
| 35 | + |
| 36 | +// hack for renderer |
| 37 | +global.document = $('<div>')[0].ownerDocument; |
| 38 | + |
| 39 | +// Local CommonJS-friendly libs |
| 40 | +global.PEG = _require('lib.pegjs.js'); |
| 41 | + |
| 42 | +// Our code... |
| 43 | +_import('ext.parserPlayground.serializer.js', ['MWTreeSerializer']); |
| 44 | +_import('ext.parserPlayground.renderer.js', ['MWTreeRenderer']); |
| 45 | +_import('ext.parserPlayground.pegParser.js', ['PegParser']); |
| 46 | + |
| 47 | +// Preload the grammar file... |
| 48 | +PegParser.src = fs.readFileSync(path.join(basePath, 'pegParser.pegjs.txt'), 'utf8'); |
| 49 | + |
| 50 | +var parser = new PegParser(); |
| 51 | +var renderer = new MWTreeRenderer(); |
| 52 | + |
| 53 | +var testParser = PEG.buildParser(fs.readFileSync('parserTests.pegjs', 'utf8')); |
| 54 | +var testFile = fs.readFileSync('../../../tests/parser/parserTests.txt', 'utf8'); |
| 55 | + |
| 56 | + |
| 57 | +try { |
| 58 | + var cases = testParser.parse(testFile); |
| 59 | +} catch (e) { |
| 60 | + console.log(e); |
| 61 | +} |
| 62 | + |
| 63 | +var articles = {}; |
| 64 | + |
| 65 | +function normalizeTitle(name) { |
| 66 | + if (typeof name !== 'string') { |
| 67 | + throw new Error('nooooooooo not a string'); |
| 68 | + } |
| 69 | + name = name.replace(/[\s_]+/g, '_'); |
| 70 | + name = name.substr(0, 1).toUpperCase() + name.substr(1); |
| 71 | + if (name == '') { |
| 72 | + throw new Error('Invalid/empty title'); |
| 73 | + } |
| 74 | + return name; |
| 75 | +} |
| 76 | + |
| 77 | +function fetchArticle(name) { |
| 78 | + var norm = normalizeTitle(name); |
| 79 | + if (norm in articles) { |
| 80 | + return articles[norm]; |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +function processArticle(item) { |
| 85 | + var norm = normalizeTitle(item.title); |
| 86 | + articles[norm] = item.text; |
| 87 | +} |
| 88 | + |
| 89 | +function nodeToHtml(node) { |
| 90 | + return $('<div>').append(node).html(); |
| 91 | +} |
| 92 | + |
| 93 | +function processTest(item) { |
| 94 | + if (!('title' in item)) { |
| 95 | + console.log(item); |
| 96 | + throw new Error('Missing title from test case.'); |
| 97 | + } |
| 98 | + if (!('input' in item)) { |
| 99 | + console.log(item); |
| 100 | + throw new Error('Missing input from test case ' + item.title); |
| 101 | + } |
| 102 | + if (!('result' in item)) { |
| 103 | + console.log(item); |
| 104 | + throw new Error('Missing input from test case ' + item.title); |
| 105 | + } |
| 106 | + console.log(item.title); |
| 107 | + |
| 108 | + parser.parseToTree(item.input + "\n", function(tree, err) { |
| 109 | + if (err) { |
| 110 | + console.log('PARSE FAIL', err); |
| 111 | + } else { |
| 112 | + renderer.treeToHtml(tree, function(node, err) { |
| 113 | + if (err) { |
| 114 | + console.log('RENDER FAIL', err); |
| 115 | + } else { |
| 116 | + console.log(node.innerHTML + "\n"); |
| 117 | + } |
| 118 | + }); |
| 119 | + } |
| 120 | + }); |
| 121 | +} |
| 122 | + |
| 123 | +cases.forEach(function(item) { |
| 124 | + if (typeof item == 'object') { |
| 125 | + if (item.type == 'article') { |
| 126 | + processArticle(item); |
| 127 | + } else if (item.type == 'test') { |
| 128 | + processTest(item); |
| 129 | + } |
| 130 | + } |
| 131 | +}); |
Property changes on: trunk/extensions/ParserPlayground/tests/parserTests.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 132 | + native |
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.renderer.js |
— | — | @@ -197,3 +197,8 @@ |
198 | 198 | callback(null); // hmmmm |
199 | 199 | } |
200 | 200 | }; |
| 201 | + |
| 202 | + |
| 203 | +if (typeof module == "object") { |
| 204 | + module.exports.MWTreeRenderer = MWTreeRenderer; |
| 205 | +} |