2012-08-29 05:55:11 +00:00
|
|
|
# vim:ts=4:et
|
2012-09-10 03:40:55 +00:00
|
|
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License
|
|
|
|
# as published by the Free Software Foundation; either version 2
|
|
|
|
# of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software Foundation,
|
|
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
#
|
|
|
|
# ##### END GPL LICENSE BLOCK #####
|
|
|
|
|
|
|
|
# <pep8 compliant>
|
2012-08-29 05:55:11 +00:00
|
|
|
|
2012-09-10 05:58:41 +00:00
|
|
|
class ScriptError(Exception):
|
|
|
|
def __init__(self, fname, line, message):
|
|
|
|
Exception.__init__(self, "%s:%d: %s" % (fname, line, message))
|
|
|
|
self.line = line
|
|
|
|
|
2012-08-29 05:55:11 +00:00
|
|
|
class Script:
|
2020-07-17 11:11:44 +00:00
|
|
|
def __init__(self, filename, text, single="{}()':", quotes=True):
|
|
|
|
if text[0:3] == "\xef\xbb\xbf":
|
|
|
|
text = text[3:]
|
|
|
|
elif text[0] == u"\ufeff":
|
|
|
|
text = text[1:]
|
2022-05-27 11:06:33 +00:00
|
|
|
self.token = ""
|
|
|
|
self.unget = False
|
2012-08-29 05:55:11 +00:00
|
|
|
self.text = text
|
|
|
|
self.pos = 0
|
2022-05-27 11:06:33 +00:00
|
|
|
self.filename = filename
|
2012-08-29 05:55:11 +00:00
|
|
|
self.line = 1
|
2022-05-27 11:06:33 +00:00
|
|
|
self.no_quote_lines = False
|
|
|
|
self.single = single
|
|
|
|
self.quotes = quotes
|
2012-09-10 05:58:41 +00:00
|
|
|
def error(self, msg):
|
|
|
|
raise ScriptError(self.filename, self.line, msg)
|
2012-08-29 05:55:11 +00:00
|
|
|
def tokenAvailable(self, crossline=False):
|
|
|
|
if self.unget:
|
|
|
|
return True
|
|
|
|
while self.pos < len(self.text):
|
2012-08-30 04:19:30 +00:00
|
|
|
while self.pos < len(self.text) and self.text[self.pos].isspace():
|
2012-08-29 05:55:11 +00:00
|
|
|
if self.text[self.pos] == "\n":
|
|
|
|
if not crossline:
|
|
|
|
return False
|
|
|
|
self.line += 1
|
|
|
|
self.pos += 1
|
|
|
|
if self.pos == len(self.text):
|
|
|
|
return False
|
|
|
|
if self.text[self.pos] in ["\x1a", "\x04"]:
|
|
|
|
# end of file characters
|
|
|
|
self.pos += 1
|
|
|
|
continue
|
|
|
|
if self.text[self.pos:self.pos + 2] == "//":
|
|
|
|
while (self.pos < len(self.text)
|
|
|
|
and self.text[self.pos] != "\n"):
|
|
|
|
self.pos += 1
|
|
|
|
if self.pos == len(self.text):
|
|
|
|
return False
|
|
|
|
if not crossline:
|
|
|
|
return False
|
|
|
|
continue
|
|
|
|
return True
|
|
|
|
return False
|
2013-11-24 02:21:40 +00:00
|
|
|
def getLine(self):
|
|
|
|
start = self.pos
|
|
|
|
end = start
|
|
|
|
while self.pos < len(self.text):
|
|
|
|
if self.text[self.pos] == "\n":
|
|
|
|
self.line += 1
|
|
|
|
self.pos += 1
|
|
|
|
break
|
|
|
|
if self.text[self.pos:self.pos + 2] == "//":
|
|
|
|
break
|
|
|
|
self.pos += 1
|
|
|
|
end = self.pos
|
|
|
|
if self.unget:
|
|
|
|
self.unget = False
|
|
|
|
self.token = self.token + self.text[start:end]
|
|
|
|
else:
|
|
|
|
self.token = self.text[start:end]
|
|
|
|
return self.pos < len(self.text)
|
2012-08-29 05:55:11 +00:00
|
|
|
def getToken(self, crossline=False):
|
|
|
|
if self.unget:
|
|
|
|
self.unget = False
|
|
|
|
return self.token
|
|
|
|
if not self.tokenAvailable(crossline):
|
|
|
|
if not crossline:
|
2012-09-10 05:58:41 +00:00
|
|
|
self.error("line is incomplete")
|
2012-08-29 05:55:11 +00:00
|
|
|
return None
|
2020-07-17 11:11:44 +00:00
|
|
|
if self.quotes and self.text[self.pos] == "\"":
|
2012-08-29 05:55:11 +00:00
|
|
|
self.pos += 1
|
|
|
|
start = self.pos
|
|
|
|
if self.text[self.pos] == len(self.text):
|
2012-09-10 05:58:41 +00:00
|
|
|
self.error("EOF inside quoted string")
|
2012-08-29 05:55:11 +00:00
|
|
|
while self.text[self.pos] != "\"":
|
|
|
|
if self.pos == len(self.text):
|
2012-09-10 05:58:41 +00:00
|
|
|
self.error("EOF inside quoted string")
|
2012-08-29 05:55:11 +00:00
|
|
|
return None
|
|
|
|
if self.text[self.pos] == "\n":
|
2022-05-27 11:06:33 +00:00
|
|
|
if self.no_quote_lines:
|
|
|
|
self.error("EOL inside quoted string")
|
|
|
|
return None
|
2012-08-29 05:55:11 +00:00
|
|
|
self.line += 1
|
|
|
|
self.pos += 1
|
|
|
|
self.token = self.text[start:self.pos]
|
|
|
|
self.pos += 1
|
|
|
|
else:
|
|
|
|
start = self.pos
|
|
|
|
if self.text[self.pos] in self.single:
|
|
|
|
self.pos += 1
|
|
|
|
else:
|
|
|
|
while (self.pos < len(self.text)
|
|
|
|
and not self.text[self.pos].isspace()
|
|
|
|
and self.text[self.pos] not in self.single):
|
|
|
|
self.pos += 1
|
|
|
|
self.token = self.text[start:self.pos]
|
|
|
|
return self.token
|
|
|
|
def ungetToken(self):
|
|
|
|
self.unget = True
|