Skip to content

Commit b92e8a8

Browse files
committed
Add string interpolation
1 parent 51506e0 commit b92e8a8

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

hscript/Expr.hx

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ package hscript;
2727
enum Const {
2828
CInt( v : Int );
2929
CFloat( f : Float );
30-
CString( s : String );
30+
CString( s : String, ?interpolated:Bool );
3131
#if !haxe3
3232
CInt32( v : haxe.Int32 );
3333
#end

hscript/Parser.hx

+71-1
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,12 @@ class Parser {
310310
e = mk(EIdent(id));
311311
return parseExprNext(e);
312312
case TConst(c):
313+
switch (c) {
314+
case CString(s, interpolated):
315+
if (interpolated)
316+
return parseExprNext(interpolate(s));
317+
default:
318+
}
313319
return parseExprNext(mk(EConst(c)));
314320
case TPOpen:
315321
var e = parseExpr();
@@ -389,6 +395,70 @@ class Parser {
389395
return unexpected(tk);
390396
}
391397
}
398+
399+
function interpolate(s:String) {
400+
var exprs:Array<Expr> = [];
401+
var dollarIndex = s.indexOf('$');
402+
403+
while (dollarIndex > -1) {
404+
var i = dollarIndex;
405+
var char = s.charAt(++i);
406+
switch (char) {
407+
case '$':
408+
s = s.substring(0, i) + s.substr(i + 1);
409+
case '{':
410+
var expr = "";
411+
var depth = 0;
412+
413+
var precedingSub = s.substring(0, i - 1);
414+
if (precedingSub != "")
415+
exprs.push(mk(EConst(CString(precedingSub))));
416+
417+
while (depth >= 0) {
418+
char = s.charAt(++i);
419+
if (char == '{')
420+
depth++;
421+
else if (char == '}') {
422+
depth--;
423+
if (depth < 0)
424+
break;
425+
}
426+
expr += char;
427+
}
428+
429+
exprs.push(parseString(expr #if hscriptPos, origin #end));
430+
s = s.substr(i + 1);
431+
case c if (c == '_' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'): // [a-zA-Z_]
432+
var ident = c;
433+
var precedingSub = s.substring(0, i - 1);
434+
if (precedingSub != "")
435+
exprs.push(mk(EConst(CString(precedingSub))));
436+
while (true) {
437+
char = s.charAt(++i);
438+
if (char == '_'
439+
|| char >= 'a' && char <= 'z'
440+
|| char >= 'A' && char <= 'Z'
441+
|| char >= '0' && char <= '9') // [a-zA-Z0-9_]
442+
ident += char;
443+
else break;
444+
}
445+
exprs.push(mk(EIdent(ident)));
446+
s = s.substr(i);
447+
}
448+
dollarIndex = s.indexOf('$');
449+
}
450+
451+
if (exprs.length == 0)
452+
exprs.push(mk(EConst(CString(s))));
453+
454+
var expr = exprs[0];
455+
for (i in 1...exprs.length) {
456+
var nextExpr = exprs[i];
457+
expr = mk(EBinop('+', expr, nextExpr));
458+
}
459+
460+
return expr;
461+
}
392462

393463
function mapCompr( tmp : String, e : Expr ) {
394464
var edef = switch( expr(e) ) {
@@ -1070,7 +1140,7 @@ class Parser {
10701140
case 125: return TBrClose;
10711141
case 91: return TBkOpen;
10721142
case 93: return TBkClose;
1073-
case 39: return TConst( CString(readString(39)) );
1143+
case 39: return TConst( CString(readString(39), true) );
10741144
case 34: return TConst( CString(readString(34)) );
10751145
case 63: return TQuestion;
10761146
case 58: return TDoubleDot;

0 commit comments

Comments
 (0)