basic LL(1) parser for ASCII STL converter
This commit is contained in:
parent
451f58f307
commit
32c489c957
|
@ -0,0 +1,95 @@
|
|||
|
||||
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)
|
Loading…
Reference in New Issue