Which programming idiom to choose for this open source library? [closed]

Which programming idiom is easier to use for beginner developers writing concrete file parsing classes?

I’m developing an open source library, which one of the main functionality is to parse plain text files and get structured information from them. All of the files contain the same kind of information, but can be in different formats like XML, plain text (each of them is structured differently), etc. There are a common set of information pieces which is the same in all (e.g. player names, table names, some id numbers)

There are formats which are very similar to each other, so it’s possible to define a common Base class for them to facilitate concrete format parser implementations. So I can clearly define base classes like SplittablePlainTextFormat, XMLFormat, SeparateSummaryFormat, etc. Each of them hints the kind of structure they aim to parse. All of the concrete classes should have the same information pieces, no matter what.

To be useful at all, this library needs to define at least 30-40 of these parsers. A couple of them are more important than others (obviously the more popular formats).

Now my question is, which is the best programming idiom to choose to facilitate the development of these concrete classes? Let me explain:

I think imperative programming is easy to follow even for beginners, because the flow is fixed, the statements just come one after another. Right now, I have this:

class SplittableBaseFormat:
    def parse(self):
        "Parses the body of the hand history, but first parse header if not yet parsed."
        if not self.header_parsed:
            self.parse_header()

        self._parse_table()
        self._parse_players()
        self._parse_button()
        self._parse_hero()
        self._parse_preflop()
        self._parse_street('flop')
        self._parse_street('turn')
        self._parse_street('river')
        self._parse_showdown()
        self._parse_pot()
        self._parse_board()
        self._parse_winners()
        self._parse_extra()

        self.parsed = True

So the concrete parser need to define these methods in order in any way they want. Easy to follow, but takes longer to implement each individual concrete parser.

So what about declarative? In this case Base classes (like SplittableFormat and XMLFormat) would do the heavy lifting based on regex and line/node number declarations in the concrete class, and concrete classes have no code at all, just line numbers and regexes, maybe other kind of rules.

Like this:

class SplittableFormat:
    def parse_table():
        "Parses TABLE_REGEX and get information"
        # set attributes here

    def parse_players():
        "parses PLAYER_REGEX and get information"
        # set attributes here


class SpecificFormat1(SplittableFormat):
    TABLE_REGEX = re.compile('^(?P<table_name>.*) other info d* etc')
    TABLE_LINE = 1
    PLAYER_REGEX = re.compile('^Player d: (?P<player_name>.*) has (.*) in chips.')
    PLAYER_LINE = 16


class SpecificFormat2(SplittableFormat):
    TABLE_REGEX = re.compile(r'^Tournament #(d*) (?P<table_name>.*) other info2 d* etc')
    TABLE_LINE = 2
    PLAYER_REGEX = re.compile(r'^Seat d: (?P<player_name>.*) has a stack of (d*)')
    PLAYER_LINE = 14

So if I want to make it possible for non-developers to write these classes the way to go seems to be the declarative way, however, I’m almost certain I can’t eliminate the declarations of regexes, which clearly needs (senior :D) programmers, so should I care about this at all? Do you think it matters to choose one over another or doesn’t matter at all? Maybe if somebody wants to work on this project, they will, if not, no matter which idiom I choose. Can I “convert” non-programmers to help developing these? What are your observations?

Other considerations:
Imperative will allow any kind of work; there is a simple flow, which they can follow but inside that, they can do whatever they want.
It would be harder to force a common interface with imperative because of this arbitrary implementations.
Declarative will be much more rigid, which is a bad thing, because formats might change over time without any notice.
Declarative will be harder for me to develop and takes longer time. Imperative is already ready to release.

I’m looking for answers about which idioms to use when, which is better for open source projects with different scenarios, which is better for wide range of developer skills.


TL; DR:

  • Parsing different file formats (plain text, XML)
  • They contains same kind of information
  • Target audience: non-developers, beginners
  • Regex probably cannot be avoided
  • 30-40 concrete parser classes needed
  • Facilitate coding these concrete classes
  • Which idiom is better?

2

I think you can go the declarative minilanguage route, but you’re unlikely to find one that works for all those formats.

