This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
LeDark Lua's profile picture

How to parse/make/do 'IF' statements.

Started by LeDark Lua, 31 July 2015 - 12:17 PM
LeDark Lua #1
Posted 31 July 2015 - 02:17 PM
Well its a dumb question, but im making a Programming language in Lua. I made so that you can make variables assign them, print them make if statemens and so on.

But When I make an if statement it goes like:

:strvar = "Hello, world."
if 1 == 1 then
   print :strvar
stopif

And the if statement == true then run code inside it else dont.
Edited on 31 July 2015 - 01:46 PM
MKlegoman357 #2
Posted 31 July 2015 - 02:19 PM
So, what's the question?
LeDark Lua #3
Posted 31 July 2015 - 02:20 PM
And the if statement == true then run code inside it else dont.

This :|
MKlegoman357 #4
Posted 31 July 2015 - 02:21 PM
You don't know how to make your parser parse the if statement?
LeDark Lua #5
Posted 31 July 2015 - 02:23 PM

tokens[i]..tokens[i+1]:sub(1, 3)..tokens[i+2]..tokens[i+3]:sub(1, 3)..tokens[i+4]=="IFNUMEQEQNUMTHEN" then
if tokens[i+1]:sub(5) == tokens[i+3]:sub(5) then
print("IF SATEMENT EQUALS TRUE")
else
print("IF SATEMENT EQUALS FALSE")
end
Edited on 31 July 2015 - 12:23 PM
LeDark Lua #6
Posted 31 July 2015 - 02:37 PM
This is my lexer. This is used in parser.

[ 1 = VAR::test, 2 = EQUALS, 3 = STRING:"Cool dude.", 4 = IF, 5 = NUM:1, 6 = EQEQ, 7 = NUM:1, 8 = THEN, 9 = PRINT, 10 = VAR::test, 11 = END, 12 = PRINT, 13 = STRING:"Cool dude.", 14 = PRINT, 15 = EXPR:2*5+5, 16 = PRINT, 17 = NUM:15, ]
Edited on 31 July 2015 - 12:37 PM
MKlegoman357 #7
Posted 31 July 2015 - 03:10 PM
Well, I haven't done any kind of programming language parser or virtual machine yet. But what the virtual machine would do is simply execute the statements one by one. When it hits the if statement it then evaluates the condition and if that condition is true then run the code of the if block.
LeDark Lua #8
Posted 31 July 2015 - 03:11 PM
So yeah, if its false? How to NOT execute the code below untill it hits END?
MKlegoman357 #9
Posted 31 July 2015 - 03:13 PM
skip to the end of the if statement? It really depends on the virtual machine running your code.
LeDark Lua #10
Posted 31 July 2015 - 03:15 PM
Virtual Machine is ComputerCraft. I can paste the whole code with parser and lexer into PrivateMessage.
MKlegoman357 #11
Posted 31 July 2015 - 03:20 PM
Do it here, so someone with better experience than me could reply. By the 'virtual machine' I'm talking about the actual program which processes and runs the parsed code. I think you're doing one thing wrong. The parser is supposed to take the code from the lexer and then group it together, not run it. There should be a separate program which actually runs the thing that the parser returns. I don't really want to comment too much, I know there are people on this forums who have made their own programming languages and understand everything better.
LeDark Lua #12
Posted 31 July 2015 - 03:22 PM
Spoiler

tArgs={ ... }

term.setCursorPos(1, 1)
term.clear()
print("BLML [ BasicLuaMadeLanguage ]\n")

symbols={}

local function openFile(file)
local f=fs.open(file, "r")
local __str=f.readAll()
f.close()
return __str
end

local function append(tokens)
local __str="[ "
for n, v in pairs(tokens) do
__str=__str..n.." = "..v..", "
end
__str=__str.."]"
return __str
end

local function doASSIGN(varName, varValue)
local __varNm=varName:sub(5)
symbols[__varNm]=varValue
end

local function getVARIABLE(varName)
if symbols[varName:sub(5)] then
return symbols[varName:sub(5)]
else
return "Undefined variable: "..varName:sub(5)
end
end

local function getINPUT(str, varName)
local __str=str:sub(2, str:len()-1)
write(__str)
local inp=read()
symbols[varName]=inp
end

local function parse(tokens)
local i=1
while i <= #tokens do
local __secTok=tokens[i+1]
if tokens[i]=="END" then
i=i+1
elseif tokens[i]..__secTok:sub(1,6)=="PRINTSTRING" or tokens[i]..__secTok:sub(1,3)=="PRINTNUM" or tokens[i]..__secTok:sub(1,4)=="PRINTEXPR" or tokens[i]..__secTok:sub(1,3)=="PRINTVAR" then
if tokens[i+1]:sub(1, 6) == "STRING" then
print(tokens[i+1]:sub(9, tokens[i+1]:len()-1))
elseif tokens[i+1]:sub(1, 3) == "NUM" then
print(tokens[i+1]:sub(5))
elseif tokens[i+1]:sub(1, 4) == "EXPR" then
print(loadstring("return "..tokens[i+1]:sub(6))())
elseif tokens[i+1]:sub(1, 3) == "VAR" then
print(getVARIABLE(tokens[i+1]))
end
i=i+2
elseif tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 6)=="VAREQUALSSTRING" or tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 3)=="VAREQUALSNUM" or tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 4)=="VAREQUALSEXPR" or tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 3)=="VAREQUALSVAR" then
if tokens[i+2]:sub(1, 6) == "STRING" then
doASSIGN(tokens[i], tokens[i+2]:sub(9, tokens[i+2]:len()-1))
elseif tokens[i+2]:sub(1, 3) == "NUM" then
doASSIGN(tokens[i], tokens[i+2]:sub(5))
elseif tokens[i+2]:sub(1, 4) == "EXPR" then
local __retStr=tokens[i+2]:sub(6)
doASSIGN(tokens[i], loadstring("return "..__retStr)())
elseif tokens[i+2]:sub(1, 3) == "VAR" then
doASSIGN(tokens[i], getVARIABLE(tokens[i+2]))
end
i=i+3
elseif tokens[i]..tokens[i+1]:sub(1, 6)..tokens[i+2]:sub(1, 3)=="INPUTSTRINGVAR" then
getINPUT(tokens[i+1]:sub(8), tokens[i+2]:sub(5))
i=i+3
elseif
tokens[i]..tokens[i+1]:sub(1, 3)..tokens[i+2]..tokens[i+3]:sub(1, 3)..tokens[i+4]=="IFNUMEQEQNUMTHEN" then
if tokens[i+1]:sub(5) == tokens[i+3]:sub(5) then
print("IF SATEMENT EQUALS TRUE")
else
print("IF SATEMENT EQUALS FALSE")
end
i=i+5

end
end
--print(append(symbols))
end

local function lex(filecontents)
local tok=""
local state=0
local varStarted=0
local expr=""
local var=""
local __str=""
local isexpr=0
local tokens={}
local n = ""
for i=1, #filecontents do
char = filecontents:sub(i, i)
tok = tok..char
if tok==" " then
if state==0 then
tok=""
else
tok=" "
end
elseif tok=="\n" or tok=="<EOF>" then
if #expr>0 and isexpr==1 then
tokens[#tokens+1]="EXPR:"..expr
expr=""
isexpr=0
elseif #expr>0 and isexpr==0 then
tokens[#tokens+1]="NUM:"..expr
expr=""
elseif #var>0 then
tokens[#tokens+1]="VAR:"..var
var = ""
varStarted=0
end
tok=""
elseif tok=="=" and state==0 then
if #expr>0 and isexpr==0 then
tokens[#tokens+1]="NUM:"..expr
expr=""
end
if #var>0 then
tokens[#tokens+1]="VAR:"..var
var = ""
varStarted=0
end
if tokens[#tokens] == "EQUALS" then
tokens[#tokens]="EQEQ"
else
tokens[#tokens+1]="EQUALS"
end
tok=""
elseif tok==":" and state==0 then
varStarted=1
var = var..tok
tok=""
elseif varStarted==1 then
if tok=="<" or tok==">" then
if #var>0 then
tokens[#tokens+1]="VAR:"..var
var = ""
varStarted=0
end
end
var=var..tok
tok=""
elseif tok=="print" or tok=="PRINT" then
tokens[#tokens+1]="PRINT"
tok=""
elseif tok=="INPUT" or tok=="input" then
tokens[#tokens+1]="INPUT"
tok=""
elseif tok=="THEN" or tok=="then" then
if #expr>0 and isexpr==0 then
tokens[#tokens+1]="NUM:"..expr
expr=""
end
if #var>0 then
tokens[#tokens+1]="VAR:"..var
var = ""
varStarted=0
end
tokens[#tokens+1]="THEN"
tok=""
elseif tok=="END" or tok=="end" then
tokens[#tokens+1]="END"
tok=""
elseif tok=="IF" or tok=="if" then
tokens[#tokens+1]="IF"
tok=""
elseif tok=="0" or tok=="1" or tok=="2" or tok=="3" or tok=="4" or tok=="5" or tok=="6" or tok=="7" or tok=="8" or tok=="9" then
expr=expr..tok
tok=""
elseif tok=="+" or tok=="-" or tok=="/" or tok=="*" or tok=="(" or tok==")" or tok=="%" then
isexpr=1
expr=expr..tok
tok=""
elseif tok=="\t" then
tok=""
elseif tok=="\"" or tok==" \"" then
if state==0 then
state=1
elseif state==1 then
tokens[#tokens+1]="STRING:"..__str.."\""
__str=""
state=0
tok=""
end
elseif state==1 then
__str=__str..tok
tok=""
end
end
failas=fs.open("append", "w")
failas.write(append(tokens))
failas.close()
print(append(tokens))
return tokens
--return ""
end

local function main()
local content=openFile(tArgs[1])
content=content.."<EOF>"
local toks=lex(content)
parse(toks)
end

main()

No one can help?
Edited on 31 July 2015 - 03:31 PM
Lyqyd #13
Posted 31 July 2015 - 05:31 PM
Be patient and don't bump your topic unless it's been weeks without a reply.
LeDark Lua #14
Posted 31 July 2015 - 05:51 PM
Oh ok. Lyquid, can you help?
Edited on 31 July 2015 - 03:52 PM
ardera #15
Posted 01 August 2015 - 04:05 PM
Where's the problem? just parse the statement, see if it's true and if it is, run the code inside the if-block
LeDark Lua #16
Posted 01 August 2015 - 04:21 PM
Ok, i dont know if you saw the code, but you came here and just said your opinion. Well ill try to explain, again. So I parse the if statement and now if its true it will continue to parse the above code and when its not I will not. My problem is HOW TO NOT parse the above code if the IF statement is false.
Edited on 01 August 2015 - 02:21 PM
LeDark Lua #17
Posted 01 August 2015 - 04:48 PM
Oh I got it guys, I just needed to make a boolean to check if parse the code below. Thanks for the comments and trying to help me fix it :)/>
flaghacker #18
Posted 01 August 2015 - 05:44 PM
Oh I got it guys, I just needed to make a boolean to check if parse the code below. Thanks for the comments and trying to help me fix it :)/>/>

Hold on a sec - that sounds like a horrible design to me. Does it work for nested if-statements? How are you going to approach loops?

I'm not trying to be harsh here :)/>
LeDark Lua #19
Posted 01 August 2015 - 06:00 PM
Ye booleans are baaaad :D/> I need a better answer.
LeDark Lua #20
Posted 01 August 2015 - 06:09 PM
This is what I did for my new parser:

Spoiler

local i=1
local __parseBelowCount=1
while i <= #tokens and __THIS.TERM==false do
local __secTok=tokens[i+1]
if __parseBelowCount==1 then
if tokens[i]=="END" then
i=i+1
elseif tokens[i]..__secTok:sub(1,6)=="PRINTSTRING" or tokens[i]..__secTok:sub(1,3)=="PRINTNUM" or tokens[i]..__secTok:sub(1,4)=="PRINTEXPR" or tokens[i]..__secTok:sub(1,3)=="PRINTVAR" then
if tokens[i+1]:sub(1, 6) == "STRING" then
print(tokens[i+1]:sub(9, tokens[i+1]:len()-1))
elseif tokens[i+1]:sub(1, 3) == "NUM" then
print(tokens[i+1]:sub(5))
elseif tokens[i+1]:sub(1, 4) == "EXPR" then
print(loadstring("return "..tokens[i+1]:sub(6))())
elseif tokens[i+1]:sub(1, 3) == "VAR" then
print(getVARIABLE(tokens[i+1]))
end
i=i+2
elseif tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 6)=="VAREQUALSSTRING" or tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 3)=="VAREQUALSNUM" or tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 4)=="VAREQUALSEXPR" or tokens[i]:sub(1, 3)..tokens[i+1]..tokens[i+2]:sub(1, 3)=="VAREQUALSVAR" then
if tokens[i+2]:sub(1, 6) == "STRING" then
doASSIGN(tokens[i], tokens[i+2]:sub(9, tokens[i+2]:len()-1))
elseif tokens[i+2]:sub(1, 3) == "NUM" then
doASSIGN(tokens[i], tokens[i+2]:sub(5))
elseif tokens[i+2]:sub(1, 4) == "EXPR" then
local __retStr=tokens[i+2]:sub(6)
doASSIGN(tokens[i], loadstring("return "..__retStr)())
elseif tokens[i+2]:sub(1, 3) == "VAR" then
doASSIGN(tokens[i], getVARIABLE(tokens[i+2]))
end
i=i+3
elseif tokens[i]..tokens[i+1]:sub(1, 6)..tokens[i+2]:sub(1, 3)=="INPUTSTRINGVAR" then
getINPUT(tokens[i+1]:sub(8), tokens[i+2]:sub(5))
i=i+3
elseif tokens[i]..tokens[i+1]:sub(1, 3)..tokens[i+2]..tokens[i+3]:sub(1, 3)..tokens[i+4]=="IFNUMEQEQNUMTHEN" then
if tokens[i+1]:sub(5) == tokens[i+3]:sub(5) then
--Do nothing...
else
__parseBelowCount=__parseBelowCount+1
end
i=i+5
elseif tokens[i]..tokens[i+1]:sub(1, 3)..tokens[i+2]..tokens[i+3]:sub(1, 3)..tokens[i+4]=="IFVAREQEQNUMTHEN" then
if getVARIABLE(tokens[i+1]) == tokens[i+3]:sub(5) then
--Do nothing...
else
__parseBelowCount=__parseBelowCount+1
end
i=i+5
end
elseif __parseBelowCount>1 then
if tokens[i] == "IF" then
__parseBelowCount=__parseBelowCount+1
end
if tokens[i] == "END" then
i=i+1
__parseBelowCount=__parseBelowCount-1
else
i=i+1
end
end
end

This works fine with if statemens within if statement untill infinity.