Skip to content

Commit

Permalink
feat: add string type (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
prevwong committed Feb 18, 2024
1 parent e2d4465 commit 6075dee
Show file tree
Hide file tree
Showing 17 changed files with 208 additions and 39 deletions.
7 changes: 7 additions & 0 deletions .changeset/wet-windows-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@rekajs/parser': patch
'@rekajs/types': patch
'@rekajs/core': patch
---

Add string type
12 changes: 12 additions & 0 deletions packages/core/src/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,18 @@ export const computeExpression = (
return expr.value;
}

if (expr instanceof t.String) {
return expr.value
.map((value) => {
if (typeof value === 'string') {
return value;
}

return computeExpression(value, reka, env, ctx);
})
.join('');
}

if (expr instanceof t.Val) {
const value = expr.init
? computeExpression(expr.init, reka, env, {
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@ export class Resolver {
if (expr instanceof t.Val) {
this.resolveVariable(expr, scope);
}

if (expr instanceof t.String) {
expr.value.map((value) => {
if (t.is(value, t.Expression)) {
this.resolveExpr(value, scope);
}
});
}
}

private resolveComponent(component: t.Component, scope: Scope) {
Expand Down
3 changes: 3 additions & 0 deletions packages/parser/src/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ export class Lexer {
this.state.current += 1;
return string;
}
case '`': {
return this.tokenize(TokenType.BACKTICK);
}
case ':': {
if (this.currentContext === tc_val_prop) {
return this.tokenize(TokenType.KIND);
Expand Down
36 changes: 36 additions & 0 deletions packages/parser/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,42 @@ const jsToReka = <T extends t.ASTNode = t.ASTNode>(
right: _convert(node.right),
});
}
case 'TemplateLiteral': {
const str = node.quasis.map((quasi) => quasi.value.raw).join('');

const bracesMatches = [...str.matchAll(/{{(.*?)}}/g)];

if (bracesMatches.length == 0) {
return t.string({
value: [str],
});
}

return t.string({
value: bracesMatches.reduce((accum, match, matchIdx) => {
const exprStr = match[0];
const { type: expr } = parseExpressionWithAcornToRekaType(
exprStr.substring(2, exprStr.length - 2),
0
);

const start =
matchIdx === 0
? 0
: (bracesMatches[matchIdx - 1].index ?? 0) +
bracesMatches[matchIdx - 1][0].length;

const innerStr = str.substring(start, match.index);
accum.push(innerStr);
accum.push(expr);

if (matchIdx === bracesMatches.length - 1) {
accum.push(str.substring(match.index! + exprStr.length));
}
return accum;
}, [] as Array<string | t.Expression>),
});
}
default: {
return t.Schema.fromJSON(node) as t.Type;
}
Expand Down
14 changes: 14 additions & 0 deletions packages/parser/src/stringifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ class _Stringifier {

this.writer.write(node.value.toString());
},
String: (node) => {
this.writer.write('`');
node.value.forEach((strOrExpr) => {
if (typeof strOrExpr === 'string') {
this.writer.write(strOrExpr);
return;
}

this.writer.write('{{');
this.stringify(strOrExpr, precedence);
this.writer.write('}}');
});
this.writer.write('`');
},
ArrayExpression: (node) => {
this.writer.write('[');
node.elements.forEach((element, i) => {
Expand Down
30 changes: 30 additions & 0 deletions packages/parser/src/tests/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,4 +304,34 @@ describe('Parser', () => {
bindable: true,
});
});
it('should be able to parse string type', () => {
const parsed = Parser.parseExpression(
'`Hello {{myVariable}} there {{1+2}}!`'
);

expect(parsed).toMatchObject({
type: 'String',
value: [
'Hello ',
{
type: 'Identifier',
name: 'myVariable',
},
' there ',
{
type: 'BinaryExpression',
left: {
type: 'Literal',
value: 1,
},
operator: '+',
right: {
type: 'Literal',
value: 2,
},
},
'!',
],
});
});
});
20 changes: 20 additions & 0 deletions packages/parser/src/tests/stringifier.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,24 @@ describe('Stringifier', () => {
)
).toEqual(`<input value:={value} />`);
});
it('should be able to stringifiy string type', () => {
expect(
Stringifier.toString(
t.string({
value: [
'Hello ',
t.identifier({
name: 'myVariable',
}),
' + ',
t.binaryExpression({
left: t.literal({ value: 1 }),
operator: '+',
right: t.literal({ value: 1 }),
}),
],
})
)
).toEqual('`Hello {{myVariable}} + {{1 + 1}}`');
});
});
1 change: 1 addition & 0 deletions packages/parser/src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export enum TokenType {
STAR = '*',
DOLLAR = '$',
AMPERSAND = '@',
BACKTICK = '`',

NOT = '!',
NEQ = '!=',
Expand Down
2 changes: 1 addition & 1 deletion packages/types/scripts/generator/stringifyField.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const fieldsToString = {
return self.node;
},
array: (self) => {
return `${stringifyField(self.array)}[]`;
return `Array<${stringifyField(self.array)}>`;
},
map: (self) => {
return `Record<string, ${stringifyField(self.type)}>`;
Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/generated/builder.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export const customKind = (
) => new t.CustomKind(...args);
export const literal = (...args: ConstructorParameters<typeof t.Literal>) =>
new t.Literal(...args);
export const string = (...args: ConstructorParameters<typeof t.String>) =>
new t.String(...args);
export const identifier = (
...args: ConstructorParameters<typeof t.Identifier>
) => new t.Identifier(...args);
Expand Down
Loading

0 comments on commit 6075dee

Please sign in to comment.