Consider grouping your formats. For example:

  1. for parsing XML, or anything similarly structured, using anything other than an XML parser is probably asking for trouble. You might be able to provide a general XML-to-whatever engine that less technical users can configure, maybe by just specifying which tags they want mapped to which fields.
  2. for parsing text, full regular expressions look like overkill for your examples – you could handle those with scanf. You could probably provide a translation from something like Python format strings to regex, while still exposing REs directly to users who want them

    eg. convert the slightly more user-friendly

    'Player {player_num:d}: {player_name:s} has {player_chips:d} in chips.'
    

    to

    'Player (?P<player_num>d+): (?P<player_name>S+) has (?<player_chips>d+) in chips.'
    

    NB. the original string isn’t much simpler than the RE, although there’s a bit less noise, but there are many fewer opportunities for a non-technical user to confuse themselves than with an RE

  3. for parsing CSV, fixed-width or binary formats, some general parser can probably be configured with delimiter, field width, or type+size info respectively. Then we’re back to specifying the mapping from columns to fields, similar to the XML.

Since none of these have anything much in common, trying to fit them all into a single DSL is hard. It’ll end up -like regular expressions – being too general for a beginner to learn easily.

The downside is, it will be hard to provide any uniformity or consistency between formats in different groups. Still, each individual group should be much easier to learn and support.

You should look into parser combinator libraries, which when set up properly, can give you declarative syntax that’s easier to read than either your recursive descent example or your regex example. Done correctly, it sort of looks like concatenating a string, but it works in reverse. With some work on your part, it might look something like:

parser = "Player" + playerNumber + ":" + playerName + "has" + chipCount + "in chips"

That being said, if you truly want non-programmers to contribute, you’re going to want to create some sort of guided graphical extractor. Think of the wizard you get when you open a text file in Excel, or the way AdBlock lets you choose an element on the page to block. The code does some autodetect on the basic structure, the user answers some questions to get the columns looking right, labels the different fields, then the code highlights all the fields and the user confirms. This system would be difficult to create, but will make maintenance of changes to the formats very nice.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Which programming idiom to choose for this open source library? [closed]

Which programming idiom is easier to use for beginner developers writing concrete file parsing classes?

I’m developing an open source library, which one of the main functionality is to parse plain text files and get structured information from them. All of the files contain the same kind of information, but can be in different formats like XML, plain text (each of them is structured differently), etc. There are a common set of information pieces which is the same in all (e.g. player names, table names, some id numbers)

There are formats which are very similar to each other, so it’s possible to define a common Base class for them to facilitate concrete format parser implementations. So I can clearly define base classes like SplittablePlainTextFormat, XMLFormat, SeparateSummaryFormat, etc. Each of them hints the kind of structure they aim to parse. All of the concrete classes should have the same information pieces, no matter what.

To be useful at all, this library needs to define at least 30-40 of these parsers. A couple of them are more important than others (obviously the more popular formats).

Now my question is, which is the best programming idiom to choose to facilitate the development of these concrete classes? Let me explain:

I think imperative programming is easy to follow even for beginners, because the flow is fixed, the statements just come one after another. Right now, I have this:

class SplittableBaseFormat:
    def parse(self):
        "Parses the body of the hand history, but first parse header if not yet parsed."
        if not self.header_parsed:
            self.parse_header()

        self._parse_table()
        self._parse_players()
        self._parse_button()
        self._parse_hero()
        self._parse_preflop()
        self._parse_street('flop')
        self._parse_street('turn')
        self._parse_street('river')
        self._parse_showdown()
        self._parse_pot()
        self._parse_board()
        self._parse_winners()
        self._parse_extra()

        self.parsed = True

So the concrete parser need to define these methods in order in any way they want. Easy to follow, but takes longer to implement each individual concrete parser.

So what about declarative? In this case Base classes (like SplittableFormat and XMLFormat) would do the heavy lifting based on regex and line/node number declarations in the concrete class, and concrete classes have no code at all, just line numbers and regexes, maybe other kind of rules.

Like this:

class SplittableFormat:
    def parse_table():
        "Parses TABLE_REGEX and get information"
        # set attributes here

    def parse_players():
        "parses PLAYER_REGEX and get information"
        # set attributes here


class SpecificFormat1(SplittableFormat):
    TABLE_REGEX = re.compile('^(?P<table_name>.*) other info d* etc')
    TABLE_LINE = 1
    PLAYER_REGEX = re.compile('^Player d: (?P<player_name>.*) has (.*) in chips.')
    PLAYER_LINE = 16


class SpecificFormat2(SplittableFormat):
    TABLE_REGEX = re.compile(r'^Tournament #(d*) (?P<table_name>.*) other info2 d* etc')
    TABLE_LINE = 2
    PLAYER_REGEX = re.compile(r'^Seat d: (?P<player_name>.*) has a stack of (d*)')
    PLAYER_LINE = 14

So if I want to make it possible for non-developers to write these classes the way to go seems to be the declarative way, however, I’m almost certain I can’t eliminate the declarations of regexes, which clearly needs (senior :D) programmers, so should I care about this at all? Do you think it matters to choose one over another or doesn’t matter at all? Maybe if somebody wants to work on this project, they will, if not, no matter which idiom I choose. Can I “convert” non-programmers to help developing these? What are your observations?

