Simple template language written in python
git clone git://git.janzachar.dev/stempl.git
0from time import sleep12class Token:3 def __init__(self, text):4 self.text = text5 self.valid = True6789class Operator(Token):10 OPERATORS = sorted([11 "+", "-", "*", "/", "//", "%",12 "==", "!=", "&", "|", "^", "&&", "||"13 "(", ")", "{{", "}}", ","14 ], key=len, reverse=True)1516 def __init__(self, text):17 self.valid = False18 for o in self.OPERATORS:19 if text.startswith(o):20 self.text = o21 self.valid = True22 return232425class Keyword(Token):26 KEYWORDS = [27 "if", "elif", "else",28 "for", "in",29 "paste", "raw",30 "with", "end",31 "global",32 ]3334 def __init__(self, text):35 self.valid = False36 for k in self.KEYWORDS:37 if not text.startswith(k):38 continue3940 if len(text) > len(k) and text[len(k)].isalnum():41 continue4243 self.text = k44 self.valid = True45 return464748class Identifier(Token):49 def __init__(self, text):50 if not text[0].isalpha():51 self.valid = False52 return5354 ptr = 055 while ptr < len(text) and text[ptr].isalnum():56 ptr += 15758 self.text = text[:ptr]59 if Operator(self.text).valid or Keyword(self.text).valid:60 self.valid = False61 return6263 self.valid = True6465class StrConst(Token):66 def __init__(self, text):67 self.valid = False6869 if text[0] != '"':70 return7172 i = 173 flag = False74 while i < len(text):75 if text[i] == '\\':76 flag = not flag77 elif text[i] == '"' and flag == False:78 break79 else:80 flag = False8182 i += 18384 if i == len(text):85 return8687 self.valid = True88 self.text = text[:i+1]899091class NumConst(Token):92 def __init__(self, text):93 self.valid = False9495 is_float = False96 i = 097 while i < len(text):98 if text[i] == '.':99 if is_float:100 return101 is_float = True102 elif not text[i].isdigit():103 break104105 i += 1106107 if i == 0 or text[:i] == ".":108 return109110 self.valid = True111 self.text = text[:i]112113class Raw(Token):114 def __init__(self, text):115 u = text.find("{{")116117 self.valid = True118 if u != -1:119 self.text = text[:u]120 else:121 self.text = text122123def expr(text):124 tok = []125 while len(text):126 if text[0].isspace():127 text = text[1:]128 continue129130 for C in (Operator, Keyword, Identifier, NumConst, StrConst):131 t = C(text)132 if not t.valid:133 continue134135 tok.append(t)136 text = text[len(t.text):]137 break138 else:139 raise ValueError("Unrecognised token :(")140141 if isinstance(tok[-1], Operator) and tok[-1].text == "}}":142 break143 return tok, text144145def lex(text):146 tok = []147 while len(text):148 r = Raw(text)149 text = text[len(r.text):]150 if len(r.text):151 tok.append(r)152153 e, text = expr(text)154 tok.extend(e)155 return tok156157