X Tutup
Skip to content

Commit bd03cad

Browse files
committed
sVB 3.5.2 and Sahla 1.0.0.3
1 parent bbceabc commit bd03cad

File tree

17 files changed

+335
-107
lines changed

17 files changed

+335
-107
lines changed

Samples/Sahla Programming Language/Sahla/Global.sb

Lines changed: 157 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ LineIndex = 1 ' Our program counter
33
Tokens = {} ' Tokens array for the current line
44
Vars = {} ' Array containing variables of current proogram
55
WhileStack = "WhileStack" ' Stack name for WHILE loops
6-
LoopStack = "LoopStack" ' Stack name for FOR loops
6+
ForStack = "ForStack" ' Stack name for FOR loops
77

88
EditorTextBox = ""
99
LblFormat = ""
@@ -133,6 +133,9 @@ EndSub
133133
Sub Run()
134134
TW.Clear()
135135
Vars = {}
136+
Stack.Clear(WhileStack)
137+
Stack.Clear(ForStack)
138+
136139
Statements = Text.Split(EditorTextBox.Text, Chars.Lf, False, False)
137140
LineIndex = 1
138141
statementsCount = Statements.Count
@@ -145,11 +148,13 @@ Sub Run()
145148
EndIf
146149

147150
If TW.IsClosed Then
151+
EditorTextBox.Focus()
148152
Return
149153
EndIf
150154
Wend
151155

152156
Terminate(ProEndMsg, False)
157+
EditorTextBox.Focus()
153158
EndSub
154159

155160
Sub EndProgram()
@@ -326,22 +331,26 @@ EndFunction
326331

327332
Sub ProcessExitLoop(line)
328333
If Stack.GetCount(WhileStack) > 0 Then
329-
LineIndex = FindClosingToken(_While, _Wend, LineIndex + 1)
330-
If LineIndex = 0 Then
331-
ReportError("'" & _Wend & "' غير موجودة", line, 1)
332-
Return
333-
Else
334-
Stack.PopValue(WhileStack)
335-
EndIf
336-
337-
ElseIf Stack.GetCount(LoopStack) > 0 Then
338-
LineIndex = FindClosingToken(_For, _Next, LineIndex + 1)
339-
If LineIndex = 0 Then
340-
ReportError("'" & _Next & "' غير موجودة", line, 1)
341-
Return
342-
EndIf
343-
Stack.PopValue(LoopStack)
334+
lastWhile = Stack.PeekValue(WhileStack)
335+
lastWhileLine = lastWhile[1]
336+
Else
337+
lastWhileLine = 0
338+
EndIf
339+
340+
If Stack.GetCount(ForStack) > 0 Then
341+
lastFor = Stack.PeekValue(ForStack)
342+
lastForLine = lastFor[4]
343+
Else
344+
lastForLine = 0
345+
EndIf
346+
347+
If lastWhileLine > lastForLine Then
348+
LineIndex = lastWhile[2]
349+
Stack.PopValue(WhileStack)
344350

351+
ElseIf lastForLine > 0 Then
352+
LineIndex = lastFor[5]
353+
Stack.PopValue(ForStack)
345354
Else
346355
ReportError("لا توجد حلقة مفتوحة للخروج منها.", line, 1)
347356
EndIf
@@ -400,29 +409,57 @@ Sub ProcessForLoopHeader()
400409
stepValue = result[1]
401410
EndIf
402411

403-
Vars[varName] = startValue
404-
loopObj = {varName, endValue, stepValue, LineIndex}
405-
Stack.PushValue(LoopStack, loopObj)
412+
nextLineIndex = FindClosingToken(_For, _Next, LineIndex + 1)
413+
If nextLineIndex = 0 Then
414+
ReportError("'" & _Next & " " & varName & "' مفقودة", LineIndex, 1)
415+
Else
416+
Vars[varName] = startValue
417+
loopObj = {varName, endValue, stepValue, LineIndex, nextLineIndex}
418+
Stack.PushValue(ForStack, loopObj)
419+
EndIf
406420
EndSub
407421

408422
Function IsValidVarName(name, line, tokenIndex)
409-
If Text.IsNumeric(name[1]) Or
410-
(Text.GetLength(name) = 1 And Chars.IsLetter(name) = False) Then
411-
ReportError("الاسم '" & name & "' لا يصلح كاسم متغير", line, tokenIndex)
423+
If Text.IsNumeric(name[1]) Then
424+
ReportError("الاسم '" & name & "' لا يصلح كاسم متغير لأنه يبدأ برقم", line, tokenIndex)
425+
Return False
426+
ElseIf name = "_" Then
427+
ReportError("العلامة _ لا تصلح بمفردها كاسم متغير، لكن يمكن أن تستخدم ضصمن اسم متغير", line, tokenIndex)
412428
Return False
429+
Else
430+
ForEach c In name
431+
If (c = "_" Or Chars.IsDigit(c) Or Chars.IsLetter(c)) = False Then
432+
ReportError("الاسم '" & name & "' لا يصلح كاسم متغير بسبب وجود الرمز '" & c & "'", line, tokenIndex)
433+
Return False
434+
EndIf
435+
Next
436+
EndIf
437+
438+
Return True
439+
EndFunction
440+
441+
Function IsValidVarName2(name)
442+
If name = _And Or Text.IsNumeric(name[1]) Then
443+
Return False
444+
Else
445+
ForEach c In name
446+
If (c = "_" Or Chars.IsDigit(c) Or Chars.IsLetter(c)) = False Then
447+
Return False
448+
EndIf
449+
Next
413450
EndIf
414451

415452
Return True
416453
EndFunction
417454

418455
Sub ProcessForLoopNext()
419456
varName = Tokens[2][3]
420-
If Stack.GetCount(LoopStack) = 0 Then
457+
If Stack.GetCount(ForStack) = 0 Then
421458
ReportError("لا توجد حلقة تكرار مفتوحة", LineIndex, 1)
422459
Return
423460
EndIf
424461

425-
loopObj = Stack.PeekValue(LoopStack)
462+
loopObj = Stack.PeekValue(ForStack)
426463
If loopObj[1] <> varName Then
427464
ReportError("اسم العداد '" & varName & "' غير صحيح:" & Text.NewLine &
428465
"يجب أن تستخدم '" & loopObj[1] & "'", LineIndex, 2)
@@ -437,7 +474,7 @@ Sub ProcessForLoopNext()
437474
(stepValue < 0 And newVal >= end) Then
438475
LineIndex = loopObj[4] ' loop
439476
Else
440-
Stack.PopValue(LoopStack)
477+
Stack.PopValue(ForStack)
441478
EndIf
442479
EndSub
443480

@@ -449,9 +486,15 @@ Sub ProcessWhileLoopHeader()
449486
Return
450487
EndIf
451488

489+
wendLineIndex = FindClosingToken(_While, _Wend, LineIndex + 1)
490+
If wendLineIndex = 0 Then
491+
ReportError("'" & _Wend & "' مفقودة", LineIndex, 1)
492+
Return
493+
EndIf
494+
452495
condition = result[1]
453496
If condition Then
454-
Stack.PushValue(WhileStack, LineIndex)
497+
Stack.PushValue(WhileStack, {LineIndex, wendLineIndex})
455498
Else
456499
lineId = LineIndex
457500
LineIndex = FindClosingToken(_While, _Wend, LineIndex + 1)
@@ -467,7 +510,8 @@ Sub ProcessWhileLoopEnd()
467510
Return
468511
EndIf
469512

470-
whileLinIndex = Stack.PeekValue(WhileStack)
513+
lastWhile = Stack.PeekValue(WhileStack)
514+
whileLinIndex = lastWhile[1]
471515
Tokenize(Statements[whileLinIndex], whileLinIndex)
472516
result = EvaluateExpression(2)
473517

@@ -519,7 +563,7 @@ Sub ProcessIfBlock()
519563
EndIf
520564

521565
While True
522-
LineIndex = FindNextBranch(LineIndex + 1, {_ElseIf, _Else})
566+
LineIndex = FindNextIfBranch(LineIndex + 1)
523567
Tokenize(Statements[LineIndex], LineIndex)
524568
branchToken = Tokens[1][3]
525569

