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

315 lines
No EOL
11 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 Parser_1 = require("../Parser");
var BNF;
(function (BNF) {
BNF.RULES = [
{
name: 'Grammar',
bnf: [['RULE_S*', '%Atomic*', 'EOF']]
},
{
name: '%Atomic',
bnf: [['Production', 'RULE_S*']],
fragment: true
},
{
name: 'Production',
bnf: [['NCName', 'RULE_S*', '"::="', 'RULE_WHITESPACE*', 'Choice', 'RULE_WHITESPACE*', 'RULE_EOL+', 'RULE_S*']]
},
{
name: 'NCName',
bnf: [[/[a-zA-Z][a-zA-Z_0-9]*/]]
},
{
name: 'Choice',
bnf: [['SequenceOrDifference', '%_Choice_1*']],
fragment: true
},
{
name: '%_Choice_1',
bnf: [['RULE_WHITESPACE*', '"|"', 'RULE_WHITESPACE*', '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*', '%Primary', 'PrimaryDecoration?']],
fragment: true
},
{
name: 'PrimaryDecoration',
bnf: [['"?"'], ['"*"'], ['"+"']]
},
{
name: 'DecorationName',
bnf: [['"ebnf://"', /[^\x5D#]+/]]
},
{
name: '%Primary',
bnf: [['NCName'], ['StringLiteral'], ['CharCode'], ['CharClass'], ['SubItem']],
fragment: true
},
{
name: 'SubItem',
bnf: [['"("', 'RULE_WHITESPACE*', 'Choice', 'RULE_WHITESPACE*', '")"']]
},
{
name: 'StringLiteral',
bnf: [[`'"'`, /[^"]*/, `'"'`], [`"'"`, /[^']*/, `"'"`]],
pinned: 1
},
{
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') {
if (preDecorationRE.test(name))
return '';
let subexpression = subExpressionRE.test(name);
if (subexpression) {
let decoration = decorationRE.exec(name);
let decorationText = decoration ? decoration[0] + ' ' : '';
let lonely = isLonelyRule(name, parser);
if (lonely)
return getBNFBody(name, parser) + decorationText;
return '(' + getBNFBody(name, parser) + ')' + decorationText;
}
return name;
}
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) {
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 = '';
switch (x.type) {
case 'SubItem':
let name = '%' + (parentName + subitems++);
createRule(tmpRules, x, name);
bnfSeq.push(preDecoration + name + decoration);
break;
case 'NCName':
case 'StringLiteral':
bnfSeq.push(preDecoration + x.text + decoration);
break;
case 'CharCode':
case 'CharClass':
if (decoration || preDecoration) {
let newRule = {
name: '%' + (parentName + subitems++),
bnf: [[convertRegex(x.text)]]
};
tmpRules.push(newRule);
bnfSeq.push(preDecoration + newRule.name + decoration);
}
else {
bnfSeq.push(convertRegex(x.text));
}
break;
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) {
let bnf = token.children.filter(x => x.type == 'SequenceOrDifference').map(s => getSubItems(tmpRules, s, name));
let rule = {
name,
bnf
};
let recover = null;
bnf.forEach(x => {
recover = recover || x['recover'];
delete x['recover'];
});
if (name.indexOf('%') == 0)
rule.fragment = true;
if (recover)
rule.recover = recover;
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 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);
});
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=W3CEBNF.js.map