Other considerations:
Imperative will allow any kind of work; there is a simple flow, which they can follow but inside that, they can do whatever they want.
It would be harder to force a common interface with imperative because of this arbitrary implementations.
Declarative will be much more rigid, which is a bad thing, because formats might change over time without any notice.
Declarative will be harder for me to develop and takes longer time. Imperative is already ready to release.

I’m looking for answers about which idioms to use when, which is better for open source projects with different scenarios, which is better for wide range of developer skills.


TL; DR:

  • Parsing different file formats (plain text, XML)
  • They contains same kind of information
  • Target audience: non-developers, beginners
  • Regex probably cannot be avoided
  • 30-40 concrete parser classes needed
  • Facilitate coding these concrete classes
  • Which idiom is better?

2

I think you can go the declarative minilanguage route, but you’re unlikely to find one that works for all those formats.

Consider grouping your formats. For example:

  1. for parsing XML, or anything similarly structured, using anything other than an XML parser is probably asking for trouble. You might be able to provide a general XML-to-whatever engine that less technical users can configure, maybe by just specifying which tags they want mapped to which fields.
  2. for parsing text, full regular expressions look like overkill for your examples – you could handle those with scanf. You could probably provide a translation from something like Python format strings to regex, while still exposing REs directly to users who want them

    eg. convert the slightly more user-friendly

    'Player {player_num:d}: {player_name:s} has {player_chips:d} in chips.'
    

    to

    'Player (?P<player_num>d+): (?P<player_name>S+) has (?<player_chips>d+) in chips.'
    

    NB. the original string isn’t much simpler than the RE, although there’s a bit less noise, but there are many fewer opportunities for a non-technical user to confuse themselves than with an RE

  3. for parsing CSV, fixed-width or binary formats, some general parser can probably be configured with delimiter, field width, or type+size info respectively. Then we’re back to specifying the mapping from columns to fields, similar to the XML.

Since none of these have anything much in common, trying to fit them all into a single DSL is hard. It’ll end up -like regular expressions – being too general for a beginner to learn easily.

The downside is, it will be hard to provide any uniformity or consistency between formats in different groups. Still, each individual group should be much easier to learn and support.

You should look into parser combinator libraries, which when set up properly, can give you declarative syntax that’s easier to read than either your recursive descent example or your regex example. Done correctly, it sort of looks like concatenating a string, but it works in reverse. With some work on your part, it might look something like:

parser = "Player" + playerNumber + ":" + playerName + "has" + chipCount + "in chips"

That being said, if you truly want non-programmers to contribute, you’re going to want to create some sort of guided graphical extractor. Think of the wizard you get when you open a text file in Excel, or the way AdBlock lets you choose an element on the page to block. The code does some autodetect on the basic structure, the user answers some questions to get the columns looking right, labels the different fields, then the code highlights all the fields and the user confirms. This system would be difficult to create, but will make maintenance of changes to the formats very nice.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Which programming idiom to choose for this open source library? [closed]

Which programming idiom is easier to use for beginner developers writing concrete file parsing classes?

I’m developing an open source library, which one of the main functionality is to parse plain text files and get structured information from them. All of the files contain the same kind of information, but can be in different formats like XML, plain text (each of them is structured differently), etc. There are a common set of information pieces which is the same in all (e.g. player names, table names, some id numbers)

There are formats which are very similar to each other, so it’s possible to define a common Base class for them to facilitate concrete format parser implementations. So I can clearly define base classes like SplittablePlainTextFormat, XMLFormat, SeparateSummaryFormat, etc. Each of them hints the kind of structure they aim to parse. All of the concrete classes should have the same information pieces, no matter what.

To be useful at all, this library needs to define at least 30-40 of these parsers. A couple of them are more important than others (obviously the more popular formats).

Now my question is, which is the best programming idiom to choose to facilitate the development of these concrete classes? Let me explain:

I think imperative programming is easy to follow even for beginners, because the flow is fixed, the statements just come one after another. Right now, I have this:

class SplittableBaseFormat:
    def parse(self):
        "Parses the body of the hand history, but first parse header if not yet parsed."
        if not self.header_parsed:
            self.parse_header()

        self._parse_table()
        self._parse_players()
        self._parse_button()
        self._parse_hero()
        self._parse_preflop()
        self._parse_street('flop')
        self._parse_street('turn')
        self._parse_street('river')
        self._parse_showdown()
        self._parse_pot()
        self._parse_board()
        self._parse_winners()
        self._parse_extra()

        self.parsed = True

