diff --git a/packages/bbob-parser/src/Token.js b/packages/bbob-parser/src/Token.js index 8ae9ddf..6c5159c 100644 --- a/packages/bbob-parser/src/Token.js +++ b/packages/bbob-parser/src/Token.js @@ -17,19 +17,70 @@ const TOKEN_TYPE_ATTR_VALUE = 'attr-value'; const TOKEN_TYPE_SPACE = 'space'; const TOKEN_TYPE_NEW_LINE = 'new-line'; -const getTokenValue = (token) => token[TOKEN_VALUE_ID]; -const getTokenLine = (token) => token[TOKEN_LINE_ID]; -const getTokenColumn = (token) => token[TOKEN_COLUMN_ID]; +/** + * @param {Token} token + * @returns {string} + */ +const getTokenValue = (token) => { + if (token && typeof token[TOKEN_VALUE_ID] !== 'undefined') { + return token[TOKEN_VALUE_ID]; + } -const isTextToken = (token) => token[TOKEN_TYPE_ID] === TOKEN_TYPE_SPACE - || token[TOKEN_TYPE_ID] === TOKEN_TYPE_NEW_LINE - || token[TOKEN_TYPE_ID] === TOKEN_TYPE_WORD; + return ''; +}; +/** + * @param {Token}token + * @returns {number} + */ +const getTokenLine = (token) => (token && token[TOKEN_LINE_ID]) || 0; +const getTokenColumn = (token) => (token && token[TOKEN_COLUMN_ID]) || 0; -const isTagToken = (token) => token[TOKEN_TYPE_ID] === TOKEN_TYPE_TAG; +/** + * @param {Token} token + * @returns {boolean} + */ +const isTextToken = (token) => { + if (token && typeof token[TOKEN_TYPE_ID] !== 'undefined') { + return token[TOKEN_TYPE_ID] === TOKEN_TYPE_SPACE + || token[TOKEN_TYPE_ID] === TOKEN_TYPE_NEW_LINE + || token[TOKEN_TYPE_ID] === TOKEN_TYPE_WORD; + } + + return false; +}; + +/** + * @param {Token} token + * @returns {boolean} + */ +const isTagToken = (token) => { + if (token && typeof token[TOKEN_TYPE_ID] !== 'undefined') { + return token[TOKEN_TYPE_ID] === TOKEN_TYPE_TAG; + } + + return false; +}; const isTagEnd = (token) => getTokenValue(token).charCodeAt(0) === SLASH.charCodeAt(0); const isTagStart = (token) => !isTagEnd(token); -const isAttrNameToken = (token) => token[TOKEN_TYPE_ID] === TOKEN_TYPE_ATTR_NAME; -const isAttrValueToken = (token) => token[TOKEN_TYPE_ID] === TOKEN_TYPE_ATTR_VALUE; +const isAttrNameToken = (token) => { + if (token && typeof token[TOKEN_TYPE_ID] !== 'undefined') { + return token[TOKEN_TYPE_ID] === TOKEN_TYPE_ATTR_NAME; + } + + return false; +}; + +/** + * @param {Token} token + * @returns {boolean} + */ +const isAttrValueToken = (token) => { + if (token && typeof token[TOKEN_TYPE_ID] !== 'undefined') { + return token[TOKEN_TYPE_ID] === TOKEN_TYPE_ATTR_VALUE; + } + + return false; +}; const getTagName = (token) => { const value = getTokenValue(token); diff --git a/packages/bbob-parser/src/parse.js b/packages/bbob-parser/src/parse.js index 93d9283..2bb697f 100644 --- a/packages/bbob-parser/src/parse.js +++ b/packages/bbob-parser/src/parse.js @@ -77,7 +77,11 @@ const parse = (input, opts = {}) => { const getNodes = () => { const lastNestedNode = nestedNodes.getLast(); - return lastNestedNode ? lastNestedNode.content : nodes.toArray(); + if (lastNestedNode && Array.isArray(lastNestedNode.content)) { + return lastNestedNode.content; + } + + return nodes.toArray(); }; /** @@ -85,7 +89,11 @@ const parse = (input, opts = {}) => { * @param {TagNode} tag */ const appendNodes = (tag) => { - getNodes().push(tag); + const items = getNodes(); + + if (Array.isArray(items)) { + items.push(tag); + } }; /** diff --git a/packages/bbob-parser/src/utils.js b/packages/bbob-parser/src/utils.js index 7d00d0b..b6d11df 100644 --- a/packages/bbob-parser/src/utils.js +++ b/packages/bbob-parser/src/utils.js @@ -57,8 +57,22 @@ export const createCharGrabber = (source, options) => { return source.substr(start, cursor.pos - start); }, - getNext: () => source[cursor.pos + 1], - getPrev: () => source[cursor.pos - 1], + getNext: () => { + const nextPos = cursor.pos + 1; + + if (nextPos <= (source.length - 1)) { + return source[nextPos]; + } + return null; + }, + getPrev: () => { + const prevPos = cursor.pos - 1; + + if (typeof source[prevPos] !== 'undefined') { + return source[prevPos]; + } + return null; + }, getCurr, getRest, /** @@ -127,7 +141,13 @@ export const createList = (values = []) => { /** * @callback getLastCb */ - const getLast = () => (nodes.length ? nodes[nodes.length - 1] : null); + const getLast = () => { + if (Array.isArray(nodes) && nodes.length > 0 && typeof nodes[nodes.length - 1] !== 'undefined') { + return nodes[nodes.length - 1]; + } + + return null; + }; /** * @callback flushLastCb * @return {*}