Created
December 23, 2016 09:19
-
-
Save anonymous/f7fee82634ba224e25e9022ec2c3c890 to your computer and use it in GitHub Desktop.
PLY Stanford polygon file format parser with pyparsing
This file contains 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
# -*- coding: utf-8 -*- | |
""" | |
Parse PLY Stanford Polygon Files | |
-------------------------------- | |
Context free grammar: | |
ply_grammar ::= header body | |
header ::= "ply" declaration+ "end_header" | |
declaration ::= format | element | property | |
format ::= "format" format_type NUMBER | |
element ::= "element" element_type NUMBER | |
property ::= ("property" property_type IDENT) | ("property" "list" property_type property_type IDENT) | |
format_type ::= "ascii" | "binary_little_endian" | "binary_big_endian" | |
element_type ::= "vertex" | "face" | "edge" | IDENT | |
property_type ::= "char" | "uchar" | "short" | "ushort" | "int" | "uint" | "float" | "double" | |
body ::= statement+ | |
statement ::= NUMBER+ | |
""" | |
import pathlib | |
import pyparsing as pp | |
number = pp.pyparsing_common.number() | |
identifier = pp.pyparsing_common.identifier() | |
lit = {l: pp.CaselessLiteral(l) for l in ( | |
"ascii", "binary_little_endian", "binary_big_endian", "vertex", "face", "edge", "char", | |
"uchar", "short", "ushort", "int", "uint", "float", "double", "format", "comment", | |
"element", "property", "list", "ply", "end_header" | |
)} | |
format_type = lit["ascii"] | lit["binary_little_endian"] | lit["binary_big_endian"] | |
element_type = lit["vertex"] | lit["face"] | lit["edge"] | identifier | |
property_type = lit["char"] | lit["uchar"] | lit["short"] | lit["ushort"] | lit["int"] | lit["uint"] | lit["float"] | lit["double"] | |
format_decl = pp.Suppress(lit["format"]) + format_type.setResultsName("file_type") + number.setResultsName("version") | |
comment_decl = lit["comment"] + pp.restOfLine | |
element_decl = pp.Suppress(lit["element"]) + element_type.setResultsName("name") + number.setResultsName("number") | |
property_decl = pp.Suppress(lit["property"]) + ( | |
(property_type.setResultsName("data_type") + identifier.setResultsName("name")) | | |
(pp.Suppress(lit["list"]) + property_type.setResultsName("idx_type") + property_type.setResultsName("data_type") + identifier.setResultsName("name")) | |
) | |
declarations = format_decl.setResultsName("format") + pp.OneOrMore(pp.Group( | |
element_decl + pp.OneOrMore(pp.Group(property_decl)) | |
)).setResultsName("declarations") | |
header = pp.Suppress(lit["ply"]) + declarations + pp.Suppress(lit["end_header"]) | |
body = pp.OneOrMore(number) | |
ply_grammar = header.setResultsName("header") + body.setResultsName("body") | |
ply_grammar.ignore(comment_decl) | |
def main(): | |
data = """ply | |
format ascii 1.0 | |
comment made by Greg Turk | |
comment this file is a cube | |
element vertex 8 | |
property float x | |
property float y | |
property float z | |
element face 6 | |
property list uchar int vertex_index | |
end_header | |
0 0 0 | |
0 0 1 | |
0 1 1 | |
0 1 0 | |
1 0 0 | |
1 0 1 | |
1 1 1 | |
1 1 0 | |
4 0 1 2 3 | |
4 7 6 5 4 | |
4 0 4 5 1 | |
4 1 5 6 2 | |
4 2 6 7 3 | |
4 3 7 4 0 | |
""" | |
try: | |
ply_grammar.validate() | |
tokens = ply_grammar.parseString(data) | |
print(tokens) | |
except pp.ParseException as e: | |
print(e.line) | |
print(" " * (e.column - 1) + "^") | |
print(e) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment