Smaller than Tinybasic.bas (450 lines), this SmallBASIC interpreter offers an in folder IDE in less than 100 lines of code! No punctuation is used for syntax (though . is command for print line ; is command print no CR + LF and ? is command for input). Variables are limited to lower case letters a-z. Notepad is used for editor in IDE but Linux users could change line to equivalent editor. Like Tinybasic, GOSUB is available. Unlike Tinybasic, no line numbers are needed but line labels are available for GO option. Also unlike Tinybasic, modern DO... LOOP and IF... ELSE... FI code blocks are available.
t="Nano3":color 11,1:for s=160 to 4 step -4:cls:w=window():w.setfont(s,"pt",0,0)
at(xmax-txtw(t))/2,(ymax-txth(t))/2:? t:delay 1:next:w.setfont(16,"pt",0,0)
label restart
color 0, 11:cls:anyfile=files("*nano3.txt"):sort anyfile:? "nano3 Files:":?
for i = 0 to ubound(anyfile):? i,anyfile(i):next
? : input "Enter file NUMBER (any else quits) > ",flnm
if isnumber(flnm) then
if flnm >= 0 and flmn <=ubound(anyfile) then : getfile = anyfile(flnm) : tload getfile, p : else : end : fi
else : end : fi
color 7, 1 : cls: for i = 0 to ubound(p):? i, p(i) : next
?:? "n(New) e(Edit) r(Run) k(Kill) f(Files) q(Quits)":input cmd
select case left(cmd,1)
case "n" : open "untitled nano3.txt" for output as #1
print #1, "nano3.txt for Nano3.bas (B+=MGA) "+right(date,4)+"-"+mid(date,4,2)+"-"+left(date,2): close #1
run "notepad untitled nano3.txt": goto restart
case "e" : run "notepad "+ getfile : goto restart
case "f" : goto restart
case "k" : kill getfile : goto restart
case "q" : end
case "r" : color 7, 0 : cls : dim v(25), w(250), stk() : cl = 0 : si = 0
label readline
w1 = word(p(cl), 1) : w2 = word(p(cl), 2)
for i = 2 to 250 : ws = word(p(cl), i) : cvtValue ws : w(i) = ws : next
if w1 = "go" then
f = 0 : for i = 0 to ubound(p)
if word(p(i), 1) = "mark" and word(p(i), 2) = word(p(cl), 2) then cl = i : f = 1: exit for
next
if f = 0 then ? "Error: could not find go mark ";word(p(cl), 2) : goto fini
elif w1 = "cls":cls
elif w1 = "at":at val(w(2)), val(w(3))
elif w1 = "wait":delay val(w(2))
elif w1 = "solve":v(6)=v(0)*v(4)-v(1)*v(3):if v(6)<>0 then v(23)=(v(2)*v(4)-v(1)*v(5))/v(6):v(24)=(v(0)*v(5)-v(2)*v(3))/v(6)
elif w1 = "?":vn=asc(w2)-97:wn=3:while w(wn) <> "":? w(wn);" ";:wn++:wend:input "";temp:v(vn)=temp
elif w1 = "." or w1 = ";":wn=2:while w(wn)<>"":? w(wn);" ";:wn++:wend:if w1 = "." then ?
elif w1 = "loop" : c = 1 : f = 0
for i = cl - 1 to 0 step -1 : fw = word(p(i), 1)
if fw = "do" then
c -- : if c = 0 then cl = i : f = 1 : exit for
elif fw = "loop" : c ++ : fi
next
if f = 0 then ? "Error: could not find do to match loop on line ";cl : goto fini
elif w1 = "exit" : c = 1 : f = 0
for i = cl + 1 to ubound(p)
fw = word(p(i), 1)
if fw = "loop" then
c -- : if c = 0 then cl = i : f = 1 : exit for
elif fw = "do" : c ++ : fi
next
if f = 0 then ? "Error: could not find loop to match exit on line ";cl : goto fini
elif w1 = "if" : es = "" : for i = 2 to 250 : es = es + w(i) : next : if eval(es) = 0 then cl = find(cl)
elif w1 = "else" : cl = find(cl)
elif len(w1) = 1 and asc(w1) > 96 and asc(w1) < 123 and w2 = "="
es = "" : for i = 3 to 250 : es = es + w(i) : next : v(asc(w1) - 97) = eval(es)
elif w1 = "end" : goto fini
elif w1 = "sub" : f = 0 : for i = cl + 1 to ubound(p) : if word(p(i), 1) = "return" then cl = i : : f = 1 : exit for
next : if f = 0 then goto fini
elif w1 = "gosub" : f = 0
for i = 0 to ubound(p) : if word(p(i), 1) = "sub" and word(p(i), 2) = word(p(cl), 2) then f = 1: exit for
next : if f = 0 then ? "Error: could not find sub ";word(p(cl), 2) : goto fini else insert stk, si, cl : cl = i : si++
elif w1 = "return"
si-- : cl = stk(si) : delete stk, si
elif w1 = "ra" : ra
fi : cl += 1 : if cl > ubound(p) then goto fini
goto readline
label fini
?:? getFile;" run is done." :?:input " Press enter to continue...";again:goto restart
case else : goto restart
end select
sub cvtValue(byref wrd)
if len(wrd) = 1 and asc(wrd) > 96 and asc(wrd) < 123 then wrd = v(asc(wrd)-97)
end
func find(ln)
local i, fw, c
c = 1
for i = ln+1 to ubound(p) : fw = word(p(i), 1)
if fw = "fi" then
c --
if c = 0 then find = i : exit func
elif fw = "if"
c ++
elif fw = "else" and c = 1
find = i : exit func
fi
next
? "Error: could not find fi to match line ";ln : goto fini
end
func word(byref source, wnumber) 'base 0, but word(s, 1) is first word if any
local w, p : source = trim(source) : if len(source) = 0 then word = "" : exit func
p = instr(source, " ")
while p > 0 : source = mid(source, 1, p) + mid(source, p + 2, len(source) - p - 1) : p = instr(source, " ") : wend
split source, " ", w : if wnumber > 0 and ubound(w) + 1 >= wnumber then word = w(wnumber - 1) else word = ""
end
func eval(s) 'thanks shian!
chain "env " + enclose("EVAL=") + " + str(" + s + ")" : eval = env("EVAL")
end
sub ra() 'set x, y to origin, set a to rad angle, set r to length if p QB color draw ray
local x,y:x=v(23)+v(17)*cos(v(0)):y=v(24)+v(17)*sin(v(0))
if 0<=v(15) and v(15)<16 then:line v(23),v(24),x,y,v(15):fi:v(23)=x:v(24)=y
end
##################################################################################
# The MIT License (MIT)
# Copyright (c) 2017 B+=MGA
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
##################################################################################
BTW, ' or REM or # or whatever are not needed for comments. To make a comment in a Nano3 program, just don't start the line with a command.
If you make a comment on an IF line after the Boolean expression, it will likely be ignored unless mistaken as part of the expression.
Do not use the lower case a as a word in a print line or input prompt unless you intend the a to be replaced by it's value displayed on screen.
Below is pictured the entire manual for Nano3-2 that is accessible from IDE files listing.