Parser/Composer library for Python
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.

432 lines
12 KiB

  1. import unittest
  2. import pypeg2
  3. import re
  4. class GrammarTestCase1(unittest.TestCase):
  5. def runTest(self):
  6. x = pypeg2.some("thing")
  7. y = pypeg2.maybe_some("thing")
  8. z = pypeg2.optional("hello", "world")
  9. self.assertEqual(x, (-2, "thing"))
  10. self.assertEqual(y, (-1, "thing"))
  11. self.assertEqual(z, (0, ("hello", "world")))
  12. class GrammarTestCase2(unittest.TestCase):
  13. def runTest(self):
  14. L1 = pypeg2.csl("thing")
  15. L2 = pypeg2.csl("hello", "world")
  16. self.assertEqual(L1, ("thing", -1, (",", pypeg2.blank, "thing")))
  17. self.assertEqual(L2, ("hello", "world", -1, (",", pypeg2.blank, "hello", "world")))
  18. class ParserTestCase(unittest.TestCase): pass
  19. class TypeErrorTestCase(ParserTestCase):
  20. def runTest(self):
  21. parser = pypeg2.Parser()
  22. with self.assertRaises(pypeg2.GrammarTypeError):
  23. parser.parse("hello, world", 23)
  24. class ParseTerminalStringTestCase1(ParserTestCase):
  25. def runTest(self):
  26. parser = pypeg2.Parser()
  27. r = parser.parse("hello, world", "hello")
  28. self.assertEqual(r, (", world", None))
  29. class ParseTerminalStringTestCase2(ParserTestCase):
  30. def runTest(self):
  31. parser = pypeg2.Parser()
  32. with self.assertRaises(SyntaxError):
  33. r = parser.parse("hello, world", "world")
  34. class ParseKeywordTestCase1(ParserTestCase):
  35. def runTest(self):
  36. parser = pypeg2.Parser()
  37. r = parser.parse("hallo, world", pypeg2.K("hallo"))
  38. self.assertEqual(r, (", world", None))
  39. pypeg2.Keyword.table[pypeg2.K("hallo")]
  40. class ParseKeywordTestCase2(ParserTestCase):
  41. def runTest(self):
  42. parser = pypeg2.Parser()
  43. with self.assertRaises(SyntaxError):
  44. r = parser.parse("hello, world", pypeg2.K("werld"))
  45. pypeg2.Keyword.table[pypeg2.K("werld")]
  46. class ParseKeywordTestCase3(ParserTestCase):
  47. def runTest(self):
  48. parser = pypeg2.Parser()
  49. with self.assertRaises(SyntaxError):
  50. r = parser.parse(", world", pypeg2.K("hallo"))
  51. pypeg2.Keyword.table[pypeg2.K("hallo")]
  52. class ParseRegexTestCase1(ParserTestCase):
  53. def runTest(self):
  54. parser = pypeg2.Parser()
  55. r = parser.parse("hello, world", re.compile(r"h.[lx]l\S", re.U))
  56. self.assertEqual(r, (", world", "hello"))
  57. class ParseRegexTestCase2(ParserTestCase):
  58. def runTest(self):
  59. parser = pypeg2.Parser()
  60. with self.assertRaises(SyntaxError):
  61. r = parser.parse("hello, world", re.compile(r"\d", re.U))
  62. class ParseSymbolTestCase1(ParserTestCase):
  63. def runTest(self):
  64. parser = pypeg2.Parser()
  65. r = parser.parse("hello, world", pypeg2.Symbol)
  66. self.assertEqual(r, (", world", pypeg2.Symbol("hello")))
  67. class ParseSymbolTestCase2(ParserTestCase):
  68. def runTest(self):
  69. parser = pypeg2.Parser()
  70. with self.assertRaises(SyntaxError):
  71. r = parser.parse(", world", pypeg2.Symbol)
  72. class ParseAttributeTestCase(ParserTestCase):
  73. def runTest(self):
  74. parser = pypeg2.Parser()
  75. r = parser.parse("hello, world", pypeg2.attr("some", pypeg2.Symbol))
  76. self.assertEqual(
  77. r,
  78. (
  79. ', world',
  80. pypeg2.attr.Class(name='some', thing=pypeg2.Symbol('hello'), subtype=None)
  81. )
  82. )
  83. class ParseTupleTestCase1(ParserTestCase):
  84. def runTest(self):
  85. parser = pypeg2.Parser()
  86. r = parser.parse("hello, world", (pypeg2.name(), ",", pypeg2.name()))
  87. self.assertEqual(
  88. r,
  89. (
  90. '',
  91. [
  92. pypeg2.attr.Class(name='name', thing=pypeg2.Symbol('hello'), subtype=None),
  93. pypeg2.attr.Class(name='name', thing=pypeg2.Symbol('world'), subtype=None)
  94. ]
  95. )
  96. )
  97. class ParseTupleTestCase2(ParserTestCase):
  98. def runTest(self):
  99. parser = pypeg2.Parser()
  100. with self.assertRaises(ValueError):
  101. parser.parse("hello, world", (-23, "x"))
  102. class ParseSomeTestCase1(ParserTestCase):
  103. def runTest(self):
  104. parser = pypeg2.Parser()
  105. r = parser.parse("hello, world", pypeg2.some(re.compile(r"\w", re.U)))
  106. self.assertEqual(r, (', world', ['h', 'e', 'l', 'l', 'o']))
  107. class ParseSomeTestCase2(ParserTestCase):
  108. def runTest(self):
  109. parser = pypeg2.Parser()
  110. with self.assertRaises(SyntaxError):
  111. r = parser.parse("hello, world", pypeg2.some(re.compile(r"\d", re.U)))
  112. class ParseMaybeSomeTestCase1(ParserTestCase):
  113. def runTest(self):
  114. parser = pypeg2.Parser()
  115. r = parser.parse("hello, world", pypeg2.maybe_some(re.compile(r"\w", re.U)))
  116. self.assertEqual(r, (', world', ['h', 'e', 'l', 'l', 'o']))
  117. class ParseMaybeSomeTestCase2(ParserTestCase):
  118. def runTest(self):
  119. parser = pypeg2.Parser()
  120. r = parser.parse("hello, world", pypeg2.maybe_some(re.compile(r"\d", re.U)))
  121. self.assertEqual(r, ('hello, world', []))
  122. class ParseCardinalityTestCase1(ParserTestCase):
  123. def runTest(self):
  124. parser = pypeg2.Parser()
  125. r = parser.parse("hello, world", (5, re.compile(r"\w", re.U)))
  126. self.assertEqual(r, (', world', ['h', 'e', 'l', 'l', 'o']))
  127. class ParseCardinalityTestCase2(ParserTestCase):
  128. def runTest(self):
  129. parser = pypeg2.Parser()
  130. with self.assertRaises(SyntaxError):
  131. r = parser.parse("hello, world", (6, re.compile(r"\w", re.U)))
  132. class ParseOptionsTestCase1(ParserTestCase):
  133. def runTest(self):
  134. parser = pypeg2.Parser()
  135. r = parser.parse("hello, world", [re.compile(r"\d+", re.U), pypeg2.word])
  136. self.assertEqual(r, (', world', 'hello'))
  137. class ParseOptionsTestCase2(ParserTestCase):
  138. def runTest(self):
  139. parser = pypeg2.Parser()
  140. with self.assertRaises(SyntaxError):
  141. r = parser.parse("hello, world", ["x", "y"])
  142. class ParseListTestCase1(ParserTestCase):
  143. class Chars(pypeg2.List):
  144. grammar = pypeg2.some(re.compile(r"\w", re.U)), pypeg2.attr("comma", ",")
  145. def runTest(self):
  146. parser = pypeg2.Parser()
  147. r = parser.parse("hello, world", ParseListTestCase1.Chars)
  148. self.assertEqual(r, (
  149. 'world',
  150. ParseListTestCase1.Chars(['h', 'e', 'l', 'l', 'o']))
  151. )
  152. self.assertEqual(r[1].comma, None)
  153. class ParseListTestCase2(ParserTestCase):
  154. class Digits(pypeg2.List):
  155. grammar = pypeg2.some(re.compile(r"\d", re.U))
  156. def runTest(self):
  157. parser = pypeg2.Parser()
  158. with self.assertRaises(SyntaxError):
  159. r = parser.parse("hello, world", ParseListTestCase2.Digits)
  160. class ParseClassTestCase1(ParserTestCase):
  161. class Word(str):
  162. grammar = pypeg2.word
  163. def runTest(self):
  164. parser = pypeg2.Parser()
  165. r = parser.parse("hello, world", ParseClassTestCase1.Word)
  166. self.assertEqual(type(r[1]), ParseClassTestCase1.Word)
  167. self.assertEqual(r[1], "hello")
  168. class ParseClassTestCase2(ParserTestCase):
  169. class Word(str):
  170. grammar = pypeg2.word, pypeg2.attr("comma", ",")
  171. def __init__(self, data):
  172. self.polished = False
  173. def polish(self):
  174. self.polished = True
  175. def runTest(self):
  176. parser = pypeg2.Parser()
  177. r = parser.parse("hello, world", ParseClassTestCase2.Word)
  178. self.assertEqual(type(r[1]), ParseClassTestCase2.Word)
  179. self.assertEqual(r[1], "hello")
  180. self.assertTrue(r[1].polished)
  181. self.assertEqual(r[1].comma, None)
  182. class Parm(object):
  183. grammar = pypeg2.name(), "=", pypeg2.attr("value", int)
  184. class Parms(pypeg2.Namespace):
  185. grammar = (pypeg2.csl(Parm), pypeg2.flag("fullstop", "."),
  186. pypeg2.flag("semicolon", ";"))
  187. class ParseNLTestCase1(ParserTestCase):
  188. def runTest(self):
  189. parser = pypeg2.Parser()
  190. parser.comment = pypeg2.comment_c
  191. t, parms = parser.parse("x=23 /* Illuminati */, y=42 /* the answer */;", Parms)
  192. self.assertEqual(parms["x"].value, 23)
  193. self.assertEqual(parms["y"].value, 42)
  194. self.assertEqual(parms.fullstop, False)
  195. self.assertEqual(parms.semicolon, True)
  196. class EnumTest(pypeg2.Symbol):
  197. grammar = pypeg2.Enum( pypeg2.K("int"), pypeg2.K("long") )
  198. class ParseEnumTestCase1(ParserTestCase):
  199. def runTest(self):
  200. parser = pypeg2.Parser()
  201. t, r = parser.parse("int", EnumTest)
  202. self.assertEqual(r, "int")
  203. class ParseEnumTestCase2(ParserTestCase):
  204. def runTest(self):
  205. parser = pypeg2.Parser()
  206. with self.assertRaises(SyntaxError):
  207. t, r = parser.parse("float", EnumTest)
  208. class ParseInvisibleTestCase(ParserTestCase):
  209. class C1(str):
  210. grammar = pypeg2.ignore("!"), pypeg2.restline
  211. def runTest(self):
  212. r = pypeg2.parse("!all", type(self).C1)
  213. self.assertEqual(str(r), "all")
  214. self.assertEqual(r._ignore1, None)
  215. class ParseOmitTestCase(ParserTestCase):
  216. def runTest(self):
  217. r = pypeg2.parse("hello", pypeg2.omit(pypeg2.word))
  218. self.assertEqual(r, None)
  219. class ComposeTestCase(unittest.TestCase): pass
  220. class ComposeString(object):
  221. grammar = "something"
  222. class ComposeStringTestCase(ComposeTestCase):
  223. def runTest(self):
  224. x = ComposeString()
  225. t = pypeg2.compose(x)
  226. self.assertEqual(t, "something")
  227. class ComposeRegex(str):
  228. grammar = pypeg2.word
  229. class ComposeRegexTestCase(ComposeTestCase):
  230. def runTest(self):
  231. x = ComposeRegex("something")
  232. t = pypeg2.compose(x)
  233. self.assertEqual(t, "something")
  234. class ComposeKeyword(object):
  235. grammar = pypeg2.K("hallo")
  236. class ComposeKeywordTestCase(ComposeTestCase):
  237. def runTest(self):
  238. x = ComposeKeyword()
  239. t = pypeg2.compose(x)
  240. self.assertEqual(t, "hallo")
  241. class ComposeSymbol(pypeg2.Symbol): pass
  242. class ComposeSymbolTestCase(ComposeTestCase):
  243. def runTest(self):
  244. x = ComposeSymbol("hello")
  245. t = pypeg2.compose(x)
  246. self.assertEqual(t, "hello")
  247. class ComposeAttribute(object):
  248. grammar = pypeg2.name()
  249. class ComposeAttributeTestCase(ComposeTestCase):
  250. def runTest(self):
  251. x = ComposeAttribute()
  252. x.name = pypeg2.Symbol("hello")
  253. t = pypeg2.compose(x)
  254. self.assertEqual(t, "hello")
  255. class ComposeFlag(object):
  256. grammar = pypeg2.flag("mark", "MARK")
  257. class ComposeFlagTestCase1(ComposeTestCase):
  258. def runTest(self):
  259. x = ComposeFlag()
  260. x.mark = True
  261. t = pypeg2.compose(x)
  262. self.assertEqual(t, "MARK")
  263. class ComposeFlagTestCase2(ComposeTestCase):
  264. def runTest(self):
  265. x = ComposeFlag()
  266. x.mark = False
  267. t = pypeg2.compose(x)
  268. self.assertEqual(t, "")
  269. class ComposeTuple(pypeg2.List):
  270. grammar = pypeg2.csl(pypeg2.word)
  271. class ComposeTupleTestCase(ComposeTestCase):
  272. def runTest(self):
  273. x = ComposeTuple(["hello", "world"])
  274. t = pypeg2.compose(x)
  275. self.assertEqual(t, "hello, world")
  276. class ComposeList(str):
  277. grammar = [ re.compile(r"\d+", re.U), pypeg2.word ]
  278. class ComposeListTestCase(ComposeTestCase):
  279. def runTest(self):
  280. x = ComposeList("hello")
  281. t = pypeg2.compose(x)
  282. self.assertEqual(t, "hello")
  283. class ComposeIntTestCase(ComposeTestCase):
  284. def runTest(self):
  285. x = pypeg2.compose(23, int)
  286. self.assertEqual(x, "23")
  287. class C2(str):
  288. grammar = pypeg2.attr("some", "!"), pypeg2.restline
  289. class ComposeInvisibleTestCase(ParserTestCase):
  290. def runTest(self):
  291. r = pypeg2.parse("!all", C2)
  292. self.assertEqual(str(r), "all")
  293. self.assertEqual(r.some, None)
  294. t = pypeg2.compose(r, C2)
  295. self.assertEqual(t, "!all")
  296. class ComposeOmitTestCase(ParserTestCase):
  297. def runTest(self):
  298. t = pypeg2.compose('hello', pypeg2.omit(pypeg2.word))
  299. self.assertEqual(t, "")
  300. class CslPython32Compatibility(ParserTestCase):
  301. def runTest(self):
  302. try:
  303. g = eval("pypeg2.csl('hello', 'world', separator=';')")
  304. except TypeError:
  305. return
  306. self.assertEqual(g, ("hello", "world", -1, (";", pypeg2.blank, "hello", "world")))
  307. if __name__ == '__main__':
  308. unittest.main()