123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- --[[
- SaferLua [safer_lua]
- ====================
- Copyright (C) 2017-2020 Joachim Stolberg
- AGPL v3
- See LICENSE.txt for more information
- scanner.lua:
- ]]--
- local function trim(s)
- return (s:gsub("^%s*(.-)%s*$", "%1"))
- end
- function safer_lua:word(ch, pttrn)
- local word = ""
- while ch:match(pttrn) do
- word = word .. ch
- self.pos = self.pos + 1
- ch = self.line:sub(self.pos, self.pos)
- end
- return word
- end
- function safer_lua:string(pttrn)
- self.pos = self.pos + 1
- local ch = self.line:sub(self.pos, self.pos)
- while not ch:match(pttrn) and self.pos < #self.line do
- if ch == "\\" then
- self.pos = self.pos + 1
- end
- self.pos = self.pos + 1
- ch = self.line:sub(self.pos, self.pos)
- end
- self.pos = self.pos + 1
- -- result is not needed
- end
- local function lines(str)
- local t = {}
- local function helper(line)
- table.insert(t, line)
- return ""
- end
- helper((str:gsub("(.-)\r?\n", helper)))
- return t
- end
- function safer_lua:scanner(text)
- local lToken = {}
- for idx, line in ipairs(lines(text)) do
- self.line = line
- self.pos = 1
- self.line = trim(self.line)
- self.line = string.split(self.line, "--", true, 1)[1]
- table.insert(lToken, idx) -- line number
- if self.line then
- -- devide line in tokens
- while true do
- if self.pos > #self.line then break end
- local ch = self.line:sub(self.pos, self.pos)
- if ch:match("[%u%l_]") then -- identifier?
- table.insert(lToken, self:word(ch, "[%w_]"))
- elseif ch:match("[%d]") then -- number?
- table.insert(lToken, self:word(ch, "[%d%xx]"))
- elseif ch:match("'") then -- string?
- self:string("'")
- elseif ch:match('"') then -- string?
- self:string('"')
- elseif ch:match("[%s]") then -- Space?
- self.pos = self.pos + 1
- elseif ch:match("[:{}]") then -- critical tokens?
- table.insert(lToken,ch)
- self.pos = self.pos + 1
- else
- self.pos = self.pos + 1
- end
- end
- end
- end
- return lToken
- end
- local InvalidKeywords = {
- ["while"] = true,
- ["repeat"] = true,
- ["until"] = true,
- ["for"] = true,
- ["range"] = true,
- --["function"] = true,
- ["_G"] = true,
- ["__load"] = true,
- ["__dump"] = true,
- }
- local InvalidChars = {
- [":"] = true,
- ["{"] = true,
- ["["] = true,
- ["]"] = true,
- ["}"] = true,
- }
- function safer_lua:check(pos, text, label, err_clbk)
- local lToken = self:scanner(text)
- local lineno = 0
- local errno = 0
- for idx,token in ipairs(lToken) do
- if type(token) == "number" then
- lineno = token
- elseif InvalidKeywords[token] then
- if token == "for" then
- -- invalid for statement?
- if lToken[idx + 3] == "in" and lToken[idx + 5] == "next" then
- --
- elseif lToken[idx + 2] == "in" and lToken[idx + 3] == "range" then
- --
- else
- err_clbk(pos, label..":"..lineno..": Invalid use of 'for'")
- errno = errno + 1
- end
- elseif token == "range" then
- if lToken[idx - 1] ~= "in" then
- err_clbk(pos, label..":"..lineno..": Invalid use of 'range'")
- errno = errno + 1
- end
- else
- err_clbk(pos, label..":"..lineno..": Invalid keyword '"..token.."'")
- errno = errno + 1
- end
- elseif InvalidChars[token] then
- err_clbk(pos, label..":"..lineno..": Invalid character '"..token.."'")
- errno = errno + 1
- end
- end
- return errno
- end
|