I'm using co2.exe from: https://github.com/Charles-Pegge/OxygenBasic/blob/master/OxygenBasic040.zip
I have a program that seems to work fine. However, when I delete a commented out line, I get a syntax error:
ERROR: undefined type for u
WORD: string
LINE:
FILE: "main source"
Here are the code diffs:
Comparing files int.bas and save\int8.bas
***** int.bas
255: thech = " ": intch = asc(thech)
256: nexttok()
***** save\int8.bas
255: thech = " ": intch = asc(thech)
256: 'print "initlex2: " thelin cr
257: nexttok()
*****
int8.bas compiles and runs ok. int.bas generates the compiler error shown above. The only difference in the files is the removal of the commented out line, line 256 in int8.bas.
Below is the complete code of the one that does not compile. For me, simply adding the following:
'print "initlex2: " thelin cr
after line 255 allows it to compile.
'Ed Davis. Tiny Basic that can play Star Trek
'Supports: end, list, load, new, run, save
'gosub/return, goto, if, input, print, multi-statement lines (:)
'a single numeric array: @(n), and rnd(n)
'$Filename "int.exe"
includepath "$\inc\"
include "console.inc"
#lookahead
const as integer c_maxlines = 7000, c_maxvars = 26, c_at_max = 1000, c_g_stack = 100, false = 0, true = 1
dim pgm(c_maxlines) as string ' program stored here
dim vars(c_maxvars) as integer ' variable store
dim gstackln(c_g_stack) as integer ' gosub line stack
dim gstacktp(c_g_stack) as integer ' gosub textp stack
dim gsp as integer ' gosub stack index
dim atarry(c_at_max) as integer ' the @ array
dim tok as string, toktype as string ' current token, and it's type
dim thelin as string, thech as string ' current program line, current character
dim intch as integer
dim curline as integer, textp as integer ' position in current line
dim num as integer ' last number read by scanner
dim errors as boolean
dim timestart as double
call main()
sub main()
gsp = 0
do
errors = false
print("> ")
pgm(0) = myinput()
if pgm(0) <> "" then
initlex(0)
if toktype = "number" then
validlinenum()
pgm(num) = mid(pgm(0), textp, len(pgm(0)) - textp + 1)
else
if not docmd() then exit sub
end if
end if
loop
end sub
function docmd() as boolean
do
if accept("bye") or accept("quit") then
return false
elseif accept("end") or accept("stop") then
return true
elseif accept("list") then
liststmt(): return true
elseif accept("run") then
runstmt()
elseif accept("goto") then
gotostmt()
elseif accept("if") then
ifstmt()
elseif accept("print") or accept("?") then
call printstmt()
elseif accept("@") then
arrassn()
elseif accept(":") then
' just continue
elseif toktype = "ident" then
assign()
elseif tok = "" then
' handled below
else
print "unknown command: " tok cr: return true
end if
if errors then return true
if curline > c_maxlines then return true
while tok = ""
if curline = 0 or curline >= c_maxlines then return true
initlex(curline + 1)
end while
loop
end function
sub assign()
dim var as integer
var = getvarindex(): nexttok()
expect("=")
vars(var) = expression(0)
end sub
sub arrassn() ' array assignment: @(expr) = expr
dim n as integer, atndx as integer
atndx = parenexpr()
if tok <> "=" then
print "Array Assign: Expecting '=', found: " & tok & cr: errors = true
else
nexttok() ' skip the "="
n = expression(0)
atarry(atndx) = n
end if
end sub
sub ifstmt()
dim b as boolean
if expression(0) = 0 then skipx(): exit sub
b = accept("then") ' "then" is optional
if toktype = "number" then gotostmt()
end sub
sub liststmt()
dim i as integer
for i = 1 to c_maxlines
if pgm(i) <> "" then print i & " " & pgm(i) & cr
next i
print cr
end sub
sub printstmt
dim printnl as boolean
printnl = true
while tok <> ":" and tok <> ""
printnl = true
if toktype = "string" then
print mid(tok, 2)
nexttok()
else
print ltrim(str(expression(0)))
end if
if accept(",") then
print " "
printnl = false
elseif accept(";") then
printnl = false
else
exit do
end if
end while
if printnl then print " " cr
end sub
sub runstmt()
clearvars()
initlex(1)
end sub
sub gotostmt()
num = expression(0)
validlinenum()
initlex(num)
end sub
sub validlinenum()
if num <= 0 or num > c_maxlines then print "Line number out of range" & cr: errors = true
end sub
sub clearvars()
dim i as integer
for i = 1 to c_maxvars
vars(i) = 0
next i
gsp = 0
end sub
function parenexpr() as integer
dim n as integer
expect("("): if errors then return 0
n = expression(0)
expect(")")
return n
end function
function expression(minprec as integer) as integer
dim n as integer
' handle numeric operands - numbers and unary operators
if accept("-") then
n = -expression(4)
elseif accept("+") then
n = expression(4)
elseif tok = "(" then
n = parenexpr()
elseif accept("rnd") then
n = rnd() * parenexpr()
elseif toktype = "number" then
n = num: nexttok()
elseif toktype = "ident" then
n = vars(getvarindex()): nexttok()
elseif accept("@") then
n = atarry(parenexpr())
else
print "syntax error: expecting an operand, found: " tok & cr: errors = true: return 0
end if
do ' while binary operator and precedence of tok >= minprec
if minprec <= 1 and tok = "=" then
nexttok(): n = Convert.ToInt32(n = expression(2))
elseif minprec <= 1 and tok = "<" then
nexttok(): n = Convert.ToInt32(n < expression(2))
elseif minprec <= 1 and tok = ">" then
nexttok(): n = Convert.ToInt32(n > expression(2))
elseif minprec <= 1 and tok = "<>" then
nexttok(): n = Convert.ToInt32(n <> expression(2))
elseif minprec <= 1 and tok = "<=" then
nexttok(): n = Convert.ToInt32(n <= expression(2))
elseif minprec <= 1 and tok = ">=" then
nexttok(): n = Convert.ToInt32(n >= expression(2))
elseif minprec <= 2 and tok = "+" then
nexttok(): n = n + expression(3)
elseif minprec <= 2 and tok = "-" then
nexttok(): n = n - expression(3)
elseif minprec <= 3 and tok = "*" then
nexttok(): n = n * expression(4)
elseif minprec <= 3 and tok = "/" then
nexttok(): n = n \ expression(4)
else
exit do
end if
loop
return n
end function
function getvarindex() as integer
if toktype <> "ident" then print "Not a variable:" & tok cr: errors = true: return 0
return asc(left(tok, 1)) - asc("a")
end function
sub expect(s as string)
if accept(s) then exit sub
print "expected: " s cr: errors = true
end sub
function accept(s as string) as boolean
if tok = s then nexttok(): return true
return false
end function
sub initlex(n as integer)
curline = n
textp = 1
initlex2()
end sub
sub initlex2()
thelin = pgm(curline)
thech = " ": intch = asc(thech)
nexttok()
end sub
sub skipx()
'print "in skip" cr: getkey()
tok = "": toktype = "": thech = "": intch = -1
textp = len(thelin) + 1
'print "skipping " cr
end sub
sub nexttok()
'print "nexttok, thelin:" thelin cr
tok = "": toktype = ""
do
if thech = "" then exit sub
if intch > asc(" ") then exit do
getch()
loop
toktype = "punct"
tok = thech + mid(thelin, textp, 1)
if tok = ">=" or tok = "<=" or tok = "<>" then
getch(): getch(): exit sub
end if
'print "nexttok before instr: " tok cr
tok = left(tok, 1)
if instr("()*+,-/:;<=>?@", tok) > 0 then getch(): exit sub
if tok = chr(34) then readstr(): exit sub ' double quote
'print "nexttok before ident: " tok cr
if (intch >= asc("a") and intch <= asc("z")) or (intch >= asc("A") and intch <= asc("Z")) then
readident()
if tok = "rem" then skipx()
exit sub
end if
'print "nexttok before readint: " tok cr
if intch >= asc("0") and intch <= asc("9") then readint(): exit sub
'print "nexttok before chr(39): " tok cr
if tok = chr(39) then skipx(): exit sub 'single quote
toktype = ""
print "What?" chr(intch) thelin cr: getch(): errors = true
getkey()
end sub
' leave the " as the beginning of the string, so it won't get confused with other tokens
' especially in the print routines
sub readstr()
toktype = "string"
getch()
do
if thech = "" then print "String not terminated" cr: errors = true: exit sub
if thech = chr(34) then exit do
tok = tok + thech
getch()
loop
getch()
'print "readstr: " tok cr
end sub
sub readint()
tok = "": toktype = "number"
do
if intch = -1 then exit do
if intch >= asc("0") and intch <= asc("9") then
tok = tok + thech
getch()
else
exit do
end if
loop
num = val(tok)
'print "readint: " tok " " num cr
end sub
sub readident()
'print "in readident:" cr
tok = "": toktype = "ident"
do
if intch = -1 then exit do
if (intch >= asc("a") and intch <= asc("z")) or (intch >= asc("A") and intch <= asc("Z")) then
tok = tok + lcase(thech)
'print "readident - concat: " tok
'getkey(): print cr
getch()
else
exit do
end if
loop
'print "readident: " tok
'print cr
end sub
sub getch()
'print("in getch")
' Any more text on this line?
if textp > len(thelin) then thech = "": intch = -1: exit sub
thech = mid(thelin, textp, 1)
intch = asc(thech)
textp = textp + 1
end sub
function myinput() as string
string s
' print "myinput" cr
' getkey()
s = input()
s = left(s, len(s) - 2)
return s
end function
function rnd() as integer
return 42
end function
Thanks for any help!
Hi Ed,
could you try using equates or defs instead of consts and see if that makes any difference:
''const as integer c_maxlines = 7000, c_maxvars = 26, c_at_max = 1000, c_g_stack = 100, false = 0, true = 1
% c_maxlines = 7000
% c_maxvars = 26
% c_at_max = 1000
% c_g_stack = 100
% false = 0
% true = 1
I'm currently reviewing constants for version 050. They give me a semantic headache. Are they like equates or are they like immutable variables which have a one time assignment at run-time ?
Quote from: Charles Pegge on July 19, 2022, 12:22:53 PM
could you try using equates or defs instead of consts and see if that makes any difference:
Yep, that fixed it! Thanks!