Skip to content

Commit

Permalink
Merge pull request #23 from ambassify/feat/support-range-expressions
Browse files Browse the repository at this point in the history
feat(expression): add support for range expression
  • Loading branch information
JorgenEvens authored Mar 15, 2023
2 parents 9467a10 + 25b5645 commit 1d42b52
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
40 changes: 39 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ const TAG_CONTROL = TAG | mkid();
const TAG_ARGUMENT = EXPRESSION | mkid();
const BLOCK = TEXT | mkid();

const TYPES = {TEXT,TWIG,ERROR,EXPRESSION,VARIABLE,OBJECT,BLOCK,TAG,TAG_ARGUMENT,OBJECT_PROPERTY,OBJECT_VALUE,STRING,FUNCTION,TAG_OUTPUT,TAG_CONTROL,EXPRESSION_LIST,LITERAL,ARRAY,NUMBER,ARGUMENT_LIST,BOOLEAN,NULL,OPERATOR,BRACKETS,FILTER,ACCESS_CHAIN};
const RANGE = EXPRESSION | mkid();

const TYPES = {TEXT,TWIG,ERROR,EXPRESSION,VARIABLE,OBJECT,BLOCK,TAG,TAG_ARGUMENT,OBJECT_PROPERTY,OBJECT_VALUE,STRING,FUNCTION,TAG_OUTPUT,TAG_CONTROL,EXPRESSION_LIST,LITERAL,ARRAY,NUMBER,ARGUMENT_LIST,BOOLEAN,NULL,OPERATOR,BRACKETS,FILTER,ACCESS_CHAIN,RANGE};
const NAMES = _invert(TYPES);

const isType = (state, type) => (state & type) == type;
Expand Down Expand Up @@ -597,6 +599,29 @@ function matchToken(config = {}, str, state = TEXT, offset = 0, skip = 0, parent
tok.add(integer);
}

/**
* Matching the left-handside expression of the RANGE expression
* This path will be taken when we already detected that we are
* reading a RANGE.
*
*/
} else if (isType(state, EXPRESSION) && tok.parent.is(RANGE) && ms('..')) {
tok.end = i;
return tok;

/**
* If an expression is followed by `..` it indicates that we are
* currently reading expressions that are part of a RANGE expression.
*
* Read the RANGE and replace the already read expression with a RANGE.
*/
} else if (isType(state, EXPRESSION) && ms('..')) {
const range = m(RANGE, tok.start);

i = range.end;
tok.end = range.end;
tok.children = [ range ];

/**
* If the next character is a dot and we are not matching a number,
* we must be matching a property access.
Expand Down Expand Up @@ -723,6 +748,19 @@ function matchToken(config = {}, str, state = TEXT, offset = 0, skip = 0, parent
tok.end = i;
return tok;

/**
* Read range expression
* example `from..to`
*/
} else if (isType(state, RANGE)) {
const from = m(EXPRESSION, i);
const to = m(EXPRESSION, from.end + 2);

tok.end = to.end;
tok.add(from);
tok.add(to);
return tok;

/**
* Detect the operator that the expression statement found.
*/
Expand Down
20 changes: 20 additions & 0 deletions test/expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@ describe('toAST', () => {
assert.equal(take(fnBar, 0, 0, 0, 'value'), 'baz');
});

it('should handle for loop with range', () => {
const ast = toAST(`
{% for idx in variable_1..test %}
{{ idx }},
{% endfor %}
`);

const range = take(ast, 1, 0, 2, 0);
assert.equal(range.type, 'RANGE');

assert.equal(range.children.length, 2);

const [ from, to ] = range.children;
assert.equal(from.type, 'EXPRESSION');
assert.equal(take(from, 0, 'name'), 'variable_1');

assert.equal(to.type, 'EXPRESSION');
assert.equal(take(to, 0, 'name'), 'test');
});

describe('# regression', () => {

it('should handle functions starting with in', () => {
Expand Down

0 comments on commit 1d42b52

Please sign in to comment.