@@ -583,44 +627,73 @@ Function FindClosingToken(openToken, closeToken, startLine)
583627
nestingLevel = 0
584628
For i = startLine To Statements.Count
585629
statement = Text.Trim(Statements[i])
586-
If statement.StartsWith(openToken) Then
630+
If StartsWithToken(statement, openToken) Then
587631
nestingLevel = nestingLevel + 1
588-
ElseIf statement.StartsWith(closeToken) Then
632+
ElseIf StartsWithToken(statement, closeToken) Then
589633
If nestingLevel = 0 Then
590634
Return i
591635
Else
592636
nestingLevel = nestingLevel - 1
593637
EndIf
638+
639+
' Next conditions prevents messed up blocks
640+
ElseIf StartsWithToken(statement, _If) Then ' Works only with While and For
641+
i = FindClosingToken(_If, _EndIf, i + 1)
642+
If i = 0 Then
643+
Return 0
644+
EndIf
645+
ElseIf StartsWithToken(statement, _While) Then ' Works only with If and For
646+
i = FindClosingToken(_While, _Wend, i + 1)
647+
If i = 0 Then
648+
Return 0
649+
EndIf
650+
ElseIf StartsWithToken(statement, _For) Then ' Works only with If and while
651+
i = FindClosingToken(_For, _Next, i + 1)
652+
If i = 0 Then
653+
Return 0
654+
EndIf
655+
ElseIf StartsWithToken(statement, _EndIf)
656+
Or StartsWithToken(statement, _Wend)
657+
Or StartsWithToken(statement, _Next) Then
658+
Return 0
594659
EndIf
595660
Next
596661
Return 0
597662
EndFunction
598663

599664

600-
Function FindNextBranch(startLine, branchTokens)
665+
Function FindNextIfBranch(startLine)
601666
nestingLevel = 0
602667
For i = startLine To Statements.Count
603668
statement = Text.Trim(Statements[i])
604-
If statement.StartsWith(_If) Then
669+
If StartsWithToken(statement, _If) Then
605670
nestingLevel = nestingLevel + 1
606-
ElseIf statement.StartsWith(_EndIf) Then
671+
ElseIf StartsWithToken(statement, _EndIf) Then
607672
If nestingLevel = 0 Then
608673
Return i
609674
Else
610675
nestingLevel = nestingLevel - 1
611676
EndIf
612677
ElseIf nestingLevel = 0 Then
613-
ForEach token In branchTokens
614-
If statement.StartsWith(token) Then
615-
Return i
616-
EndIf
617-
Next
678+
If StartsWithToken(statement, _ElseIf) Or StartsWithToken(statement, _Else) Then
679+
Return i
680+
EndIf
618681
EndIf
619682
Next
620683

621684
Return 0
622685
EndFunction
623686

687+
Function StartsWithToken(statement, token)
688+
If Text.StartsWith(statement, token) = False Then
689+
Return False
690+
ElseIf statement = token Then
691+
Return True
692+
EndIf
693+
694+
nextChar = statement[Text.GetLength(token) + 1]
695+
Return (nextChar = "_" Or Chars.IsDigit(nextChar) Or Chars.IsLetter(nextChar)) = False
696+
EndFunction
624697

625698
Function EvaluateExpression(start)
626699
result = ParseExpression(start)
@@ -1298,31 +1371,26 @@ Function AutoCompleteBlock()
12981371
spaces = Text.Repeat(" ", prev.Length - word.Length)
12991372

13001373
If word = _If Then
1301-
EditorTextBox.Text =
1302-
Text.Trim(txt.SubText(1, pos - 1)) & " " & "شرط " & Chars.CrLf
1374+
EditorTextBox.SelectedText = " " & "شرط " & Chars.CrLf
13031375
& spaces & " " & Chars.CrLf
1304-
& spaces & _EndIf & Chars.CrLf
1305-
& Text.Trim(txt.SubText(lineEnd + 1, txt.Length - pos))
1376+
& spaces & _EndIf
13061377
EditorTextBox.CaretIndex = pos + 1
13071378
Return 3
13081379

