Parser/Composer library for Python https://fdik.org/pypeg2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
2.7 KiB

  1. #!/usr/bin/python3
  2. """
  3. Ini file sample (see end of file for the content of the ini file)
  4. To parse an ini file we use the grammar below. Comments in ini files are
  5. starting with a semicolon ";".
  6. Multi line strings are not possible in doctest so we build one from a list
  7. >>> ini_file_text = "\\n".join([
  8. ... "[Number 1]",
  9. ... "this=something",
  10. ... "that=something else",
  11. ... "",
  12. ... "; now for something even more useless",
  13. ... "[Number 2]",
  14. ... "once=anything",
  15. ... "twice=goes",
  16. ... ])
  17. >>> ini_file = parse(ini_file_text, IniFile, comment=(";", restline))
  18. Because IniFile and Section are Namespaces, we can access their content by
  19. name.
  20. >>> print("found: " + repr(ini_file["Number 1"]["that"]))
  21. found: 'something else'
  22. pyPEG is measuring the position of each object in the input text with a
  23. tuple (line_number, offset).
  24. >>> ini_file["Number 1"]["that"].position_in_text
  25. (3, 26)
  26. >>> ini_file["Number 2"].position_in_text
  27. (6, 85)
  28. pyPEG can also do the reverse job, composing a text of an object tree.
  29. >>> ini_file["Number 1"]["that"] = Key("new one")
  30. >>> ini_file["Number 3"] = Section()
  31. >>> print(compose(ini_file))
  32. [Number 1]
  33. this=something
  34. that=new one
  35. [Number 2]
  36. once=anything
  37. twice=goes
  38. [Number 3]
  39. <BLANKLINE>
  40. pyPEG contains an XML backend, too:
  41. >>> from pypeg2.xmlast import thing2xml
  42. >>> print(thing2xml(ini_file, pretty=True).decode())
  43. <IniFile>
  44. <Section name="Number 1">
  45. <Key name="this">something</Key>
  46. <Key name="that">new one</Key>
  47. </Section>
  48. <Section name="Number 2">
  49. <Key name="once">anything</Key>
  50. <Key name="twice">goes</Key>
  51. </Section>
  52. <Section name="Number 3" />
  53. </IniFile>
  54. In this sample the tree contains named objects only. Then we can output object
  55. names as tag names. Spaces in names will be translated into underscores.
  56. >>> print(thing2xml(ini_file, pretty=True, object_names=True).decode())
  57. <IniFile>
  58. <Number_1>
  59. <this>something</this>
  60. <that>new one</that>
  61. </Number_1>
  62. <Number_2>
  63. <once>anything</once>
  64. <twice>goes</twice>
  65. </Number_2>
  66. <Number_3 />
  67. </IniFile>
  68. """
  69. from __future__ import unicode_literals, print_function
  70. from pypeg2 import *
  71. import re
  72. # ini file parser
  73. # symbols in ini files can include spaces
  74. Symbol.regex = re.compile(r"[\w\s]+")
  75. # A key is "name = some string"
  76. class Key(str):
  77. grammar = name(), "=", restline, endl
  78. # Sections start with a name like "[NAME]" and may contain at least one key
  79. class Section(Namespace):
  80. grammar = "[", name(), "]", endl, maybe_some(Key)
  81. # Ini files have one or more sections
  82. class IniFile(Namespace):
  83. grammar = some(Section)
  84. if __name__ == "__main__":
  85. import doctest
  86. doctest.testmod(optionflags=(doctest.ELLIPSIS | doctest.REPORT_ONLY_FIRST_FAILURE))