UNPKG

apg-js-examples

Version:

Examples of using the suite of apg-js applications and libraries.

149 lines (144 loc) 5.69 kB
/* eslint-disable func-names */ /* eslint-disable new-cap */ /* ************************************************************************************* * copyright: Copyright (c) 2021 Lowell D. Thomas, all rights reserved * license: BSD-2-Clause (https://opensource.org/licenses/BSD-2-Clause) * ********************************************************************************* */ // This is the driver program for all examples. module.exports = function setup(doStats, doTrace) { const nodeUtil = require('node:util'); let html; const inspectOptions = { showHidden: true, depth: null, }; try { const { apgLib } = require('apg-js'); const writeHtml = require('../writeHtml'); const grammar = new (require('./phone-number'))(); const parser = new apgLib.parser(); const id = apgLib.ids; if (doStats) { parser.stats = new apgLib.stats(); } if (doTrace) { parser.trace = new apgLib.trace(); } // This is the required `UDT` callback function. // Rule name callback functions are optional, however // when `UDT`s are present in the grammar, // the parser will fail with an error message if all of the `UDT`s in the grammar // do not have callback functions defined for them. const UDToffice = function (result, chars, phraseIndex, data) { let matchFound = false; const TRUE = true; while (TRUE) { if (chars + phraseIndex + 3 <= chars.length) { /* not three digits left in the string */ break; } const dig1 = chars[phraseIndex]; const dig2 = chars[phraseIndex + 1]; const dig3 = chars[phraseIndex + 2]; if (dig1 < 50 || dig1 > 57) { /* first digit must be in range 2-9 */ break; } if (dig2 < 48 || dig2 > 57 || dig3 < 48 || dig3 > 57) { /* second & third digits must be in range 0-9 */ break; } if (dig2 === 49 && dig3 === 49) { /* if the second digit is "1" then the third digit cannot also be "1" */ throw new Error('UDT u_office: digits 2 and 3 cannot both be 1'); } matchFound = true; break; } if (matchFound === true) { result.state = id.MATCH; result.phraseLength = 3; if (data !== null) { data.u_office = apgLib.utils.charsToString(chars, phraseIndex, result.phraseLength); } } else { result.state = id.NOMATCH; result.phraseLength = 0; } }; // Define some rule name (`RNM`) callback functions. const phoneNumber = function (result, chars, phraseIndex, data) { if (result.state === id.MATCH) { if (Array.isArray(data) === false) { throw new Error("parser's user data must be an array"); } /* initialize the data array length to zero */ data.length = 0; } }; const areaCode = function (result, chars, phraseIndex, data) { if (result.state === id.MATCH) { /* capture the area code */ data['area-code'] = apgLib.utils.charsToString(chars, phraseIndex, result.phraseLength); } }; const subscriber = function (result, chars, phraseIndex, data) { if (result.state === id.MATCH) { /* capture the 4-digit subscriber number */ data.subscriber = apgLib.utils.charsToString(chars, phraseIndex, result.phraseLength); } }; parser.callbacks['phone-number'] = phoneNumber; parser.callbacks['area-code'] = areaCode; parser.callbacks.u_office = UDToffice; parser.callbacks.subscriber = subscriber; const inputString = '(555)234-5678'; const inputCharacterCodes = apgLib.utils.stringToChars(inputString); const startRule = 'phone-number'; const phoneParts = []; // Parse the phone number. console.log('the grammar:'); console.log(grammar.toString()); console.log('the input string:'); console.log(inputString); const result = parser.parse(grammar, startRule, inputCharacterCodes, phoneParts); console.log(); console.log("the parser's results"); console.dir(result, inspectOptions); if (result.success === false) { throw new Error(`input string: '${inputString}' : parse failed`); } // Display parsed phone number parts on the console. console.log(); console.log(`phone number: ${inputString}`); console.log(` area-code: ${phoneParts['area-code']}`); console.log(` u_office: ${phoneParts.u_office}`); console.log(` subscriber: ${phoneParts.subscriber}`); if (doStats) { /* If requested, display the stats in all orderings on a web page. */ html = ''; html += parser.stats.toHtml('ops', 'ops-only stats'); html += parser.stats.toHtml('index', 'rules ordered by index'); html += parser.stats.toHtml('alpha', 'rules ordered alphabetically'); html += parser.stats.toHtml('hits', 'rules ordered by hit count'); html = apgLib.utils.htmlToPage(html, 'udt-stats'); writeHtml(html, 'udt-stats'); } if (doTrace) { /* If requested, display the trace on a web page. */ html = parser.trace.toHtmlPage('ascii', 'udt trace'); writeHtml(html, 'udt-trace'); } } catch (e) { let msg = '\nEXCEPTION THROWN: \n'; if (e instanceof Error) { msg += `${e.name}: ${e.message}`; } else if (typeof e === 'string') { msg += e; } else { msg += nodeUtil.inspect(e, inspectOptions); } console.log(msg); throw e; } };