13091380
ElseIf word = _While Then
1310-
EditorTextBox.Text =
1311-
Text.Trim(txt.SubText(1, pos - 1)) & " " & _True & Chars.CrLf
1381+
EditorTextBox.SelectedText =
1382+
" " & _True & Chars.CrLf
13121383
& spaces & spaces & " " & Chars.CrLf
1313-
& spaces & _Wend & Chars.CrLf
1314-
& Text.Trim(txt.SubText(lineEnd + 1, txt.Length - pos))
1384+
& spaces & _Wend
13151385
EditorTextBox.CaretIndex = pos + 1
13161386
Return _True.Length
13171387

13181388
ElseIf word = _For Then
13191389
forVar = GetForVar()
1320-
x = " " & forVar & " = 1 " & _To1 & " 10"
1321-
EditorTextBox.Text =
1322-
Text.Trim(txt.SubText(1, pos - 1)) & x & Chars.CrLf
1390+
EditorTextBox.SelectedText =
1391+
" " & forVar & " = 1 " & _To1 & " 10" & Chars.CrLf
13231392
& spaces & " " & Chars.CrLf
1324-
& spaces & _Next & " " & forVar & Chars.CrLf
1325-
& Text.Trim(txt.SubText(lineEnd + 1, txt.Length - pos))
1393+
& spaces & _Next & " " & forVar
13261394
EditorTextBox.CaretIndex = pos + 1
13271395
Return 1
13281396
EndIf
@@ -1406,7 +1474,7 @@ Function GetVarNames()
14061474
space = Text.IndexOf(line, " ", pos, True)
14071475
If space = 0 Or space = pos - 1 Then
14081476
varName = Text.Trim(Text.GetSubText(line, 1, space - 1))
1409-
If varName <> "" And varName.Contains(" ") = False
1477+
If varName <> "" And IsValidVarName2(varName)
14101478
And Vars.ContainsValue(varName) = False Then
14111479
Vars.Append(varName)
14121480
EndIf
@@ -1415,4 +1483,40 @@ Function GetVarNames()
14151483
Next
14161484

14171485
Return Vars
1418-
EndFunction
1486+
EndFunction
1487+
1488+
Sub FixNextVarName(ixdex, lineText)
1489+
forPos = lineText.IndexOf(_For, 1, False)
1490+
If forPos = 0 Then
1491+
Return
1492+
EndIf
1493+
1494+
Tokenize(lineText, 1)
1495+
varName = Tokens[2][3]
1496+
If varName = "" Then
1497+
Return
1498+
EndIf
1499+
1500+
code = Text.GetSubTextToEnd(EditorTextBox.Text, ixdex)
1501+
Statements = Text.Split(code, Chars.Lf, False, False)
1502+
nextLineIndex = FindClosingToken(_For, _Next, 2)
1503+
If nextLineIndex = 0 Then
1504+
Return
1505+
EndIf
1506+
1507+
Tokenize(Statements[nextLineIndex], nextLineIndex)
1508+
nextVarName = Tokens[2][3]
1509+
1510+
If nextVarName <> varName Then
1511+
lineStart = ixdex
1512+
For i = 1 To nextLineIndex - 1
1513+
lineStart = lineStart + Text.GetLength(Statements[i]) + 1
1514+
Next
1515+
1516+
caretPos = EditorTextBox.CaretIndex
1517+
EditorTextBox.SelectionStart = lineStart + Tokens[2][2] - 1
1518+
EditorTextBox.SelectionLength = Text.GetLength(nextVarName)
1519+
EditorTextBox.SelectedText = varName
1520+
EditorTextBox.CaretIndex = caretPos
1521+
EndIf
1522+
EndSub

Samples/Sahla Programming Language/Sahla/Samples/Even Numbers.shl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ False
1111
اكتب السطر "الأعداد الزوجية من 2 إلى 20:"
1212

1313
من العدد = 2 حتى 20 بزيادة 2
14-
اكتب سطرا العدد
15-
زد العدد
14+
اكتب السطر العدد
15+
زد العدد

0 commit comments

Comments
 (0)
X Tutup