| blc2 - Python library and frontend for running theatrical lighting and SFX. Written for the English 2041F fall 2019 theatre production of "The Cenci".
git clone https://benconnors.ca/git-repos/blc2 |
parsers.py (4548B) - raw
1 from blc2.constants import INFTY 2 3 def parse_interval(s): 4 if not s: 5 return None, s 6 dash = False 7 init_s = s 8 buff = "" 9 r = [-1, -1] 10 i = 0 11 while s: 12 if not dash and s[0] == '-': 13 if buff: 14 r[0] = int(buff) 15 buff = "" 16 dash = True 17 elif s[0] in "0123456789": 18 buff += s[0] 19 else: 20 break 21 s = s[1:] 22 i += 1 23 24 if buff: 25 r[1 if dash else 0] = int(buff) 26 elif not buff and not dash: 27 return None, s, None 28 29 if not dash: 30 r[1] = r[0] 31 32 return tuple(r), s, init_s[:i] 33 34 def parse_range(s): 35 if not s: 36 return None, s, None 37 38 rs = [] 39 disp = [] 40 tc = False 41 while s: 42 r, s, d = parse_interval(s) 43 if r is None: 44 break 45 tc = False 46 rs.append(r) 47 disp.append(d) 48 if s and s[0] == ',': 49 s = s[1:] 50 tc = True 51 else: 52 break 53 54 if not rs: 55 return None, s, None 56 return tuple(rs), s, ", ".join(disp) + (", " if tc else "") 57 58 def parse_channelrange(s): 59 if not s: 60 return None, s, None 61 62 f, s, d1 = parse_range(s) 63 if f is None: 64 return None, s, None 65 elif not s or s[0] != ';': 66 return (f, ((-1,-1),)), s, d1 67 68 69 s = s[1:] 70 c, s, d2 = parse_range(s) 71 if c is None: 72 return (f, ((-1, -1),)), s, d1 + "; " 73 74 return (f, c), s, d1+"; "+d2 75 76 def parse_value(s): 77 if not s: 78 return None, s, None 79 80 buff = "" 81 while s: 82 if s[0] in "0123456789" and int(buff+s[0]) < 256: 83 buff += s[0] 84 s = s[1:] 85 else: 86 break 87 88 return (None if not buff else int(buff)), s, buff 89 90 def parse_num(s): 91 if not s: 92 return None, s, None 93 94 buff = "" 95 while s: 96 if s[0] in "0123456789": 97 buff += s[0] 98 s = s[1:] 99 else: 100 break 101 102 return (None if not buff else int(buff)), s, buff 103 104 def parse_numlist(s): 105 if not s: 106 return None, s, None 107 108 rs = [] 109 disp = [] 110 tc = False 111 while s: 112 r, s, d = parse_num(s) 113 if r is None: 114 break 115 tc = False 116 rs.append(r) 117 disp.append(d) 118 if s and s[0] == ',': 119 s = s[1:] 120 tc = True 121 else: 122 break 123 124 if not rs: 125 return None, s, None 126 return tuple(rs), s, ", ".join(disp) + (", " if tc else "") 127 128 _POSTFIXES = "mcisahkegtp" 129 130 def parse_time(s): 131 if not s: 132 return None, s, None 133 134 v, s, d = parse_num(s) 135 if v is None: 136 if s[0].lower() == 'i': 137 return INFTY, s[1:], "infinity" 138 return None, s, None 139 140 if not s: 141 return v, s, d 142 143 try: 144 idx = _POSTFIXES.index(s[0].lower()) 145 except ValueError: 146 return v, s, d 147 148 v *= 10**idx 149 return v, s[1:], d+s[0].lower() 150 151 _ALL_LETTERS = "abcdefghijklmnopqrstuvwxyz" 152 def parse_any_letter(s): 153 if not s: 154 return None, s 155 156 l = s[0].lower() 157 158 if l not in _ALL_LETTERS: 159 return None, s, None 160 161 return _ALL_LETTERS.index(l), s[1:], l 162 163 def make_parse_letter(letter, display): 164 def inner(s): 165 if not s or s[0] != letter: 166 return None, s, None 167 return True, s[1:], display 168 169 return inner 170 171 def parse_null(s): 172 return True, s, "" 173 174 def parse_string(s): 175 if not s: 176 return None, s, None 177 178 buff = "" 179 while s: 180 if s[0] != ' ': 181 buff += s[0] 182 s = s[1:] 183 else: 184 if not buff: 185 return None, s, None 186 break 187 188 return buff, s, buff 189 190 def parse_quotedstring(s): 191 if not s: 192 return None, s, None 193 194 if s[0] != "'": 195 return None, s, None 196 s = s[1:] 197 198 buff = "" 199 bs = False 200 while s: 201 if s[0] == '\\': 202 buff += s[0] 203 bs = not bs 204 elif s[0] == "'": 205 if bs: 206 buff += s[0] 207 bs = False 208 else: 209 s = s[1:] 210 break 211 else: 212 buff += s[0] 213 bs = False 214 s = s[1:] 215 else: 216 return buff, s, "'"+buff 217 return buff, s, "'"+buff+"'" 218 219 PARSE_MAP = { 220 "$channel_range": parse_channelrange, 221 "$value": parse_value, 222 "$null": parse_null, 223 "$string": parse_string, 224 "$num": parse_num, 225 "$quoted_string": parse_quotedstring, 226 "$letter": parse_any_letter, 227 "$time": parse_time, 228 "$numlist": parse_numlist, 229 }