So the concrete parser need to define these methods in order in any way they want. Easy to follow, but takes longer to implement each individual concrete parser.

So what about declarative? In this case Base classes (like SplittableFormat and XMLFormat) would do the heavy lifting based on regex and line/node number declarations in the concrete class, and concrete classes have no code at all, just line numbers and regexes, maybe other kind of rules.

Like this:

class SplittableFormat:
    def parse_table():
        "Parses TABLE_REGEX and get information"
        # set attributes here

    def parse_players():
        "parses PLAYER_REGEX and get information"
        # set attributes here


class SpecificFormat1(SplittableFormat):
    TABLE_REGEX = re.compile('^(?P<table_name>.*) other info d* etc')
    TABLE_LINE = 1
    PLAYER_REGEX = re.compile('^Player d: (?P<player_name>.*) has (.*) in chips.')
    PLAYER_LINE = 16


class SpecificFormat2(SplittableFormat):
    TABLE_REGEX = re.compile(r'^Tournament #(d*) (?P<table_name>.*) other info2 d* etc')
    TABLE_LINE = 2
    PLAYER_REGEX = re.compile(r'^Seat d: (?P<player_name>.*) has a stack of (d*)')
    PLAYER_LINE = 14

So if I want to make it possible for non-developers to write these classes the way to go seems to be the declarative way, however, I’m almost certain I can’t eliminate the declarations of regexes, which clearly needs (senior :D) programmers, so should I care about this at all? Do you think it matters to choose one over another or doesn’t matter at all? Maybe if somebody wants to work on this project, they will, if not, no matter which idiom I choose. Can I “convert” non-programmers to help developing these? What are your observations?

Other considerations:
Imperative will allow any kind of work; there is a simple flow, which they can follow but inside that, they can do whatever they want.
It would be harder to force a common interface with imperative because of this arbitrary implementations.
Declarative will be much more rigid, which is a bad thing, because formats might change over time without any notice.
Declarative will be harder for me to develop and takes longer time. Imperative is already ready to release.

I’m looking for answers about which idioms to use when, which is better for open source projects with different scenarios, which is better for wide range of developer skills.


TL; DR:

  • Parsing different file formats (plain text, XML)
  • They contains same kind of information
  • Target audience: non-developers, beginners
  • Regex probably cannot be avoided
  • 30-40 concrete parser classes needed
  • Facilitate coding these concrete classes
  • Which idiom is better?

2

I think you can go the declarative minilanguage route, but you’re unlikely to find one that works for all those formats.

Consider grouping your formats. For example:

  1. for parsing XML, or anything similarly structured, using anything other than an XML parser is probably asking for trouble. You might be able to provide a general XML-to-whatever engine that less technical users can configure, maybe by just specifying which tags they want mapped to which fields.
  2. for parsing text, full regular expressions look like overkill for your examples – you could handle those with scanf. You could probably provide a translation from something like Python format strings to regex, while still exposing REs directly to users who want them

    eg. convert the slightly more user-friendly

    'Player {player_num:d}: {player_name:s} has {player_chips:d} in chips.'
    

    to

    'Player (?P<player_num>d+): (?P<player_name>S+) has (?<player_chips>d+) in chips.'
    

    NB. the original string isn’t much simpler than the RE, although there’s a bit less noise, but there are many fewer opportunities for a non-technical user to confuse themselves than with an RE

  3. for parsing CSV, fixed-width or binary formats, some general parser can probably be configured with delimiter, field width, or type+size info respectively. Then we’re back to specifying the mapping from columns to fields, similar to the XML.

Since none of these have anything much in common, trying to fit them all into a single DSL is hard. It’ll end up -like regular expressions – being too general for a beginner to learn easily.

The downside is, it will be hard to provide any uniformity or consistency between formats in different groups. Still, each individual group should be much easier to learn and support.

You should look into parser combinator libraries, which when set up properly, can give you declarative syntax that’s easier to read than either your recursive descent example or your regex example. Done correctly, it sort of looks like concatenating a string, but it works in reverse. With some work on your part, it might look something like:

parser = "Player" + playerNumber + ":" + playerName + "has" + chipCount + "in chips"

That being said, if you truly want non-programmers to contribute, you’re going to want to create some sort of guided graphical extractor. Think of the wizard you get when you open a text file in Excel, or the way AdBlock lets you choose an element on the page to block. The code does some autodetect on the basic structure, the user answers some questions to get the columns looking right, labels the different fields, then the code highlights all the fields and the user confirms. This system would be difficult to create, but will make maintenance of changes to the formats very nice.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật