UNPKG

apg-js-examples

Version:

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

164 lines (162 loc) 8.02 kB
/* ************************************************************************************* * copyright: Copyright (c) 2021 Lowell D. Thomas, all rights reserved * license: BSD-2-Clause (https://opensource.org/licenses/BSD-2-Clause) * ********************************************************************************* */ // This module briefly describes all of the arguments to the `apg-exp` constructor // and demonstrates in detail the four different flags available. // ``` // let ApgExp = require("apg-exp"); // let exp = new ApgExp(grammar, flags, nodeHits, treeDepth); // grammar - this can be either a string defining the // SABNF grammar or a pre-compiled grammar object. // - e.g. grammar = 'rule = "a" / "b"\n'; // (note: newline character is required // by the SABNF syntax) // - or grammar = new (require("/path/to/rule.js")(); // where rule.js was previously created // with the apg parser generator. // flags - any combination of g, y, u and d. // (note: if both g and y are specified, // y prevails) // nodeHits - limits the number of node hits (unit parser steps) // treeDepth - limits the maximum depth allowed of the parse tree // ``` // The flags available to the `exec()` function are described in more detail below. // (All flags are ignored by the `test()` function.) // <ul> // <li> // `g` - the `global` flag is used to match all occurrences of a pattern in a string. // This is used with repeated calls to the `exec()` function. // After each successful pattern match, the `lastIndex` variable is repositioned to the character just following the match. // After an unsuccessful match, `lastIndex` is reset to zero. // When used with the `replace()` function, all occurrences of the pattern are replaced with one call. // </li> // <li> // `y` - the `sticky` flag is described in the // <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp">MDN</a>) // documentation, but does not seem to be implemented in `node.js`. // With the `y` flag set, `lastIndex` acts as an anchor. The match is attempted at the index `lastIndex` only. // If a match is not found, `lastIndex` is set to 0 and the result is null. // If a match is found, it acts similarly to global mode in that `lastIndex` is repositioned to the next // character following the match. // Therefore, it can also be used with repeated calls to `exec()`, finding all *consecutive* phrases that exactly follow one another. // When used with the `replace()` function, all consecutive occurrences of the pattern are replaced with one call. // </li> // <li> // `u` - with the unicode flag set, all matched phrases in the `result` and `last match` objects are // returned as arrays of character code integers rather than JavaScript strings. // (The `replace()` and `split()` functions will throw an exception if called with the `u` flag set.) // </li> // <li> // `d` - the debug flag is used to turn on tracing, `apg`'s debugger. // The `apg` tracing object can be configured and displayed just // as with any other `apg` application to see exactly how the parser is behaving. // </li> // </ul> // // Some simple examples of using each of these flags follow. (function flagsEsample() { try { const apgJs = require('apg-js'); const ApgExp = apgJs.apgExp; const grammar = 'rule = "abc" / "xyz"\n'; let exp; let flags; let result; let str; // With no flags, `lastIndex` remains at 0 after a successful match and repeated calls simply find the same match. console.log(); console.log('The flags demonstration'); console.log(); console.log(` grammar: ${grammar}`); flags = ''; exp = new ApgExp(grammar, flags); str = '---abc---xyz---ABC---'; result = exp.exec(str); console.log(' : With no flags, lastIndex is never repositioned. The same phrase is found over and over.'); console.log(` flags: '${exp.flags}'`); console.log(` input: '${str}'`); console.log(`lastIndex: ${exp.lastIndex}: index: ${result.index}: result[0]: '${result[0]}'`); result = exp.exec(str); console.log(`lastIndex: ${exp.lastIndex}: index: ${result.index}: result[0]: '${result[0]}'`); result = exp.exec(str); console.log(`lastIndex: ${exp.lastIndex}: index: ${result.index}: result[0]: '${result[0]}'`); // With the global flag, `g`, repeated calls will find the next match. flags = 'g'; exp = new ApgExp(grammar, flags); console.log(); console.log(" : With the 'g' flag, lastIndex is repositioned. Each call finds the next phrase."); console.log(` flags: '${exp.flags}'`); console.log(` input: '${str}'`); const TRUE = true; while (TRUE) { result = exp.exec(str); if (result === null || result[0] === '') { console.log(`lastIndex: ${exp.lastIndex}: result: '${result}'`); break; } console.log(`lastIndex: ${exp.lastIndex}: index: ${result.index}: result[0]: '${result[0]}'`); } // With the 'sticky' flag, `y`, the patterns must be consecutive for repeated matching. flags = 'y'; exp = new ApgExp(grammar, flags); console.log(); console.log(" : With the 'y' flag, lastIndex is an anchor. The phrase must be found exactly at lastIndex."); console.log(` flags: '${exp.flags}'`); console.log(` input: '${str}'`); while (TRUE) { result = exp.exec(str); if (result === null || result[0] === '') { console.log(`lastIndex: ${exp.lastIndex}: result: '${result}'`); break; } console.log(`lastIndex: ${exp.lastIndex}: index: ${result.index}: result[0]: '${result[0]}'`); } str = 'abcxyzABC'; console.log(); console.log(" : With the 'y' flag, 'consecutive' phrases will be found with subsequent calls."); console.log(` flags: '${exp.flags}'`); console.log(` input: '${str}'`); while (TRUE) { result = exp.exec(str); if (result === null || result[0] === '') { console.log(`lastIndex: ${exp.lastIndex}: result: '${result}'`); break; } console.log(`lastIndex: ${exp.lastIndex}: index: ${result.index}: result[0]: '${result[0]}'`); } // With the unicode flag, `u`, the result is an array of character codes rather than a string. flags = 'ug'; exp = new ApgExp(grammar, flags); str = '---abc---xyz---ABC---'; console.log(); console.log(" : With the 'u' flag, phrases are arrays of character codes, not strings."); console.log(` flags: '${exp.flags}'`); console.log(` input: '${str}'`); while (TRUE) { result = exp.exec(str); if (result === null || result[0] === '') { console.log(`lastIndex: ${exp.lastIndex}: result: '${result}'`); break; } console.log(`lastIndex: ${exp.lastIndex}: index: ${result.index}: result[0]: '[${result[0]}]'`); } // With the debug flag, `d`, the trace object is available for inspection. // We will see in other examples how to configure and display the trace information. // For now, we just demonstrate that the trace object can be made available with the `d` flag. flags = 'd'; exp = new ApgExp(grammar, flags); console.log(); console.log(" : When the 'd' flag is set, the exp.trace object is available for use."); console.log(` flags: '${exp.flags}'`); console.log(`exp.trace: ${exp.trace}`); flags = ''; exp = new ApgExp(grammar, flags); console.log(); console.log(" : When the 'd' flag is not set, the exp.trace object is null."); console.log(` flags: '${exp.flags}'`); console.log(`exp.trace: ${exp.trace}`); } catch (e) { console.log(`EXCEPTION: ${e.message}`); } })();