with open("humanoid.stl", "r") as fp: stl = fp.read() #--- class Lexer: def __init__(self, data): assert(data.startswith("solid")) self.data = data self.pos = min(80, data.index("\n")) def lex(self): # Skip leading whitespace while self.pos < len(self.data) and self.data[self.pos] in " \t\n": self.pos += 1 if self.pos >= len(self.data): return None # Grab a word i = self.pos while i < len(self.data) and self.data[i] not in " \t\n": i += 1 word = self.data[self.pos:i] self.pos = i return float(word) if word[0] in "+-0123456789." else word #--- class Parser: def __init__(self, lexer): self.lexer = lexer self.la = "" # look-ahead token self.feed() def at_end(self): return self.la == None def feed(self): t = self.la self.la = lexer.lex() return t def expect_keyword(self, keyword): assert self.la == keyword self.feed() def expect_float(self): assert isinstance(self.la, float) return self.feed() #--- def vec3(self, leading_keyword): self.expect_keyword(leading_keyword) x = self.expect_float() y = self.expect_float() z = self.expect_float() return (x, y, z) def outer_loop(self): self.expect_keyword("outer") self.expect_keyword("loop") v1 = self.vec3("vertex") v2 = self.vec3("vertex") v3 = self.vec3("vertex") self.expect_keyword("endloop") return [v1, v2, v3] def facet(self): self.expect_keyword("facet") normal = self.vec3("normal") vertices = self.outer_loop() self.expect_keyword("endfacet") return {"normal": normal, "vertices": vertices} def solid(self): facets = [] while self.la == "facet": facets.append(self.facet()) self.expect_keyword("endsolid") self.feed() assert self.at_end() return facets #--- lexer = Lexer(stl) parser = Parser(lexer) solid = parser.solid() from pprint import pprint pprint(solid, width=90)