Source code for timApp.document.attributeparser
[docs]class AttributeParser:
"""
:type string: str
:type current_pos: int
"""
def __init__(self, string=""):
self.str = string
self.current_pos = 0
[docs] def parse_code_type(self):
if not self.has_chars() or self.current_char() != "`":
return {}
while self.has_chars() and self.current_char() == "`":
self.current_pos += 1
self.eat_whitespace()
start = self.current_pos
while self.has_chars() and self.current_char() not in (" ", "{"):
self.current_pos += 1
end = self.current_pos
self.current_pos = 0
if start != end:
return {"code_lang": self.str[start:end]}
return {}
[docs] def get_attributes(self):
code_info = self.parse_code_type()
potential_start_indices = [
i
for i, x in enumerate(self.str)
if x == AttributeParser.attr_list_start_char()
]
for i in potential_start_indices:
tokens = self.try_get_attributes(i + 1)
if tokens is not None:
return tokens | code_info, i
return code_info, None
[docs] def try_get_attributes(self, pos):
self.current_pos = pos
tokens = {}
end_found = False
while self.has_chars():
self.eat_whitespace()
if not self.has_chars():
break
if self.try_parse_attr_list_end_char():
end_found = True
self.get_char()
break
token = self.try_parse_hash()
if token:
if "taskId" in tokens:
break
tokens["taskId"] = token
continue
token = self.try_parse_class()
if token:
if not tokens.get("classes"):
tokens["classes"] = []
tokens["classes"].append(token)
continue
key, val = self.try_parse_keyvaluepair()
if key:
tokens[key] = val
continue
break
if end_found:
self.eat_whitespace()
return None if self.has_chars() else tokens
else:
return None
[docs] def try_parse_attr_list_end_char(self):
if self.current_char() == self.attr_list_end_char():
return True
return False
[docs] def try_parse_helper(self, char):
if self.current_char() != char:
return None
find_pos = self.current_pos + 1
i = self.str.find(" ", find_pos)
i2 = self.str.find(self.attr_list_end_char(), find_pos)
if 0 <= i2 < i or i < 0:
i = i2
if i < 0:
return None
value = self.str[find_pos:i]
self.current_pos = i
return value
[docs] def try_parse_keyvaluepair(self):
key_name = ""
saved_pos = self.current_pos
while True:
if not self.has_chars():
self.current_pos = saved_pos
return None, None
curr = self.get_char()
if curr == " ":
self.current_pos = saved_pos
return None, None
if curr == "=":
break
key_name += curr
if key_name == "":
self.current_pos = saved_pos
return None, None
value = ""
quote_enabled = False
if self.has_chars() and self.current_char() == '"':
quote_enabled = True
self.get_char()
while self.has_chars():
curr = self.get_char()
if not quote_enabled:
if curr == " ":
break
elif curr == self.attr_list_end_char():
self.current_pos -= 1
break
if quote_enabled and curr == "\\":
curr = self.get_char()
if curr != '"' and curr != "\\":
self.current_pos = saved_pos
return None, None
elif quote_enabled and curr == '"':
return key_name, value
value += curr
if not quote_enabled:
return key_name, value
else:
self.current_pos = saved_pos
return None, None
[docs] def eat_whitespace(self):
while self.has_chars() and self.current_char() == " ":
self.current_pos += 1