Skip to content
This repository was archived by the owner on Apr 10, 2023. It is now read-only.

Commit 1baa51b

Browse files
committed
feat(Support scoped identifier): ✨Remove argument token type, use identifier instead. Injec
1 parent bd799ac commit 1baa51b

File tree

2 files changed

+49
-72
lines changed

2 files changed

+49
-72
lines changed

__tests__/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const execute = compiler.execute;
1414
test('tokenizer', (t) => {
1515
t.deepEqual(tokenizer('{{userGrade}} == 0'), [
1616
{
17-
type: tokenTypes.ARGUMENT,
17+
type: tokenTypes.IDENTIFIER,
1818
value: 'userGrade',
1919
},
2020
{
@@ -180,7 +180,7 @@ test('execute', (t) => {
180180
t.deepEqual(compiler('false && true || false && true'), false);
181181
t.deepEqual(compiler('true && false || !true'), false);
182182
t.deepEqual(compiler('undefined === undefined'), true);
183-
t.deepEqual(compiler('undefined === {{test}}', {}), true);
183+
t.deepEqual(compiler('undefined === {{test}}', { test: undefined }), true);
184184
t.deepEqual(compiler('1 === undefined'), false);
185185
t.deepEqual(compiler('null === undefined'), false);
186186
t.deepEqual(compiler('null === null'), true);

index.js

Lines changed: 47 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const tokenTypes = {
99
COMPARISON_OPERATOR: 'comparisonOperator', // ==, ===, >, <, <=, >=, !=, !==
1010
CONDITIONAL_OPERATOR: 'conditionalOperator', // ? :
1111
LOGICAL_OPERATOR: 'logicalOperator', // &&, ||, !
12-
ARGUMENT: 'argument',
1312
NUMBER: 'number',
1413
STRING: 'string',
1514
BOOLEAN: 'boolean',
@@ -67,34 +66,34 @@ const binaryOperatorPrecedence = {
6766
};
6867

6968
const astFactory = {
70-
PROGRAM: (body) => {
69+
PROGRAM(body) {
7170
return { type: astTypes.PROGRAM, body };
7271
},
73-
EXPRESSION_STATEMENT: (expression) => {
72+
EXPRESSION_STATEMENT(expression) {
7473
return { type: astTypes.EXPRESSION_STATEMENT, expression };
7574
},
76-
LITERAL: (value) => {
75+
LITERAL(value) {
7776
return { type: astTypes.LITERAL, value };
7877
},
79-
BINARY_EXPRESSION: (operator, left, right) => {
78+
BINARY_EXPRESSION(operator, left, right) {
8079
return { type: astTypes.BINARY_EXPRESSION, operator, left, right };
8180
},
82-
UNARY_EXPRESSION: (operator, argument) => {
81+
UNARY_EXPRESSION(operator, argument) {
8382
return { type: astTypes.UNARY_EXPRESSION, operator, argument };
8483
},
85-
LOGICAL_EXPRESSION: (operator, left, right) => {
84+
LOGICAL_EXPRESSION(operator, left, right) {
8685
return { type: astTypes.LOGICAL_EXPRESSION, operator, left, right };
8786
},
88-
IDENTIFIER: (name) => {
87+
IDENTIFIER(name) {
8988
return { type: astTypes.IDENTIFIER, name };
9089
},
91-
SEQUENCE_EXPRESSION: (expressions) => {
90+
SEQUENCE_EXPRESSION(expressions) {
9291
return { type: astTypes.SEQUENCE_EXPRESSION, expressions };
9392
},
94-
CONDITIONAL_EXPRESSION: (test, consequent, alternate) => {
93+
CONDITIONAL_EXPRESSION(test, consequent, alternate) {
9594
return { type: astTypes.CONDITIONAL_EXPRESSION, test, consequent, alternate };
9695
},
97-
MEMBER_EXPRESSION: (object, property) => {
96+
MEMBER_EXPRESSION(object, property) {
9897
return { type: astTypes.MEMBER_EXPRESSION, object, property };
9998
},
10099
};
@@ -235,7 +234,7 @@ function tokenizer(input) {
235234
}
236235
if (input[i + j + 1] === '}') {
237236
if (value !== '') {
238-
pushToken(tokenTypes.ARGUMENT, value, 4);
237+
pushToken(tokenTypes.IDENTIFIER, value, 4);
239238
continue;
240239
}
241240
}
@@ -336,7 +335,7 @@ function tokenizer(input) {
336335

337336
compiler.tokenizer = tokenizer;
338337

339-
function parser(tokens, args) {
338+
function parser(tokens) {
340339
let length = tokens.length;
341340

342341
function getLogicalExpression(start, end) {
@@ -398,7 +397,6 @@ function parser(tokens, args) {
398397
prevToken.type === tokenTypes.BOOLEAN ||
399398
prevToken.type === tokenTypes.IDENTIFIER ||
400399
prevToken.type === tokenTypes.NULL ||
401-
prevToken.type === tokenTypes.ARGUMENT ||
402400
(
403401
prevToken.type === tokenTypes.PARENTHESIS &&
404402
prevToken.value === ')'
@@ -465,7 +463,6 @@ function parser(tokens, args) {
465463
if (start !== end) {
466464
return null;
467465
}
468-
maskArguments(start, end);
469466
const token = tokens[start];
470467
if (token.type === tokenTypes.IDENTIFIER) {
471468
return getIdentifier(start, end);
@@ -496,30 +493,6 @@ function parser(tokens, args) {
496493
throw new Error('Unexpected literal token type: ' + token.type);
497494
}
498495

499-
function maskArguments(start, end) {
500-
if (start !== end) {
501-
return null;
502-
}
503-
const token = tokens[start];
504-
if (token.type === tokenTypes.ARGUMENT) {
505-
token.value = args[token.value];
506-
if (typeof token.value === 'string') {
507-
token.type = tokenTypes.STRING;
508-
} else if (typeof token.value === 'number') {
509-
token.type = tokenTypes.NUMBER;
510-
} else if (typeof token.value === 'boolean') {
511-
token.type = tokenTypes.BOOLEAN;
512-
} else if (token.value === null) {
513-
token.type = tokenTypes.NULL;
514-
} else if (token.value === undefined) {
515-
token.type = tokenTypes.IDENTIFIER;
516-
token.value = 'undefined';
517-
} else {
518-
throw new Error('Unexpected argument type: ' + token.value);
519-
}
520-
}
521-
}
522-
523496
function getSequenceExpressions(start, end) {
524497
let sequenceExpressions = [];
525498
let prevStart = start;
@@ -693,93 +666,94 @@ compiler.parser = parser;
693666

694667
/**
695668
* @param ast
669+
* @param scope containing arguments
696670
* @returns {*}
697671
*/
698-
function execute(ast) {
672+
function execute(ast, scope) {
699673
if (ast.type === astTypes.PROGRAM) {
700674
for (let i = 0, l = ast.body.length - 1; i < l; i++) {
701-
execute(ast.body[i]);
675+
execute(ast.body[i], scope);
702676
}
703-
return execute(ast.body[ast.body.length - 1]);
677+
return execute(ast.body[ast.body.length - 1], scope);
704678
}
705679
if (ast.type === astTypes.EXPRESSION_STATEMENT) {
706-
return execute(ast.expression);
680+
return execute(ast.expression, scope);
707681
}
708682
if (ast.type === astTypes.SEQUENCE_EXPRESSION) {
709683
for (let i = 0; i < ast.expressions.length - 1; i++) {
710-
execute(ast.expressions[i]);
684+
execute(ast.expressions[i], scope);
711685
}
712-
return execute(ast.expressions[ast.expressions.length - 1]);
686+
return execute(ast.expressions[ast.expressions.length - 1], scope);
713687
}
714688
if (ast.type === astTypes.LOGICAL_EXPRESSION) {
715689
if (ast.operator === '&&') {
716-
return execute(ast.left) && execute(ast.right);
690+
return execute(ast.left, scope) && execute(ast.right, scope);
717691
}
718692
if (ast.operator === '||') {
719-
return execute(ast.left) || execute(ast.right);
693+
return execute(ast.left, scope) || execute(ast.right, scope);
720694
}
721695
throw new Error('Unexpected LOGICAL_EXPRESSION operator: ' + ast.operator);
722696
}
723697
if (ast.type === astTypes.BINARY_EXPRESSION) {
724698
if (ast.operator === '===') {
725-
return execute(ast.left) === execute(ast.right);
699+
return execute(ast.left, scope) === execute(ast.right, scope);
726700
}
727701
if (ast.operator === '==') {
728-
return execute(ast.left) == execute(ast.right);
702+
return execute(ast.left, scope) == execute(ast.right, scope);
729703
}
730704
if (ast.operator === '>') {
731-
return execute(ast.left) > execute(ast.right);
705+
return execute(ast.left, scope) > execute(ast.right, scope);
732706
}
733707
if (ast.operator === '<') {
734-
return execute(ast.left) < execute(ast.right);
708+
return execute(ast.left, scope) < execute(ast.right, scope);
735709
}
736710
if (ast.operator === '<=') {
737-
return execute(ast.left) <= execute(ast.right);
711+
return execute(ast.left, scope) <= execute(ast.right, scope);
738712
}
739713
if (ast.operator === '>=') {
740-
return execute(ast.left) >= execute(ast.right);
714+
return execute(ast.left, scope) >= execute(ast.right, scope);
741715
}
742716
if (ast.operator === '!=') {
743-
return execute(ast.left) != execute(ast.right);
717+
return execute(ast.left, scope) != execute(ast.right, scope);
744718
}
745719
if (ast.operator === '!==') {
746-
return execute(ast.left) !== execute(ast.right);
720+
return execute(ast.left, scope) !== execute(ast.right, scope);
747721
}
748722
if (ast.operator === '+') {
749-
return execute(ast.left) + execute(ast.right);
723+
return execute(ast.left, scope) + execute(ast.right, scope);
750724
}
751725
if (ast.operator === '-') {
752-
return execute(ast.left) - execute(ast.right);
726+
return execute(ast.left, scope) - execute(ast.right, scope);
753727
}
754728
if (ast.operator === '*') {
755-
return execute(ast.left) * execute(ast.right);
729+
return execute(ast.left, scope) * execute(ast.right, scope);
756730
}
757731
if (ast.operator === '/') {
758-
return execute(ast.left) / execute(ast.right);
732+
return execute(ast.left, scope) / execute(ast.right, scope);
759733
}
760734
if (ast.operator === '%') {
761-
return execute(ast.left) % execute(ast.right);
735+
return execute(ast.left, scope) % execute(ast.right, scope);
762736
}
763737
if (ast.operator === '**') {
764-
return execute(ast.left) ** execute(ast.right);
738+
return execute(ast.left, scope) ** execute(ast.right, scope);
765739
}
766740
if (ast.operator === '&') {
767-
return execute(ast.left) & execute(ast.right);
741+
return execute(ast.left, scope) & execute(ast.right, scope);
768742
}
769743
if (ast.operator === '|') {
770-
return execute(ast.left) | execute(ast.right);
744+
return execute(ast.left, scope) | execute(ast.right, scope);
771745
}
772746
if (ast.operator === '^') {
773-
return execute(ast.left) ^ execute(ast.right);
747+
return execute(ast.left, scope) ^ execute(ast.right, scope);
774748
}
775749
if (ast.operator === '>>') {
776-
return execute(ast.left) >> execute(ast.right);
750+
return execute(ast.left, scope) >> execute(ast.right, scope);
777751
}
778752
if (ast.operator === '<<') {
779-
return execute(ast.left) << execute(ast.right);
753+
return execute(ast.left, scope) << execute(ast.right, scope);
780754
}
781755
if (ast.operator === '>>>') {
782-
return execute(ast.left) >>> execute(ast.right);
756+
return execute(ast.left, scope) >>> execute(ast.right, scope);
783757
}
784758
throw new Error('Unexpected BINARY_EXPRESSION operator: ' + ast.operator);
785759
}
@@ -808,6 +782,9 @@ function execute(ast) {
808782
if (ast.name === 'undefined') {
809783
return undefined;
810784
}
785+
if (scope.hasOwnProperty(ast.name)) {
786+
return scope[ast.name];
787+
}
811788
throw new Error('Unexpected identifier name: ' + ast.name);
812789
}
813790
if (ast.type === astTypes.CONDITIONAL_EXPRESSION) {
@@ -818,10 +795,10 @@ function execute(ast) {
818795

819796
compiler.execute = execute;
820797

821-
function compiler(input, args) {
798+
function compiler(input, scope) {
822799
const tokens = tokenizer(input);
823-
const ast = parser(tokens, args);
824-
return execute(ast);
800+
const ast = parser(tokens);
801+
return execute(ast, scope);
825802
}
826803

827804
module.exports = compiler;

0 commit comments

Comments
 (0)