# HG changeset patch # User Santeri Piippo # Date 1512913607 -7200 # Node ID 50d3086070df0303e025bf0e65df98913ff432f0 # Parent 5411a25cfca72935eceee3635ce38bd0507b1edb Moved the parsing function into a new file diff -r 5411a25cfca7 -r 50d3086070df ldraw.py --- a/ldraw.py Sun Dec 10 15:45:50 2017 +0200 +++ b/ldraw.py Sun Dec 10 15:46:47 2017 +0200 @@ -1,110 +1,5 @@ #!/usr/bin/env python3 -import linetypes -import re -from geometry import * - -class BadLdrawLine(Exception): - pass - -def parse_ldraw_code(line): - line = line.strip() - if not line: - return linetypes.EmptyLine() - elif line == '0': - return linetypes.Comment('') - elif line.startswith('0 '): - return linetypes.Comment(line[2:].strip()) - elif line.startswith('1 '): - return parse_ldraw_subfile_reference(line) - elif line.startswith('2 '): - return parse_ldraw_line(line) - elif line.startswith('3 '): - return parse_ldraw_triangle(line) - elif line.startswith('4 '): - return parse_ldraw_quadrilateral(line) - elif line.startswith('5 '): - return parse_ldraw_contour(line) - else: - raise BadLdrawLine('unknown line type') - -def parse_ldraw_subfile_reference(line): - pattern = r'^1\s+(\d+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$' - match = re.search(pattern, line) - if not match: - raise BadLdrawLine('unable to parse') - groups = list(match.groups()) - indices = { - 'color': 0, - 'anchor': slice(1, 4), - 'matrix': slice(4, 13), - 'subfile_path': 13 - } - try: - color = int(groups[indices['color']]) - vertex_values = [float(x) for x in groups[indices['anchor']]] - matrix_values = [float(x) for x in groups[indices['matrix']]] - except ValueError: - raise BadLdrawLine('bad numeric values') - return linetypes.SubfileReference( - color = color, - anchor = Vertex(*vertex_values), - matrix = TransformationMatrix(matrix_values), - subfile_path = groups[indices['subfile_path']] - ) - -def generic_parse_polygon(line, *, type_code, vertex_count): - pattern = r'^' \ - + str(type_code) \ - + '\s+(\d+)' \ - + r'\s+([^ ]+)' * (vertex_count * 3) \ - + r'\s*$' - match = re.search(pattern, line) - if not match: - raise BadLdrawLine(str.format('cannot parse type-{} line', type_code)) - vertices = [] - for vertex_index in range(vertex_count): - slice_begin = 1 + vertex_index * 3 - slice_end = 1 + (vertex_index + 1) * 3 - coordinates = match.groups()[slice_begin:slice_end] - assert(len(coordinates) == 3) - try: - coordinates = [float(x) for x in coordinates] - except ValueError: - raise BadLdrawLine('bad numeric values') - vertices.append(Vertex(*coordinates)) - return { - 'color': int(match.group(1)), - 'vertices': vertices, - } - -def parse_ldraw_line(line): - parse_result = generic_parse_polygon(line, type_code = 2, vertex_count = 2) - return linetypes.LineSegment( - color = parse_result['color'], - geometry = LineSegment(*parse_result['vertices']), - ) - -def parse_ldraw_triangle(line): - parse_result = generic_parse_polygon(line, type_code = 3, vertex_count = 3) - return linetypes.Triangle( - color = parse_result['color'], - geometry = Polygon(parse_result['vertices']), - ) - -def parse_ldraw_quadrilateral(line): - parse_result = generic_parse_polygon(line, type_code = 4, vertex_count = 4) - return linetypes.Quadrilateral( - color = parse_result['color'], - geometry = Polygon(parse_result['vertices']), - ) - -def parse_ldraw_contour(line): - parse_result = generic_parse_polygon(line, type_code = 5, vertex_count = 4) - return linetypes.Contour( - color = parse_result['color'], - geometry = LineSegment(*parse_result['vertices'][0:2]), - control_points = parse_result['vertices'][2:], - ) +from parse import parse_ldraw_code def read_ldraw(file, *, libraries): result = list() diff -r 5411a25cfca7 -r 50d3086070df parse.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parse.py Sun Dec 10 15:46:47 2017 +0200 @@ -0,0 +1,106 @@ +import linetypes +import re +from geometry import * + +class BadLdrawLine(Exception): + pass + +def parse_ldraw_code(line): + line = line.strip() + if not line: + return linetypes.EmptyLine() + elif line == '0': + return linetypes.Comment('') + elif line.startswith('0 '): + return linetypes.Comment(line[2:].strip()) + elif line.startswith('1 '): + return parse_ldraw_subfile_reference(line) + elif line.startswith('2 '): + return parse_ldraw_line(line) + elif line.startswith('3 '): + return parse_ldraw_triangle(line) + elif line.startswith('4 '): + return parse_ldraw_quadrilateral(line) + elif line.startswith('5 '): + return parse_ldraw_contour(line) + else: + raise BadLdrawLine('unknown line type') + +def parse_ldraw_subfile_reference(line): + pattern = r'^1\s+(\d+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$' + match = re.search(pattern, line) + if not match: + raise BadLdrawLine('unable to parse') + groups = list(match.groups()) + indices = { + 'color': 0, + 'anchor': slice(1, 4), + 'matrix': slice(4, 13), + 'subfile_path': 13 + } + try: + color = int(groups[indices['color']]) + vertex_values = [float(x) for x in groups[indices['anchor']]] + matrix_values = [float(x) for x in groups[indices['matrix']]] + except ValueError: + raise BadLdrawLine('bad numeric values') + return linetypes.SubfileReference( + color = color, + anchor = Vertex(*vertex_values), + matrix = TransformationMatrix(matrix_values), + subfile_path = groups[indices['subfile_path']] + ) + +def generic_parse_polygon(line, *, type_code, vertex_count): + pattern = r'^' \ + + str(type_code) \ + + '\s+(\d+)' \ + + r'\s+([^ ]+)' * (vertex_count * 3) \ + + r'\s*$' + match = re.search(pattern, line) + if not match: + raise BadLdrawLine(str.format('cannot parse type-{} line', type_code)) + vertices = [] + for vertex_index in range(vertex_count): + slice_begin = 1 + vertex_index * 3 + slice_end = 1 + (vertex_index + 1) * 3 + coordinates = match.groups()[slice_begin:slice_end] + assert(len(coordinates) == 3) + try: + coordinates = [float(x) for x in coordinates] + except ValueError: + raise BadLdrawLine('bad numeric values') + vertices.append(Vertex(*coordinates)) + return { + 'color': int(match.group(1)), + 'vertices': vertices, + } + +def parse_ldraw_line(line): + parse_result = generic_parse_polygon(line, type_code = 2, vertex_count = 2) + return linetypes.LineSegment( + color = parse_result['color'], + geometry = LineSegment(*parse_result['vertices']), + ) + +def parse_ldraw_triangle(line): + parse_result = generic_parse_polygon(line, type_code = 3, vertex_count = 3) + return linetypes.Triangle( + color = parse_result['color'], + geometry = Polygon(parse_result['vertices']), + ) + +def parse_ldraw_quadrilateral(line): + parse_result = generic_parse_polygon(line, type_code = 4, vertex_count = 4) + return linetypes.Quadrilateral( + color = parse_result['color'], + geometry = Polygon(parse_result['vertices']), + ) + +def parse_ldraw_contour(line): + parse_result = generic_parse_polygon(line, type_code = 5, vertex_count = 4) + return linetypes.Contour( + color = parse_result['color'], + geometry = LineSegment(*parse_result['vertices'][0:2]), + control_points = parse_result['vertices'][2:], + )