falcor-path-syntax
Version:
Parser for Falcor Path Syntax
115 lines (89 loc) • 3.12 kB
JavaScript
var TokenTypes = require('./../TokenTypes');
var E = require('./../exceptions');
var idxE = E.indexer;
var range = require('./range');
var quote = require('./quote');
var routed = require('./routed');
/**
* The indexer is all the logic that happens in between
* the '[', opening bracket, and ']' closing bracket.
*/
module.exports = function indexer(tokenizer, openingToken, state, out) {
var token = tokenizer.next();
var done = false;
var allowedMaxLength = 1;
var routedIndexer = false;
// State variables
state.indexer = [];
while (!token.done) {
switch (token.type) {
case TokenTypes.token:
case TokenTypes.quote:
// ensures that token adders are properly delimited.
if (state.indexer.length === allowedMaxLength) {
E.throwError(idxE.requiresComma, tokenizer);
}
break;
}
switch (token.type) {
// Extended syntax case
case TokenTypes.openingBrace:
routedIndexer = true;
routed(tokenizer, token, state, out);
break;
case TokenTypes.token:
var t = +token.token;
if (isNaN(t)) {
E.throwError(idxE.needQuotes, tokenizer);
}
state.indexer[state.indexer.length] = t;
break;
// dotSeparators at the top level have no meaning
case TokenTypes.dotSeparator:
if (!state.indexer.length) {
E.throwError(idxE.leadingDot, tokenizer);
}
range(tokenizer, token, state, out);
break;
// Spaces do nothing.
case TokenTypes.space:
break;
case TokenTypes.closingBracket:
done = true;
break;
// The quotes require their own tree due to what can be in it.
case TokenTypes.quote:
quote(tokenizer, token, state, out);
break;
// Its time to decend the parse tree.
case TokenTypes.openingBracket:
E.throwError(idxE.nested, tokenizer);
break;
case TokenTypes.commaSeparator:
++allowedMaxLength;
break;
default:
E.throwError(E.unexpectedToken, tokenizer);
break;
}
// If done, leave loop
if (done) {
break;
}
// Keep cycling through the tokenizer.
token = tokenizer.next();
}
if (state.indexer.length === 0) {
E.throwError(idxE.empty, tokenizer);
}
if (state.indexer.length > 1 && routedIndexer) {
E.throwError(idxE.routedTokens, tokenizer);
}
// Remember, if an array of 1, keySets will be generated.
if (state.indexer.length === 1) {
state.indexer = state.indexer[0];
}
out[out.length] = state.indexer;
// Clean state.
state.indexer = undefined;
};