botbook/node_modules/ebnf/dist/Grammars/Custom.js
Rodrigo Rodriguez 6ae15fe3e5 Updated.
2024-09-04 13:13:15 -03:00

413 lines
No EOL
15 KiB
JavaScript

"use strict";
// https://www.w3.org/TR/REC-xml/#NT-Name
// http://www.bottlecaps.de/rr/ui
Object.defineProperty(exports, "__esModule", { value: true });
// Grammar ::= Production*
// Production ::= NCName '::=' Choice
// NCName ::= [http://www.w3.org/TR/xml-names/#NT-NCName]
// Choice ::= SequenceOrDifference ( '|' SequenceOrDifference )*
// SequenceOrDifference ::= (Item ( '-' Item | Item* ))?
// Item ::= Primary ( '?' | '*' | '+' )?
// Primary ::= NCName | StringLiteral | CharCode | CharClass | '(' Choice ')'
// StringLiteral ::= '"' [^"]* '"' | "'" [^']* "'"
// CharCode ::= '#x' [0-9a-fA-F]+
// CharClass ::= '[' '^'? ( RULE_Char | CharCode | CharRange | CharCodeRange )+ ']'
// RULE_Char ::= [http://www.w3.org/TR/xml#NT-RULE_Char]
// CharRange ::= RULE_Char '-' ( RULE_Char - ']' )
// CharCodeRange ::= CharCode '-' CharCode
// RULE_WHITESPACE ::= RULE_S | Comment
// RULE_S ::= #x9 | #xA | #xD | #x20
// Comment ::= '/*' ( [^*] | '*'+ [^*/] )* '*'* '*/'
const TokenError_1 = require("../TokenError");
const Parser_1 = require("../Parser");
var BNF;
(function (BNF) {
BNF.RULES = [
{
name: 'Grammar',
bnf: [['RULE_S*', 'Attributes?', 'RULE_S*', '%Atomic*', 'EOF']]
},
{
name: '%Atomic',
bnf: [['Production', 'RULE_S*']],
fragment: true
},
{
name: 'Production',
bnf: [
[
'NCName',
'RULE_S*',
'"::="',
'RULE_WHITESPACE*',
'%Choice',
'RULE_WHITESPACE*',
'Attributes?',
'RULE_EOL+',
'RULE_S*'
]
]
},
{
name: 'NCName',
bnf: [[/[a-zA-Z][a-zA-Z_0-9]*/]]
},
{
name: 'Attributes',
bnf: [['"{"', 'Attribute', '%Attributes*', 'RULE_S*', '"}"']]
},
{
name: '%Attributes',
bnf: [['RULE_S*', '","', 'Attribute']],
fragment: true
},
{
name: 'Attribute',
bnf: [['RULE_S*', 'NCName', 'RULE_WHITESPACE*', '"="', 'RULE_WHITESPACE*', 'AttributeValue']]
},
{
name: 'AttributeValue',
bnf: [['NCName'], [/[1-9][0-9]*/]]
},
{
name: '%Choice',
bnf: [['SequenceOrDifference', '%_Choice_1*']],
fragment: true
},
{
name: '%_Choice_1',
bnf: [['RULE_S*', '"|"', 'RULE_S*', 'SequenceOrDifference']],
fragment: true
},
{
name: 'SequenceOrDifference',
bnf: [['%Item', 'RULE_WHITESPACE*', '%_Item_1?']]
},
{
name: '%_Item_1',
bnf: [['Minus', '%Item'], ['%Item*']],
fragment: true
},
{
name: 'Minus',
bnf: [['"-"']]
},
{
name: '%Item',
bnf: [['RULE_WHITESPACE*', 'PrimaryPreDecoration?', '%Primary', 'PrimaryDecoration?']],
fragment: true
},
{
name: 'PrimaryDecoration',
bnf: [['"?"'], ['"*"'], ['"+"']]
},
{
name: 'PrimaryPreDecoration',
bnf: [['"&"'], ['"!"'], ['"~"']]
},
{
name: '%Primary',
bnf: [['NCName'], ['StringLiteral'], ['CharCode'], ['CharClass'], ['SubItem']],
fragment: true
},
{
name: 'SubItem',
bnf: [['"("', 'RULE_S*', '%Choice', 'RULE_S*', '")"']]
},
{
name: 'StringLiteral',
bnf: [[`'"'`, /[^"]*/, `'"'`], [`"'"`, /[^']*/, `"'"`]]
},
{
name: 'CharCode',
bnf: [['"#x"', /[0-9a-zA-Z]+/]]
},
{
name: 'CharClass',
bnf: [["'['", "'^'?", '%RULE_CharClass_1+', '"]"']]
},
{
name: '%RULE_CharClass_1',
bnf: [['CharCodeRange'], ['CharRange'], ['CharCode'], ['RULE_Char']],
fragment: true
},
{
name: 'RULE_Char',
bnf: [[/\x09/], [/\x0A/], [/\x0D/], [/[\x20-\x5c]/], [/[\x5e-\uD7FF]/], [/[\uE000-\uFFFD]/]]
},
{
name: 'CharRange',
bnf: [['RULE_Char', '"-"', 'RULE_Char']]
},
{
name: 'CharCodeRange',
bnf: [['CharCode', '"-"', 'CharCode']]
},
{
name: 'RULE_WHITESPACE',
bnf: [['%RULE_WHITESPACE_CHAR*'], ['Comment', 'RULE_WHITESPACE*']]
},
{
name: 'RULE_S',
bnf: [['RULE_WHITESPACE', 'RULE_S*'], ['RULE_EOL', 'RULE_S*']]
},
{
name: '%RULE_WHITESPACE_CHAR',
bnf: [[/\x09/], [/\x20/]],
fragment: true
},
{
name: 'Comment',
bnf: [['"/*"', '%RULE_Comment_Body*', '"*/"']]
},
{
name: '%RULE_Comment_Body',
bnf: [[/[^*]/], ['"*"+', /[^/]*/]],
fragment: true
},
{
name: 'RULE_EOL',
bnf: [[/\x0D/, /\x0A/], [/\x0A/], [/\x0D/]]
},
{
name: 'Link',
bnf: [["'['", 'Url', "']'"]]
},
{
name: 'Url',
bnf: [[/[^\x5D:/?#]/, '"://"', /[^\x5D#]+/, '%Url1?']]
},
{
name: '%Url1',
bnf: [['"#"', 'NCName']],
fragment: true
}
];
BNF.defaultParser = new Parser_1.Parser(BNF.RULES, { debug: false });
const preDecorationRE = /^(!|&)/;
const decorationRE = /(\?|\+|\*)$/;
const subExpressionRE = /^%/;
function getBNFRule(name, parser) {
if (typeof name == 'string') {
let decoration = decorationRE.exec(name);
let preDecoration = preDecorationRE.exec(name);
let preDecorationText = preDecoration ? preDecoration[0] : '';
let decorationText = decoration ? decoration[0] + ' ' : '';
let subexpression = subExpressionRE.test(name);
if (subexpression) {
let lonely = isLonelyRule(name, parser);
if (lonely)
return preDecorationText + getBNFBody(name, parser) + decorationText;
return preDecorationText + '(' + getBNFBody(name, parser) + ')' + decorationText;
}
return name.replace(preDecorationRE, preDecorationText);
}
else {
return name.source
.replace(/\\(?:x|u)([a-zA-Z0-9]+)/g, '#x$1')
.replace(/\[\\(?:x|u)([a-zA-Z0-9]+)-\\(?:x|u)([a-zA-Z0-9]+)\]/g, '[#x$1-#x$2]');
}
}
/// Returns true if the rule is a string literal or regular expression without a descendant tree
function isLonelyRule(name, parser) {
let rule = Parser_1.findRuleByName(name, parser);
return (rule &&
rule.bnf.length == 1 &&
rule.bnf[0].length == 1 &&
(rule.bnf[0][0] instanceof RegExp || rule.bnf[0][0][0] == '"' || rule.bnf[0][0][0] == "'"));
}
function getBNFChoice(rules, parser) {
return rules.map(x => getBNFRule(x, parser)).join(' ');
}
function getBNFBody(name, parser) {
let rule = Parser_1.findRuleByName(name, parser);
if (rule)
return rule.bnf.map(x => getBNFChoice(x, parser)).join(' | ');
return 'RULE_NOT_FOUND {' + name + '}';
}
function emit(parser) {
let acumulator = [];
parser.grammarRules.forEach(l => {
if (!/^%/.test(l.name)) {
let recover = l.recover ? ' { recoverUntil=' + l.recover + ' }' : '';
acumulator.push(l.name + ' ::= ' + getBNFBody(l.name, parser) + recover);
}
});
return acumulator.join('\n');
}
BNF.emit = emit;
let subitems = 0;
function restar(total, resta) {
console.log('reberia restar ' + resta + ' a ' + total);
throw new Error('Difference not supported yet');
}
function convertRegex(txt) {
return new RegExp(txt
.replace(/#x([a-zA-Z0-9]{4})/g, '\\u$1')
.replace(/#x([a-zA-Z0-9]{3})/g, '\\u0$1')
.replace(/#x([a-zA-Z0-9]{2})/g, '\\x$1')
.replace(/#x([a-zA-Z0-9]{1})/g, '\\x0$1'));
}
function getSubItems(tmpRules, seq, parentName, parentAttributes) {
let anterior = null;
let bnfSeq = [];
seq.children.forEach((x, i) => {
if (x.type == 'Minus') {
restar(anterior, x);
}
else {
}
let decoration = seq.children[i + 1];
decoration = (decoration && decoration.type == 'PrimaryDecoration' && decoration.text) || '';
let preDecoration = '';
if (anterior && anterior.type == 'PrimaryPreDecoration') {
preDecoration = anterior.text;
}
let pinned = preDecoration == '~' ? 1 : undefined;
if (pinned) {
preDecoration = '';
}
switch (x.type) {
case 'SubItem':
let name = '%' + (parentName + subitems++);
createRule(tmpRules, x, name, parentAttributes);
bnfSeq.push(preDecoration + name + decoration);
break;
case 'NCName':
bnfSeq.push(preDecoration + x.text + decoration);
break;
case 'StringLiteral':
if (decoration || preDecoration || !/^['"/()a-zA-Z0-9&_.:=,+*\-\^\\]+$/.test(x.text)) {
bnfSeq.push(preDecoration + x.text + decoration);
}
else {
for (const c of x.text.slice(1, -1)) {
if (parentAttributes && parentAttributes["ignoreCase"] == "true" && /[a-zA-Z]/.test(c)) {
bnfSeq.push(new RegExp("[" + c.toUpperCase() + c.toLowerCase() + "]"));
}
else {
bnfSeq.push(new RegExp(Parser_1.escapeRegExp(c)));
}
}
}
break;
case 'CharCode':
case 'CharClass':
if (decoration || preDecoration) {
let newRule = {
name: '%' + (parentName + subitems++),
bnf: [[convertRegex(x.text)]],
pinned
};
tmpRules.push(newRule);
bnfSeq.push(preDecoration + newRule.name + decoration);
}
else {
bnfSeq.push(convertRegex(x.text));
}
break;
case 'PrimaryPreDecoration':
case 'PrimaryDecoration':
break;
default:
throw new Error(' HOW SHOULD I PARSE THIS? ' + x.type + ' -> ' + JSON.stringify(x.text));
}
anterior = x;
});
return bnfSeq;
}
function createRule(tmpRules, token, name, parentAttributes = undefined) {
let attrNode = token.children.filter(x => x.type == 'Attributes')[0];
let attributes = {};
if (attrNode) {
attrNode.children.forEach(x => {
let name = x.children.filter(x => x.type == 'NCName')[0].text;
if (name in attributes) {
throw new TokenError_1.TokenError('Duplicated attribute ' + name, x);
}
else {
attributes[name] = x.children.filter(x => x.type == 'AttributeValue')[0].text;
}
});
}
let bnf = token.children.filter(x => x.type == 'SequenceOrDifference').map(s => getSubItems(tmpRules, s, name, parentAttributes ? parentAttributes : attributes));
let rule = {
name,
bnf
};
if (name.indexOf('%') == 0)
rule.fragment = true;
if (attributes['recoverUntil']) {
rule.recover = attributes['recoverUntil'];
if (rule.bnf.length > 1)
throw new TokenError_1.TokenError('only one-option productions are suitable for error recovering', token);
}
if ('pin' in attributes) {
let num = parseInt(attributes['pin']);
if (!isNaN(num)) {
rule.pinned = num;
}
if (rule.bnf.length > 1)
throw new TokenError_1.TokenError('only one-option productions are suitable for pinning', token);
}
if ('ws' in attributes) {
rule.implicitWs = attributes['ws'] != 'explicit';
}
else {
rule.implicitWs = null;
}
rule.fragment = rule.fragment || attributes['fragment'] == 'true';
rule.simplifyWhenOneChildren = attributes['simplifyWhenOneChildren'] == 'true';
tmpRules.push(rule);
}
function getRules(source, parser = BNF.defaultParser) {
let ast = parser.getAST(source);
if (!ast)
throw new Error('Could not parse ' + source);
if (ast.errors && ast.errors.length) {
throw ast.errors[0];
}
let implicitWs = null;
let attrNode = ast.children.filter(x => x.type == 'Attributes')[0];
let attributes = {};
if (attrNode) {
attrNode.children.forEach(x => {
let name = x.children.filter(x => x.type == 'NCName')[0].text;
if (name in attributes) {
throw new TokenError_1.TokenError('Duplicated attribute ' + name, x);
}
else {
attributes[name] = x.children.filter(x => x.type == 'AttributeValue')[0].text;
}
});
}
implicitWs = attributes['ws'] == 'implicit';
let tmpRules = [];
ast.children.filter(x => x.type == 'Production').map((x) => {
let name = x.children.filter(x => x.type == 'NCName')[0].text;
createRule(tmpRules, x, name);
});
tmpRules.forEach(rule => {
if (rule.implicitWs === null)
rule.implicitWs = implicitWs;
});
return tmpRules;
}
BNF.getRules = getRules;
function Transform(source, subParser = BNF.defaultParser) {
return getRules(source.join(''), subParser);
}
BNF.Transform = Transform;
class Parser extends Parser_1.Parser {
constructor(source, options) {
const subParser = options && options.debugRulesParser === true ? new Parser_1.Parser(BNF.RULES, { debug: true }) : BNF.defaultParser;
super(getRules(source, subParser), options);
}
emitSource() {
return emit(this);
}
}
BNF.Parser = Parser;
})(BNF || (BNF = {}));
exports.default = BNF;
//# sourceMappingURL=Custom.js.map