@@ -20,11 +20,52 @@ func NewInterpreter() *Interpreter {
2020
2121// Execute parses and executes a single line of code
2222func (i * Interpreter ) Execute (line string ) {
23+ // Remove inline comments starting with //
24+ if idx := strings .Index (line , "//" ); idx != - 1 {
25+ line = strings .TrimSpace (line [:idx ])
26+ }
27+ // Normalize spacing around '=' so "x=x+5" also works
28+ line = strings .ReplaceAll (line , "=" , " = " )
29+
2330 tokens := strings .Fields (line )
2431 if len (tokens ) == 0 {
2532 return
2633 }
2734
35+ // Handle assignments like: x = 5 or x = y + 5 or x = "hello"
36+ if len (tokens ) >= 3 && tokens [1 ] == "=" {
37+ varName := tokens [0 ]
38+ rhs := strings .Join (tokens [2 :], " " )
39+ rhs = strings .TrimSpace (rhs )
40+ if rhs == "" {
41+ fmt .Println ("bhul hoye gelo vai check kor ekbar: invalid assignment" )
42+ return
43+ }
44+ // quoted string
45+ if strings .HasPrefix (rhs , "\" " ) && strings .HasSuffix (rhs , "\" " ) {
46+ i .variables [varName ] = rhs [1 : len (rhs )- 1 ]
47+ return
48+ }
49+ // try numeric expression
50+ rhsTokens := strings .Fields (rhs )
51+ if val , err := i .evaluateExpression (rhsTokens ); err == nil {
52+ i .variables [varName ] = val
53+ return
54+ }
55+ // try integer parse
56+ if v , err := strconv .Atoi (rhs ); err == nil {
57+ i .variables [varName ] = v
58+ return
59+ }
60+ // try variable lookup
61+ if value , ok := i .variables [rhs ]; ok {
62+ i .variables [varName ] = value
63+ return
64+ }
65+ fmt .Println ("bhul hoye gelo vai check kor ekbar: invalid assignment" )
66+ return
67+ }
68+
2869 switch tokens [0 ] {
2970 case "kemon" :
3071 if len (tokens ) < 3 || tokens [1 ] != "achis" {
@@ -118,6 +159,10 @@ func (i *Interpreter) Execute(line string) {
118159}
119160
120161func (i * Interpreter ) evaluateExpression (tokens []string ) (int , error ) {
162+ if len (tokens ) == 0 {
163+ return 0 , fmt .Errorf ("invalid expression" )
164+ }
165+
121166 if len (tokens ) == 1 {
122167 if value , ok := i .variables [tokens [0 ]]; ok {
123168 switch v := value .(type ) {
@@ -211,6 +256,89 @@ func (i *Interpreter) getValue(token string) (int, error) {
211256 return 0 , fmt .Errorf ("unknown variable '%s'" , token )
212257}
213258
259+ // ExecuteLoop processes a loop header and executes the single-line body.
260+ // header: full header string (e.g., "bolte thak i [0] -> [10] [i++] :")
261+ // body: single-line loop body (e.g., "kemon achis i")
262+ func (i * Interpreter ) ExecuteLoop (header , body string ) {
263+ header = strings .TrimSpace (header )
264+ if strings .HasSuffix (header , ":" ) {
265+ header = strings .TrimSuffix (header , ":" )
266+ }
267+
268+ // expected format: bolte thak <iter> [<start>] -> [<end>] [<incr>]
269+ parts := strings .Fields (header )
270+ if len (parts ) < 4 {
271+ fmt .Println ("bhul hoye gelo vai check kor ekbar: invalid loop syntax" )
272+ return
273+ }
274+ // parts[0] = bolte, parts[1] = thak, parts[2] = iter
275+ iter := parts [2 ]
276+
277+ // find start and end between brackets
278+ startIdx := strings .Index (header , "[" )
279+ endIdx := strings .Index (header , "]" )
280+ if startIdx == - 1 || endIdx == - 1 || endIdx <= startIdx {
281+ fmt .Println ("bhul hoye gelo vai check kor ekbar: invalid loop range" )
282+ return
283+ }
284+ startStr := header [startIdx + 1 : endIdx ]
285+
286+ arrowIdx := strings .Index (header [endIdx :], "->" )
287+ if arrowIdx == - 1 {
288+ fmt .Println ("bhul hoye gelo vai check kor ekbar: invalid loop arrow" )
289+ return
290+ }
291+
292+ // find the next bracket after arrow
293+ rest := header [endIdx + arrowIdx :]
294+ nextOpen := strings .Index (rest , "[" )
295+ nextClose := strings .Index (rest , "]" )
296+ if nextOpen == - 1 || nextClose == - 1 {
297+ fmt .Println ("bhul hoye gelo vai check kor ekbar: invalid loop end" )
298+ return
299+ }
300+ endStr := rest [nextOpen + 1 : nextClose ]
301+
302+ // default increment = 1; check for optional increment bracket at end
303+ incr := 1
304+ // find last bracket content
305+ lastOpen := strings .LastIndex (header , "[" )
306+ lastClose := strings .LastIndex (header , "]" )
307+ if lastOpen != - 1 && lastClose != - 1 && lastClose > lastOpen {
308+ possible := header [lastOpen + 1 : lastClose ]
309+ // if possible contains ++ or += treat as increment
310+ if possible == iter + "++" || strings .Contains (possible , "++" ) {
311+ incr = 1
312+ } else if strings .Contains (possible , "+=" ) {
313+ parts := strings .Split (possible , "+=" )
314+ if len (parts ) == 2 {
315+ if v , err := strconv .Atoi (parts [1 ]); err == nil {
316+ incr = v
317+ }
318+ }
319+ }
320+ }
321+
322+ // parse start and end
323+ s , err1 := strconv .Atoi (strings .TrimSpace (startStr ))
324+ e , err2 := strconv .Atoi (strings .TrimSpace (endStr ))
325+ if err1 != nil || err2 != nil {
326+ fmt .Println ("bhul hoye gelo vai check kor ekbar: invalid loop numeric values" )
327+ return
328+ }
329+
330+ // run loop (support ascending only)
331+ if s <= e {
332+ for v := s ; v <= e ; v += incr {
333+ i .variables [iter ] = v
334+ i .Execute (strings .TrimSpace (body ))
335+ }
336+ return
337+ }
338+
339+ fmt .Println ("bhul hoye gelo vai check kor ekbar: start greater than end not supported" )
340+ }
341+
214342func main () {
215343 version := flag .Bool ("v" , false , "Print the version" )
216344 help := flag .Bool ("h" , false , "Display help" )
@@ -244,8 +372,23 @@ func main() {
244372 interpreter := NewInterpreter ()
245373 scanner := bufio .NewScanner (file )
246374 for scanner .Scan () {
247- line := scanner .Text ()
248- interpreter .Execute (strings .TrimSpace (line ))
375+ line := strings .TrimSpace (scanner .Text ())
376+ // Skip blank lines and comment-only lines
377+ trimmed := strings .TrimSpace (line )
378+ if trimmed == "" || strings .HasPrefix (trimmed , "//" ) {
379+ continue
380+ }
381+ // If it's a loop header (file mode), read next line as body
382+ if strings .HasPrefix (trimmed , "bolte thak" ) {
383+ if scanner .Scan () {
384+ body := scanner .Text ()
385+ interpreter .ExecuteLoop (trimmed , body )
386+ } else {
387+ fmt .Println ("bhul hoye gelo vai check kor ekbar: loop header but no body" )
388+ }
389+ continue
390+ }
391+ interpreter .Execute (line )
249392 }
250393 if err := scanner .Err (); err != nil {
251394 fmt .Printf ("Error reading file '%s': %v\n " , fileName , err )
0 commit comments