1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using System . Text ;
3
4
4
5
namespace MoonSharp . Interpreter . Tree
@@ -60,23 +61,58 @@ public void Next()
60
61
m_Current = FetchNewToken ( ) ;
61
62
}
62
63
64
+ private List < int > templateStringState = new List < int > ( ) ;
65
+
66
+ void PushTemplateString ( )
67
+ {
68
+ templateStringState . Add ( 0 ) ;
69
+ }
70
+
71
+ bool InTemplateString ( ) => templateStringState . Count > 0 ;
72
+
73
+ void TemplateStringAddBracket ( )
74
+ {
75
+ if ( InTemplateString ( ) ) {
76
+ templateStringState [ templateStringState . Count - 1 ] ++ ;
77
+ }
78
+ }
79
+
80
+ bool ReturnToTemplateString ( )
81
+ {
82
+ var c = templateStringState [ templateStringState . Count - 1 ] ;
83
+ if ( c == 0 ) return true ;
84
+ templateStringState [ templateStringState . Count - 1 ] -- ;
85
+ return false ;
86
+ }
87
+
88
+ void PopTemplateString ( )
89
+ {
90
+ templateStringState . RemoveAt ( templateStringState . Count - 1 ) ;
91
+ }
92
+
93
+
63
94
struct Snapshot
64
95
{
65
96
public int Cursor ;
66
97
public Token Current ;
67
98
public int Line ;
68
99
public int Col ;
100
+ public int [ ] TemplateStringState ;
69
101
}
102
+
70
103
71
104
private Snapshot s ;
105
+
106
+
72
107
73
108
public void SavePos ( )
74
109
{
75
110
s = new Snapshot ( ) {
76
111
Cursor = m_Cursor ,
77
112
Current = m_Current ,
78
113
Line = m_Line ,
79
- Col = m_Col
114
+ Col = m_Col ,
115
+ TemplateStringState = templateStringState . ToArray ( ) ,
80
116
} ;
81
117
}
82
118
@@ -86,6 +122,7 @@ public void RestorePos()
86
122
m_Current = s . Current ;
87
123
m_Line = s . Line ;
88
124
m_Col = s . Col ;
125
+ templateStringState = new List < int > ( s . TemplateStringState ) ;
89
126
}
90
127
91
128
public Token PeekNext ( )
@@ -94,6 +131,12 @@ public Token PeekNext()
94
131
Token current = m_Current ;
95
132
int line = m_Line ;
96
133
int col = m_Col ;
134
+ //Save the template string state
135
+ int stateC = templateStringState . Count ;
136
+ int lastC = 0 ;
137
+ if ( templateStringState . Count > 0 ) {
138
+ lastC = templateStringState [ templateStringState . Count - 1 ] ;
139
+ }
97
140
98
141
Next ( ) ;
99
142
Token t = Current ;
@@ -102,7 +145,19 @@ public Token PeekNext()
102
145
m_Current = current ;
103
146
m_Line = line ;
104
147
m_Col = col ;
105
-
148
+ //Restore the template string state
149
+ if ( templateStringState . Count < stateC )
150
+ {
151
+ templateStringState . Add ( lastC ) ;
152
+ }
153
+ else if ( templateStringState . Count > stateC )
154
+ {
155
+ templateStringState . RemoveAt ( templateStringState . Count - 1 ) ;
156
+ }
157
+ else if ( stateC != 0 )
158
+ {
159
+ templateStringState [ templateStringState . Count - 1 ] = lastC ;
160
+ }
106
161
return t ;
107
162
}
108
163
@@ -463,8 +518,17 @@ private Token ReadToken()
463
518
case ')' :
464
519
return CreateSingleCharToken ( TokenType . Brk_Close_Round , fromLine , fromCol ) ;
465
520
case '{' :
521
+ TemplateStringAddBracket ( ) ;
466
522
return CreateSingleCharToken ( TokenType . Brk_Open_Curly , fromLine , fromCol ) ;
467
- case '}' :
523
+ case '}' when InTemplateString ( ) : {
524
+ if ( ReturnToTemplateString ( ) ) {
525
+ return ReadTemplateString ( fromLine , fromCol , false ) ;
526
+ }
527
+ else {
528
+ return CreateSingleCharToken ( TokenType . Brk_Close_Curly , fromLine , fromCol ) ;
529
+ }
530
+ }
531
+ case '}' when ! InTemplateString ( ) :
468
532
return CreateSingleCharToken ( TokenType . Brk_Close_Curly , fromLine , fromCol ) ;
469
533
case ',' :
470
534
return CreateSingleCharToken ( TokenType . Comma , fromLine , fromCol ) ;
@@ -509,6 +573,19 @@ private Token ReadToken()
509
573
}
510
574
case ':' :
511
575
return PotentiallyDoubleCharOperator ( ':' , TokenType . Colon , TokenType . DoubleColon , fromLine , fromCol ) ;
576
+ case '`' :
577
+ {
578
+ char next = CursorCharNext ( ) ;
579
+ if ( next == '`' )
580
+ {
581
+ PushTemplateString ( ) ;
582
+ return ReadTemplateString ( fromLine , fromCol , true ) ;
583
+ }
584
+ throw new SyntaxErrorException ( CreateToken ( TokenType . Invalid , fromLine , fromCol ) , "unexpected symbol near '{0}'" , CursorChar ( ) )
585
+ {
586
+ IsPrematureStreamTermination = true
587
+ } ;
588
+ }
512
589
case '"' :
513
590
case '\' ' :
514
591
return ReadSimpleStringToken ( fromLine , fromCol ) ;
@@ -534,6 +611,70 @@ private Token ReadToken()
534
611
}
535
612
}
536
613
614
+
615
+ Token ReadTemplateString ( int fromLine , int fromCol , bool isStart )
616
+ {
617
+ StringBuilder text = new StringBuilder ( 32 ) ;
618
+
619
+ for ( char c = CursorCharNext ( ) ; CursorNotEof ( ) ; c = CursorCharNext ( ) )
620
+ {
621
+ redo_Loop :
622
+
623
+ if ( c == '\\ ' )
624
+ {
625
+ text . Append ( c ) ;
626
+ c = CursorCharNext ( ) ;
627
+ text . Append ( c ) ;
628
+
629
+ if ( c == '\r ' )
630
+ {
631
+ c = CursorCharNext ( ) ;
632
+ if ( c == '\n ' )
633
+ text . Append ( c ) ;
634
+ else
635
+ goto redo_Loop ;
636
+ }
637
+ else if ( c == 'z' )
638
+ {
639
+ c = CursorCharNext ( ) ;
640
+
641
+ if ( char . IsWhiteSpace ( c ) )
642
+ SkipWhiteSpace ( ) ;
643
+
644
+ c = CursorChar ( ) ;
645
+
646
+ goto redo_Loop ;
647
+ }
648
+ }
649
+ else if ( c == '$' && CursorMatches ( "${" ) )
650
+ {
651
+ CursorCharNext ( ) ;
652
+ CursorCharNext ( ) ;
653
+ Token t = CreateToken ( TokenType . String_TemplateFragment , fromLine , fromCol ) ;
654
+ t . Text = LexerUtils . UnescapeLuaString ( t , text . ToString ( ) ) ;
655
+ return t ;
656
+ }
657
+ else if ( c == '`' && CursorMatches ( "``" ) )
658
+ {
659
+ CursorCharNext ( ) ;
660
+ CursorCharNext ( ) ;
661
+ PopTemplateString ( ) ;
662
+ Token t = CreateToken ( isStart ? TokenType . String_Long : TokenType . String_EndTemplate , fromLine , fromCol ) ;
663
+ t . Text = LexerUtils . UnescapeLuaString ( t , text . ToString ( ) ) ;
664
+ return t ;
665
+ }
666
+ else
667
+ {
668
+ text . Append ( c ) ;
669
+ }
670
+ }
671
+
672
+ throw new SyntaxErrorException (
673
+ CreateToken ( TokenType . Invalid , fromLine , fromCol ) ,
674
+ "unfinished string near '{0}'" , text . ToString ( ) ) { IsPrematureStreamTermination = true } ;
675
+ }
676
+
677
+
537
678
private string ReadLongString ( int fromLine , int fromCol , string startpattern , string subtypeforerrors )
538
679
{
539
680
// here we are at the first '=' or second '['
0 commit comments