Skip to content

Commit

Permalink
Merge pull request #1 from nobitlost/dev_CSE-332
Browse files Browse the repository at this point in the history
Fixed nested curly braces parsing
  • Loading branch information
sergey-nbl authored Apr 10, 2017
2 parents 0802f99 + ff97c3f commit 2e7717d
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 4 deletions.
51 changes: 51 additions & 0 deletions spec/AstParser/basic.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,55 @@ describe('AstParser', () => {
}
]);
});

it('should parse enclosed curly brackets', () => {
const res = p.parse
(`@macro set(val)
local var1 = @{val};
@end
@{set('{}')}
`);
//console.log(JSON.stringify(res, null, ' '));

expect(res).toEqual([
{
"_line": 1,
"type": "macro",
"declaration": "set(val)",
"body": [
{
"_line": 2,
"type": "output",
"value": "local var1 = ",
"computed": true
},
{
"_line": 2,
"type": "output",
"value": "val",
"computed": false
},
{
"_line": 2,
"type": "output",
"value": ";\n",
"computed": true
}
]
},
{
"_line": 4,
"type": "output",
"value": "set('{}')",
"computed": false
},
{
"_line": 4,
"type": "output",
"value": "\n",
"computed": true
}
]);
});

});
51 changes: 47 additions & 4 deletions src/AstParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

'use strict';

const jsep = require('jsep');

// instruction types
const INSTRUCTIONS = require('./Machine').INSTRUCTIONS;

Expand Down Expand Up @@ -57,6 +59,10 @@ const Errors = {
*/
class AstParser {

constructor() {
this._initParser();
}

/**
* Parse source into AST
*
Expand All @@ -69,6 +75,22 @@ class AstParser {
);
}

_initParser() {
this._jsep = jsep;

// remove binary ops
this._jsep.removeBinaryOp('!==');
this._jsep.removeBinaryOp('===');
this._jsep.removeBinaryOp('>>');
this._jsep.removeBinaryOp('<<');
this._jsep.removeBinaryOp('>>>');
this._jsep.removeBinaryOp('&');
this._jsep.removeBinaryOp('^');

// remove unary ops
this._jsep.removeUnaryOp('~');
}

/**
* Returns tokens generator
* @param {string} source
Expand Down Expand Up @@ -191,7 +213,7 @@ class AstParser {
// do nothing
} else {
// split source fragment into computed/uncomputed chunks
yield* AstParser._tokenizeSourceFragment(text, 1 + i);
yield* this._tokenizeSourceFragment(text, 1 + i);
}
}
}
Expand All @@ -202,13 +224,34 @@ class AstParser {
* @param {number} line #
* @private
*/
static * _tokenizeSourceFragment(fragment, line) {
* _tokenizeSourceFragment(fragment, line) {

let matches;

// extract source fragments and inline expressions
while (matches = /@{(.*?)}/.exec(fragment)) {

let expArg = null;
let parsed = false;
let argLen = fragment.length - matches.index - 3; // 3 = length("@{}")

// find a sequence of a maximum length that is a valid expression
while (argLen >= 0) {
try {
expArg = fragment.substr(matches.index + 2, argLen); // 2 = length("@{")
this._jsep(expArg);
parsed = true;
break;
} catch (e) {
// take it easy and keep trying
}
argLen--;
}

if (!parsed || fragment.charAt(matches.index + 2 + argLen) != '}') {
throw new Errors.SyntaxError(`Syntax error in the inline instruction at (${this.file}:${line})`);
}

// push source fragment
if (matches.index > 0) {
yield {
Expand All @@ -222,10 +265,10 @@ class AstParser {
yield {
_line: line,
type: TOKENS.INLINE_EXPRESSION,
args: [matches[1]]
args: [expArg]
};

fragment = fragment.substr(matches.index + matches[0].length);
fragment = fragment.substr(matches.index + 2 + argLen + 1); // match.index + length("@{") + length(arg) + length("}")
}

// push last source fragment
Expand Down

0 comments on commit 2e7717d

Please sign in to comment.