Last active
June 20, 2023 09:50
-
-
Save hadware/5dc39e407b78900a1f9e71b52ebf3a36 to your computer and use it in GitHub Desktop.
Parsing Examples with sly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sly import Lexer, Parser | |
import pprint | |
class JSONLexer(Lexer): | |
tokens = {"FLOAT", "INTEGER", "STRING"} | |
literals = {'{', '}', '[', ']', ',', ':'} | |
ignore = " \t\n" | |
@_(r"\".*?\"") | |
def STRING(self, t): | |
t.value = t.value.strip("\"") | |
return t | |
@_(r"\d+\.\d*") | |
def FLOAT(self, t): | |
t.value = float(t.value) | |
return t | |
@_(r"\d+") | |
def INTEGER(self, t): | |
t.value = int(t.value) | |
return t | |
class JSONParser(Parser): | |
tokens = JSONLexer.tokens | |
start = "json" | |
@_('object', | |
'array') | |
def json(self, p): | |
return p[0] | |
@_('"{" members "}"') | |
def object(self, p): | |
return {key: value for key, value in p.members} | |
@_('pair') | |
def members(self, p): | |
return [p.pair] | |
@_('pair "," members') | |
def members(self, p): | |
return [p.pair] + p.members | |
@_('STRING ":" value') | |
def pair(self, p): | |
return p.STRING, p.value | |
@_('"[" elements "]"') | |
def array(self, p): | |
return p.elements | |
@_('value') | |
def elements(self, p): | |
return [p.value] | |
@_('value "," elements') | |
def elements(self, p): | |
return [p.value] + p.elements | |
@_('STRING', | |
'INTEGER', | |
'FLOAT', | |
'object', | |
'array') | |
def value(self, p): | |
return p[0] | |
def error(self, p): | |
raise ValueError("Parsing error at token %s" % str(p)) | |
if __name__ == "__main__": | |
lexer = JSONLexer() | |
parser = JSONParser() | |
json_text = """{"menu": { | |
"id": "file", | |
"value": "File", | |
"popup": { | |
"menuitem": [ | |
{"value": "New", "onclick": "CreateNewDoc()"}, | |
{"value": "Open", "onclick": "OpenDoc()"}, | |
{"value": "Close", "onclick": "CloseDoc()"} | |
], | |
"delay" : 1.5 | |
} | |
}} | |
""" | |
result = parser.parse(lexer.tokenize(json_text)) | |
pprint.pprint(result) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pprint | |
from dataclasses import dataclass | |
from typing import List, Tuple | |
from sly import Lexer, Parser | |
@dataclass | |
class Vertex: | |
coords: Tuple[float, float, float] | |
def __repr__(self): | |
return "VERTEX(%f,%f,%f)" % self.coords | |
@dataclass | |
class Facet: | |
vertices: Tuple[Vertex, Vertex, Vertex] | |
normal: Vertex | |
def __repr__(self): | |
return "\t FACET({normal})\n\t\t{vertices}".format( | |
normal=repr(self.normal), | |
vertices="\n\t\t".join(repr(vertex) for vertex in self.vertices) | |
) | |
@dataclass | |
class Solid: | |
name: str | |
facets: List[Facet] | |
def __repr__(self): | |
return "SOLID({name})\n{facets}\n".format( | |
name=self.name, | |
facets="\n".join(repr(facet) for facet in self.facets) | |
) | |
class STLLexer(Lexer): | |
tokens = {"SOLID_START", "SOLID_END", | |
"FACET_START", "FACET_END", "NAME_LITERAL", | |
"LOOP_START", "LOOP_END", | |
"NAME_LITERAL", "VERTEX_TAG", "FLOAT"} | |
@_(r"[ \t\n]+") | |
def ignore_whitespace(self, t): | |
self.lineno += t.value.count("\n") | |
SOLID_START = r"solid" | |
SOLID_END = r"endsolid" | |
FACET_START = r"facet normal" | |
FACET_END = r"endfacet" | |
LOOP_START = r"outer loop" | |
LOOP_END = r"endloop" | |
VERTEX_TAG = r"vertex" | |
@_("[+-]?\d+(\.\d*(e[+-]?\d+)?)?") | |
def FLOAT(self, t): | |
t.value = float(t.value) | |
return t | |
NAME_LITERAL = r"\w+" | |
class STLParser(Parser): | |
tokens = STLLexer.tokens | |
start = "stl" | |
@_("solid") | |
def stl(self, p): | |
return p.solid | |
@_("SOLID_START NAME_LITERAL facets_list SOLID_END") | |
@_("SOLID_START NAME_LITERAL facets_list SOLID_END NAME_LITERAL") | |
def solid(self, p): | |
return Solid(name=p[1], facets=p.facets_list) | |
@_("facet") | |
def facets_list(self, p): | |
return [p.facet] | |
@_("facet facets_list") | |
def facets_list(self, p): | |
return [p.facet] + p.facets_list | |
@_("FACET_START triplet loop FACET_END") | |
def facet(self, p): | |
return Facet(vertices=p.loop, normal=Vertex(p.triplet)) | |
@_("LOOP_START vertex vertex vertex LOOP_END") | |
def loop(self, p): | |
return p[1], p[2], p[3] | |
@_("VERTEX_TAG triplet") | |
def vertex(self, p): | |
return Vertex(p.triplet) | |
@_("FLOAT FLOAT FLOAT") | |
def triplet(self, p): | |
return p[0], p[1], p[2] | |
def error(self, token): | |
pass | |
if __name__ == "__main__": | |
lexer = STLLexer() | |
parser = STLParser() | |
with open("star.stl") as stl_file: | |
# pprint.pprint(list(lexer.tokenize(stl_file.read()))) | |
solid = parser.parse(lexer.tokenize(stl_file.read())) | |
print(solid) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment