You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yaclog-ksp/yaclog_ksp/script.py

124 lines
4.3 KiB
Python

# 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.
# Original: https://github.com/taniwha/cfgnode
# <pep8 compliant>
class ScriptError(Exception):
def __init__(self, fname, line, message):
Exception.__init__(self, "%s:%d: %s" % (fname, line, message))
self.line = line
class Script:
def __init__(self, filename, text, single="{}()':", quotes=True):
self.filename = filename
if text[0:3] == "\xef\xbb\xbf":
text = text[3:]
self.text = text
self.single = single
self.quotes = quotes
self.pos = 0
self.line = 1
self.unget = False
self.token = None
def error(self, msg):
raise ScriptError(self.filename, self.line, msg)
def token_available(self, crossline=False):
if self.unget:
return True
while self.pos < len(self.text):
while self.pos < len(self.text) and self.text[self.pos].isspace():
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
def get_line(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)
def get_token(self, crossline=False):
if self.unget:
self.unget = False
return self.token
if not self.token_available(crossline):
if not crossline:
self.error("line is incomplete")
return None
if self.quotes and self.text[self.pos] == "\"":
self.pos += 1
start = self.pos
if self.text[self.pos] == len(self.text):
self.error("EOF inside quoted string")
while self.text[self.pos] != "\"":
if self.pos == len(self.text):
self.error("EOF inside quoted string")
return None
if self.text[self.pos] == "\n":
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 unget_token(self):
self.unget = True