@bacons/xcode
Version:
pbxproj parser
120 lines • 4.65 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = exports.BaseVisitor = exports.PbxprojParser = exports.CommentCstParser = void 0;
const chevrotain_1 = require("./chevrotain");
const identifiers_1 = require("./identifiers");
const lexer_1 = require("./lexer");
class CommentCstParser extends chevrotain_1.CstParser {
RULE(name, implementation, config) {
return super.RULE(name, () => {
const start = this.LA(1).startOffset;
const ruleResult = implementation();
const end = this.LA(0);
if (ruleResult !== undefined) {
// @ts-ignore
ruleResult.position = {
start: start,
end: end,
};
}
return ruleResult;
}, config);
}
LA(howMuch) {
// Skip Comments during regular parsing as we wish to auto-magically insert them
// into our CST
while ((0, chevrotain_1.tokenMatcher)(super.LA(howMuch), identifiers_1.Comment)) {
// @ts-expect-error
super.consumeToken();
}
return super.LA(howMuch);
}
cstPostTerminal(key, consumedToken) {
// @ts-expect-error
super.cstPostTerminal(key, consumedToken);
let lookBehindIdx = -1;
let prevToken = super.LA(lookBehindIdx);
// After every Token (terminal) is successfully consumed
// We will add all the comment that appeared before it to the CST (Parse Tree)
while ((0, chevrotain_1.tokenMatcher)(prevToken, identifiers_1.Comment)) {
// @ts-expect-error
super.cstPostTerminal(identifiers_1.Comment.name, prevToken);
lookBehindIdx--;
prevToken = super.LA(lookBehindIdx);
}
}
}
exports.CommentCstParser = CommentCstParser;
class PbxprojParser extends CommentCstParser {
constructor() {
super(lexer_1.tokens, {
recoveryEnabled: false,
});
this.head = this.RULE("head", () => {
this.OR([
{ ALT: () => this.SUBRULE(this.array) },
{ ALT: () => this.SUBRULE(this.object) },
]);
});
this.array = this.RULE("array", () => {
this.CONSUME(identifiers_1.ArrayStart);
this.OPTION(() => {
this.MANY(() => {
this.SUBRULE(this.value);
this.OPTION2(() => this.CONSUME(identifiers_1.Separator));
});
});
this.CONSUME(identifiers_1.ArrayEnd);
});
this.object = this.RULE("object", () => {
this.CONSUME(identifiers_1.ObjectStart);
this.OPTION(() => {
this.MANY(() => {
this.SUBRULE(this.objectItem);
});
});
this.CONSUME(identifiers_1.ObjectEnd);
});
this.objectItem = this.RULE("objectItem", () => {
this.SUBRULE(this.identifier);
this.CONSUME(identifiers_1.Colon);
this.SUBRULE(this.value);
this.CONSUME(identifiers_1.Terminator);
});
this.identifier = this.RULE("identifier", () => {
this.OR([
{ ALT: () => this.CONSUME(identifiers_1.QuotedString) },
{ ALT: () => this.CONSUME(identifiers_1.StringLiteral) },
]);
});
this.value = this.RULE("value", () => {
this.OR([
{ ALT: () => this.SUBRULE(this.object) },
{ ALT: () => this.SUBRULE(this.array) },
{ ALT: () => this.CONSUME(identifiers_1.DataLiteral) },
{ ALT: () => this.SUBRULE(this.identifier) },
]);
});
// very important to call this after all the rules have been setup.
// otherwise the parser may not work correctly as it will lack information
// derived from the self analysis.
this.performSelfAnalysis();
}
}
exports.PbxprojParser = PbxprojParser;
const parser = new PbxprojParser();
exports.BaseVisitor = parser.getBaseCstVisitorConstructorWithDefaults();
function parse(text) {
const lexingResult = lexer_1.lexer.tokenize(text);
if (lexingResult.errors.length) {
throw new Error(`Parsing errors: ${lexingResult.errors[0].message}`);
}
parser.input = lexingResult.tokens;
const parsingResult = parser.head();
if (parser.errors.length) {
throw new Error(`Parsing errors: ${parser.errors[0].message}`);
}
return parsingResult;
}
exports.parse = parse;
//# sourceMappingURL=parser.js.map