1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2025-2026 Benjamin Abendroth <braph93@gmx.de>
'''Module containing code for parsing strings as a stream.'''
class StringStream:
'''String stream class for reading a string.'''
def __init__(self, string):
self.s = string
self.i = 0
self.length = len(string)
def peek(self, seek=0):
'''Return character at current position + seek without advancing.'''
try:
return self.s[self.i + seek]
except IndexError:
return None
def peek_str(self, length=1):
'''Return substring of given length from current position.'''
return self.s[self.i:length]
def get(self):
'''Return current character and advance position by one.'''
c = self.s[self.i]
self.i += 1
return c
def have(self):
'''Return True if iterator is not at its end.'''
return self.i < self.length
def advance(self, length):
'''Advance the stream by a given length.'''
self.i += length
def parse_shell_single_quote(self, in_quotes=False):
'''Parse a single-quoted shell string.'''
if not in_quotes:
assert self.get() == "'"
string = ''
while True:
try:
c = self.get()
except IndexError as e:
raise ValueError("Unclosed single quote") from e
if c == "'":
return string
string += c
def parse_shell_double_quote(self, in_quotes=False):
'''Parse a double-quoted shell string.'''
if not in_quotes:
assert self.get() == '"'
string = ''
while True:
try:
c = self.get()
except IndexError as e:
raise ValueError("Unclosed double quote") from e
if c == '\\':
try:
string += self.get()
except IndexError as e:
raise ValueError("Missing character after backslash") from e
elif c == '"':
return string
else:
string += c
|