UNPKG

parser-combinator

Version:
436 lines (374 loc) 14.2 kB
import X from '../../../lib/standard/extractor/extractor-bundle'; import {F, C} from '../../../lib/parsec/index'; import stream from '../../../lib/stream/index'; export default { setUp: function(done) { done(); }, 'test spaces': function(test) { const line = stream.ofString(' this starts with 4 spaces'); const x = new X(); const combinator = x.spaces().thenLeft(F.any.rep()); const value = combinator.parse(line).value; test.equals(value.length, 4); test.done(); }, 'test spaces and line feed': function(test) { const line = stream.ofString(' this \n contains line feed'); const x = new X(); const combinator = x .spaces() .then(x.word()) .thenRight(x.spaces()) .thenLeft(F.any); const value = combinator.parse(line).value; test.equals(value.length, 3); test.done(); }, 'test spaces, tabs and line feed': function(test) { const line = stream.ofString(' this \n \t contains line feed'); const x = new X(); const combinator = x .spaces() .then(x.word()) .thenRight(x.spaces()) .thenLeft(F.any); const value = combinator.parse(line).value; test.equals(value.length, 5); test.done(); }, 'test numbers': function(test) { const line = stream.ofString('98'); const x = new X(); const combinator = x.number(); const value = combinator.parse(line).value; test.ok(value === 98); test.done(); }, 'test digits': function(test) { const line = stream.ofString('98'); const x = new X(); const combinator = x.digits(); const value = combinator.parse(line).value; test.ok(value === '98'); test.done(); }, 'test single word': function(test) { let line = stream.ofString('Parsec-'); const x = new X(); const combinator = x.word().thenLeft(C.char('-')); const value = combinator.parse(line).value; test.ok(value === 'Parsec'); test.done(); }, 'test single word hexadecimal': function(test) { let line = stream.ofString('10FF-hexadecimal'); const hexadecimal = C.charIn('0123456789ABCDEF'); const x = new X({letter: hexadecimal}); const combinator = x .word() .map(x => parseInt(x, 16)) .thenLeft(C.char('-')) .thenLeft(C.string('hexadecimal')); const value = combinator.parse(line).value; test.equals(value, 4351); test.done(); }, 'single word with bad letters should fail': function(test) { let line = stream.ofString('classicWord-notHexadecimal'); const hexadecimal = C.charIn('0123456789ABCDEF'); const x = new X({letter: hexadecimal}); const combinator = x .word() .map(x => parseInt(x, 16)) .thenLeft(C.char('-')) .thenLeft(C.string('notHexadecimal')); const accepted = combinator.parse(line).isAccepted(); test.ok(!accepted); test.done(); }, 'test words': function(test) { let line = stream.ofString( 'The James Bond series, by writer Ian Fleming' ); const x = new X(); const combinator = x.words(); const value = combinator.parse(line).value; test.ok(value[1] === ' '); test.ok(_includes(value, 'Bond')); test.done(); }, 'test stringIn': function(test) { let line = stream.ofString('James Bond'); const x = new X(); const combinator = x.stringIn(['The', 'James', 'Bond', 'series']); const value = combinator.parse(line).value; test.ok(typeof value === 'string'); test.ok(value === 'James'); test.done(); }, 'test stringIn one string sidecase': function(test) { let line = stream.ofString('James'); const x = new X(); const combinator = x.stringIn(['James']); const value = combinator.parse(line).value; test.ok(typeof value === 'string'); test.ok(value === 'James'); test.done(); }, 'test stringIn empty sidecase': function(test) { let line = stream.ofString('James'); const x = new X(); const combinator = x.stringIn([]).then(F.eos); const parsing = combinator.parse(line); test.ok(!parsing.isAccepted()); test.done(); }, 'test wordsIn': function(test) { let line = stream.ofString('James Bond by Ian Fleming'); const x = new X(); const combinator = x.wordsIn( ['James', 'Bond', 'by', 'Ian', 'Fleming'], true ); const value = combinator.parse(line).value; test.ok(value.length === 9); test.ok(_includes(value, 'James')); test.ok(_includes(value, 'Bond')); test.ok(_includes(value, 'Fleming')); test.done(); }, 'test wordsIn without keeping spaces': function(test) { let line = stream.ofString('James Bond by Ian Fleming'); const x = new X(); const combinator = x.wordsIn( ['James', 'Bond', 'by', 'Ian', 'Fleming'], false ); const value = combinator.parse(line).value; test.ok(value.length === 5); test.ok(_includes(value, 'James')); test.ok(_includes(value, 'Bond')); test.ok(_includes(value, 'Fleming')); test.done(); }, 'test wordsIn keeping spaces with alt spaces': function(test) { let line = stream.ofString('James%Bond%by Ian=Fleming'); const x = new X({moreSeparators: '%='}); const combinator = x.wordsIn( ['James', 'Bond', 'by', 'Ian', 'Fleming'], false ); const value = combinator.parse(line).value; test.ok(value.length === 5); test.ok(_includes(value, 'James')); test.ok(_includes(value, 'Bond')); test.ok(_includes(value, 'Fleming')); test.done(); }, 'test wordsIn with custom spaces': function(test) { const str = 'JamesSPACEBondSPACEbySPACEIanSPACEFlemingSPACESPACE'; let line = stream.ofString(str); const x = new X({wordSeparators: C.string('SPACE')}); const combinator = x.wordsIn( ['James', 'Bond', 'by', 'Ian', 'Fleming'], false ); const value = combinator.parse(line).value; test.ok(value.length === 5); test.ok(_includes(value, 'James')); test.ok(_includes(value, 'Bond')); test.ok(_includes(value, 'Fleming')); test.done(); }, 'test wordsIn with both custom spaces and more Sep': function(test) { const str = 'James=BondSPACEbySPACEIanSPACEFlemingSPACESPACE'; let line = stream.ofString(str); let found = false; const original = console.warn; console.warn = () => { found = true; }; const x = new X({ wordSeparators: C.string('SPACE'), moreSeparators: '%=', }); const combinator = x.wordsIn( ['James=Bond', 'by', 'Ian', 'Fleming'], false ); const value = combinator.parse(line).value; test.ok(found); test.ok(value.length === 4); test.ok(_includes(value, 'James=Bond')); test.ok(_includes(value, 'Fleming')); console.warn = original; test.done(); }, 'test wordsUntil': function(test) { const line = stream.ofString('I write until James appears'); const x = new X(); const combinator = x.wordsUntil(C.string('James')).thenLeft(F.any); const value = combinator.parse(line).value; test.equals(value, 'I write until '); test.done(); }, 'test wordsUntil Not found': function(test) { const line = stream.ofString('I write until James appears'); const x = new X(); const combinator = x .wordsUntil(C.string('Indiana')) .then(C.string('I')) .thenLeft(F.any); const accepted = combinator.parse(line).isAccepted(); test.ok(!accepted); test.done(); }, 'test wordsUntil found with more parsers': function(test) { const line = stream.ofString('I write until James Bond appears'); const x = new X(); const combinator = x .wordsUntil(C.string('James')) .thenLeft(C.string('James Bond')) .thenLeft(F.any); const value = combinator.parse(line).value; test.equals(value, 'I write until '); test.done(); }, 'test wordsUntil found with failing parser': function(test) { const line = stream.ofString('I write until James Bond appears'); const x = new X(); const combinator = x .wordsUntil(C.string('James')) .thenLeft(C.string('Indiana jones')) .thenLeft(F.any); const accepted = combinator.parse(line).isAccepted(); test.ok(!accepted); test.done(); }, 'test first': function(test) { const line = stream.ofString("Hello 'World'"); const x = new X({wordSeparators: C.charIn(" '")}); const helloParser = x.words().map(x.first); const value = helloParser.parse(line).value; test.equals(value, 'Hello'); test.done(); }, 'test last': function(test) { const line = stream.ofString("Hello 'World'"); const x = new X({moreSeparators: "'"}); const helloParser = x.words(false).map(x.last); const value = helloParser.parse(line).value; test.equals(value, 'World'); test.done(); }, 'test wordsUntilFast string': function(test) { const line = stream.ofString('soXYZso'); const x = new X(); const combinator = x.wordsUntil('XYZ'); const parser = combinator.parse(line); const value = parser.value; const offset = parser.offset; test.equals(value, 'so'); test.equals(offset, 2); test.done(); }, 'test wordsUntilFast string with continuation': function(test) { const document = 'start-detect-XYZ-continues'; const line = stream.ofString(document); const start = C.string('start-'); const x = new X(); const combinator = start.thenRight( x.wordsUntil('XYZ').thenLeft(C.string('XYZ-continues')) ); const parser = combinator.parse(line); const value = parser.value; const offset = parser.offset; test.equals(value, 'detect-'); test.equals(offset, document.length); test.done(); }, 'test wordsUntilFast array of string with continuation': function(test) { const document = 'start-detect-XYZ-continues'; const line = stream.ofString(document); const start = C.string('start-'); const x = new X(); const combinator = start.thenRight( x .wordsUntil(['ABC', 'ZE', 'XYZ']) .thenLeft(C.string('XYZ-continues')) ); const parser = combinator.parse(line); const value = parser.value; const offset = parser.offset; test.equals(value, 'detect-'); test.equals(offset, document.length); test.done(); }, 'test wordsUntilFast string fails': function(test) { const document = 'start-detect-XYZ-continues'; const line = stream.ofString(document); const start = C.string('start-'); const x = new X(); const combinator = start.thenRight( x.wordsUntil('EEE').thenLeft(C.string('XYZ-continues')) ); const parsing = combinator.parse(line); test.ok(!parsing.isAccepted()); test.done(); }, 'test wordsUntilFast array of string fails': function(test) { const document = 'start-detect-XYZ-continues'; const line = stream.ofString(document); const start = C.string('start-'); const x = new X(); const combinator = start.thenRight( x .wordsUntil(['ABC', 'ZE', 'EEE']) .thenLeft(C.string('XYZ-continues')) ); const parsing = combinator.parse(line); test.ok(!parsing.isAccepted()); test.done(); }, 'test wordsUntilFast fails if array stream': function(test) { const document = ['More', 'XYZ']; const line = stream.ofArray(document); const x = new X(); const combinator = x.wordsUntil(['ABC', 'ZE', 'XYZ']); let found = false; try { const parsing = combinator.parse(line); } catch (e) { if (e === 'Input source must be a String') { found = true; } } test.ok(found); test.done(); }, 'test wordsUntilFastString fails if array stream': function(test) { const document = ['More', 'XYZ']; const line = stream.ofArray(document); const x = new X(); const combinator = x.wordsUntil('XYZ'); let found = false; try { const parsing = combinator.parse(line); } catch (e) { if (e === 'Input source must be a String') { found = true; } } test.ok(found); test.done(); }, }; function _includes(array, value) { for (let i = 0; i < array.length; i++) { if (array[i] === value) { return true; } } return false; }