# Path: core/ezdxf/lldxf/types.py
# NONE_TAG = DXFTag(None, None)
# TAG_STRING_FORMAT = '%3d\n%s\n'
# TYPE_TABLE = _build_type_table([
#     (internal_type, (-10, )),  # spacial tags for internal use
#     (ustr, range(0, 10)),
#     (point_tuple, range(10, 20)),  # 2d or 3d points
#     (float, range(20, 60)),  # code 20-39 belongs to 2d/3d points and should not appear alone
#     (int, range(60, 100)),
#     (ustr, range(100, 106)),
#     (point_tuple, range(110, 113)),  # 110, 111, 112 - UCS definition
#     (float, range(113, 150)),  # 113-139 belongs to UCS definition and should not appear alone
#     (int, range(160, 170)),
#     (int, range(170, 180)),
#     (point_tuple, [210]),  # extrusion direction
#     (float, range(211, 240)),  # code 220, 230 belongs to extrusion direction and should not appear alone
#     (int, range(270, 290)),
#     (int, range(290, 300)),  # bool 1=True 0=False
#     (ustr, range(300, 370)),
#     (int, range(370, 390)),
#     (ustr, range(390, 400)),
#     (int, range(400, 410)),
#     (ustr, range(410, 420)),
#     (int, range(420, 430)),
#     (ustr, range(430, 440)),
#     (int, range(440, 460)),
#     (float, range(460, 470)),
#     (ustr, range(470, 480)),
#     (ustr, range(480, 482)),
#     (ustr, range(999, 1010)),
#     (point_tuple, range(1010, 1020)),
#     (float, range(1020, 1060)),  # code 1020-1039 belongs to 2d/3d points and should not appear alone
#     (int, range(1060, 1072)),
# ])
# def point_tuple(value):
# def _build_type_table(types):
# def internal_type(value):
# def is_point_code(code):
# def is_point_tag(tag):
# def cast_tag(tag, types=TYPE_TABLE):
# def cast_tag_value(code, value, types=TYPE_TABLE):
# def tag_type(code):
# def strtag(tag):
# def strtag2(tag):
# def convert_tags_to_text_lines(line_tags):
# def convert_text_lines_to_tags(text_lines):
# 
# Path: core/ezdxf/lldxf/const.py
# class DXFStructureError(DXFError):
#     pass


from .types import DXFTag, is_point_code, cast_tag
from .const import DXFStructureError
    tags 999.
    """

    lines = s.split('\n')
    if s.endswith('\n'):  # split() creates an extra item, if s ends with '\n'
        lines.pop()
    pos = 0

    def next_tag():
        return DXFTag(int(lines[pos]), lines[pos+1])

    count = len(lines)
    while pos < count:
        x = next_tag()
        pos += 2
        code = x.code
        if is_point_code(code):
            y = next_tag()  # y coordinate is mandatory - string_tagger relies on well formed DXF strings
            pos += 2
            if pos < count:
                z = next_tag()  # z coordinate just for 3d points
            else:  # if string s ends with a 2d point
                z = DUMMY_TAG
            if z.code == code + 20:
                pos += 2
                point = (float(x.value), float(y.value), float(z.value))
            else:
                point = (float(x.value), float(y.value))
            yield DXFTag(code, point)
        else:

# Path: core/ezdxf/lldxf/types.py
# NONE_TAG = DXFTag(None, None)
# TAG_STRING_FORMAT = '%3d\n%s\n'
# TYPE_TABLE = _build_type_table([
#     (internal_type, (-10, )),  # spacial tags for internal use
#     (ustr, range(0, 10)),
#     (point_tuple, range(10, 20)),  # 2d or 3d points
#     (float, range(20, 60)),  # code 20-39 belongs to 2d/3d points and should not appear alone
#     (int, range(60, 100)),
#     (ustr, range(100, 106)),
#     (point_tuple, range(110, 113)),  # 110, 111, 112 - UCS definition
#     (float, range(113, 150)),  # 113-139 belongs to UCS definition and should not appear alone
#     (int, range(160, 170)),
#     (int, range(170, 180)),
#     (point_tuple, [210]),  # extrusion direction
#     (float, range(211, 240)),  # code 220, 230 belongs to extrusion direction and should not appear alone
#     (int, range(270, 290)),
#     (int, range(290, 300)),  # bool 1=True 0=False
#     (ustr, range(300, 370)),
#     (int, range(370, 390)),
#     (ustr, range(390, 400)),
#     (int, range(400, 410)),
#     (ustr, range(410, 420)),
#     (int, range(420, 430)),
#     (ustr, range(430, 440)),
#     (int, range(440, 460)),
#     (float, range(460, 470)),
#     (ustr, range(470, 480)),
#     (ustr, range(480, 482)),
#     (ustr, range(999, 1010)),
#     (point_tuple, range(1010, 1020)),
#     (float, range(1020, 1060)),  # code 1020-1039 belongs to 2d/3d points and should not appear alone
#     (int, range(1060, 1072)),
# ])
# def point_tuple(value):
# def _build_type_table(types):
# def internal_type(value):
# def is_point_code(code):
# def is_point_tag(tag):
# def cast_tag(tag, types=TYPE_TABLE):
# def cast_tag_value(code, value, types=TYPE_TABLE):
# def tag_type(code):
# def strtag(tag):
# def strtag2(tag):
# def convert_tags_to_text_lines(line_tags):
# def convert_text_lines_to_tags(text_lines):
# 
# Path: core/ezdxf/lldxf/const.py
# class DXFStructureError(DXFError):
#     pass


# Path: core/ezdxf/lldxf/tagger.py
from .types import DXFTag, is_point_code, cast_tag
from .const import DXFStructureError

    tags 999.
    """

    lines = s.split('\n')
    if s.endswith('\n'):  # split() creates an extra item, if s ends with '\n'
        lines.pop()
    pos = 0

    def next_tag():
        return DXFTag(int(lines[pos]), lines[pos+1])

    count = len(lines)
    while pos < count:
        x = next_tag()
        pos += 2
        code = x.code
        if is_point_code(code):
            y = next_tag()  # y coordinate is mandatory - string_tagger relies on well formed DXF strings
            pos += 2
            if pos < count:
                z = next_tag()  # z coordinate just for 3d points
            else:  # if string s ends with a 2d point
                z = DUMMY_TAG
            if z.code == code + 20:
                pos += 2
                point = (float(x.value), float(y.value), float(z.value))
            else:
                point = (float(x.value), float(y.value))
            yield DXFTag(code, point)
        else:

            yield cast_tag(x)