-- Natural language compiler, outputs lua code -- (C) rnd 2021 -- TODO: add IF: if condition arg1 ACTION1 else ACTION2 ? -- ADD SUBROUTINE: sub NAME = enter subroutine definition mode, sub end = ends definition mode if not init then init = true dtext = {}; dout = function(text) dtext[#dtext+1] = text end text = [[ if cond1 value action1 and action2 and action3 else actiona1 and actiona2 ]] translate = { -- dictionary of used words ["forward"] = "forward", ["backward"] = "backward", ["left"] = "left", ["right"] = "right", ["random"] = "random", ["dirt"] = "default:dirt", ["wood"]= "default:wood", ["cobble"] = "default:cobble", } cmds = { ["if"] = function(code,ibeg,iend) -- if COND value ACTION1 and ACTION2 and ... ACTIONn else(optional) ACTION1 and ... and ACTIONm -- COND: 'see' nodename (block right in front), 'var = value' value of variable?,... local ELSE = " else" local AND = " and" local i,j,condtype,value; condtype, j = get_next_word(code,ibeg,iend) local out = {}; dout(condtype) if condtype== "see" then value, j = get_next_word(code,j,iend) value = translate(value or ""); if not minetest.registered_nodename(value) then say("error: unknown block name " .. value .. "used in 'if'") return "" end out[#out+1] = "if read_node.forward() == " .. value .. " then "; else say("error: unknown condition " .. condtype .. " used in 'if'") return "" end end -- now after j left: ACTION1 else(optional) ACTION2, ACTION can be multiple, separated by ' and ' -- parse and before else local k = j; lcoal cmds = {} while k do k = string.find(code,AND,j) if k and k 'hello', 6 get_next_word = function(code, ibeg,iend) -- attempt to return next word, starting from position ibeg. returns word, index after word if not ibeg or not iend then return end local j = string.find(code,"%w",ibeg); -- where is start of word? if not j or j>iend then return "", iend+1 end -- no words present ibeg = j; j = string.find(code,"%W",j);--where is end of word? if not j or j>iend then return string.sub(code,ibeg,iend-1),iend+1 end return string.sub(code,ibeg,j-1), j end parse_code = function(code) local out = {}; local ibeg,iend,word; local clen = string.len(code) local step =0 iend = 1; ibeg = 1; while step < 10 do if ibeg>clen then break end step = step+1 iend = string.find(code, "\n", ibeg) if not iend then iend = clen end -- get out of loop, no more lines to process word, ibeg = get_next_word(code,ibeg,iend) --dout("rem " .. string.sub(code,ibeg,iend)) --dout("Dword '" .. word .. "' " .. ibeg .. " " .. iend) local cmd = cmds[word]; if cmd then out[#out+1],ibeg = cmd(code,ibeg,iend) end if not ibeg then ibeg = iend+1 end if ibeg<=iend then -- still some space remaining in line, last parameter is repetition local count,i count,i = get_next_word(code,ibeg,iend); count = tonumber(count) or 1 if count>9 then count = 9 elseif count<1 then count=1 end if count > 1 then out[#out] = "for i=1,"..count.. " do " .. out[#out] .. " end" end end ibeg = iend +1 -- go new line end return table.concat(out,"\n") end self.label(parse_code(text) .. "\n\n" .. table.concat(dtext,"\n")) end