pbxproj
Version:
parse & stringify xcode pbxproj format
94 lines (74 loc) • 2.02 kB
JavaScript
'use strict';
/*
* Module dependencies
*/
var _ = require('lodash');
var util = require('util');
/*
* Stage of parsing process (parent constructor)
*/
var ParserStage = module.exports = function (ctx, data, cursor, line, back) {
this.data = data;
this.cursor = cursor || 0;
this.expected = [];
this.back = back || _.noop;
this.ctx = ctx;
this.line = line || 0;
};
/*
* Error formater
*/
ParserStage.prototype.error = function () {
throw new Error(
[util.format('[%d:%d]', this.line, this.cursor), ':']
.concat(_.toArray(arguments))
.join(' ')
);
};
/*
* ExpectedError formater
*/
ParserStage.prototype.expectedError = function (found) {
this.error('Expected :', this.expected.map(function(expect) {
return '\'' + expect.pattern + '\'';
}).join(' or '), 'found :', found);
};
/*
* Register a new expect rule : pattern + cycle callback
*/
ParserStage.prototype.expect = function (pattern, cycle) {
this.expected.push({pattern: pattern, cycle: cycle});
};
/*
* Check if next caracter match any expect rule
*/
ParserStage.prototype.matchNext = function () {
var stage = this;
if (this.cursor >= this.data.length) return;
return _.find(this.expected, function (expect) {
return stage.data[stage.cursor].match(expect.pattern);
});
};
/*
* Run one parsing cycle
*/
ParserStage.prototype.run = function () {
var car;
var nextStage;
var match = this.matchNext();
var cycle = !!match ? match.cycle : null;
if (this.cursor >= this.data.length && this.expected.length) {
this.expectedError('END');
} else if (this.cursor < this.data.length && !!match) {
car = this.data[this.cursor];
this.cursor++;
this.expected = [];
cycle(car);
} else if (this.data[this.cursor].match(/\s/)) {
this.cursor++;
this.run();
} else if (this.cursor < this.data.length && !match) {
this.expectedError(this.data[this.cursor]);
}
if (this.cursor < this.data.length && this.data[this.cursor] === '\n') this.line++;
};