temporal_operator.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. """@package grass.temporal
  2. Temporal operator evaluation with PLY
  3. (C) 2013 by the GRASS Development Team
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS
  6. for details.
  7. :authors: Thomas Leppelt and Soeren Gebbert
  8. .. code-block:: python
  9. >>> p = TemporalOperatorParser()
  10. >>> expression = "{equal|equivalent|cover|in|meet|contain|overlap}"
  11. >>> p.parse(expression, optype = 'relation')
  12. >>> print((p.relations, p.temporal, p.function))
  13. (['equal', 'equivalent', 'cover', 'in', 'meet', 'contain', 'overlap'], None, None)
  14. >>> p = TemporalOperatorParser()
  15. >>> expression = "{equal| during}"
  16. >>> p.parse(expression, optype = 'relation')
  17. >>> print((p.relations, p.temporal, p.function))
  18. (['equal', 'during'], None, None)
  19. >>> p = TemporalOperatorParser()
  20. >>> expression = "{contains | starts}"
  21. >>> p.parse(expression)
  22. >>> print((p.relations, p.temporal, p.function))
  23. (['contains', 'starts'], None, None)
  24. >>> p = TemporalOperatorParser()
  25. >>> expression = "{&&, during}"
  26. >>> p.parse(expression, optype = 'boolean')
  27. >>> print((p.relations, p.temporal, p.function, p.aggregate))
  28. (['during'], 'l', '&&', '&')
  29. >>> p = TemporalOperatorParser()
  30. >>> expression = "{||, equal | during}"
  31. >>> p.parse(expression, optype = 'boolean')
  32. >>> print((p.relations, p.temporal, p.function, p.aggregate))
  33. (['equal', 'during'], 'l', '||', '|')
  34. >>> p = TemporalOperatorParser()
  35. >>> expression = "{||, equal | during, &}"
  36. >>> p.parse(expression, optype = 'boolean')
  37. >>> print((p.relations, p.temporal, p.function, p.aggregate))
  38. (['equal', 'during'], 'l', '||', '&')
  39. >>> p = TemporalOperatorParser()
  40. >>> expression = "{&&, during, |}"
  41. >>> p.parse(expression, optype = 'boolean')
  42. >>> print((p.relations, p.temporal, p.function, p.aggregate))
  43. (['during'], 'l', '&&', '|')
  44. >>> p = TemporalOperatorParser()
  45. >>> expression = "{&&, during, |, r}"
  46. >>> p.parse(expression, optype = 'boolean')
  47. >>> print((p.relations, p.temporal, p.function, p.aggregate))
  48. (['during'], 'r', '&&', '|')
  49. >>> p = TemporalOperatorParser()
  50. >>> expression = "{&&, during, u}"
  51. >>> p.parse(expression, optype = 'boolean')
  52. >>> print((p.relations, p.temporal, p.function, p.aggregate))
  53. (['during'], 'u', '&&', '&')
  54. >>> p = TemporalOperatorParser()
  55. >>> expression = "{:, during, r}"
  56. >>> p.parse(expression, optype = 'select')
  57. >>> print((p.relations, p.temporal, p.function))
  58. (['during'], 'r', ':')
  59. >>> p = TemporalOperatorParser()
  60. >>> expression = "{!:, equal | contains, d}"
  61. >>> p.parse(expression, optype = 'select')
  62. >>> print((p.relations, p.temporal, p.function))
  63. (['equal', 'contains'], 'd', '!:')
  64. >>> p = TemporalOperatorParser()
  65. >>> expression = "{#, during, r}"
  66. >>> p.parse(expression, optype = 'hash')
  67. >>> print((p.relations, p.temporal, p.function))
  68. (['during'], 'r', '#')
  69. >>> p = TemporalOperatorParser()
  70. >>> expression = "{#, equal | contains}"
  71. >>> p.parse(expression, optype = 'hash')
  72. >>> print((p.relations, p.temporal, p.function))
  73. (['equal', 'contains'], 'l', '#')
  74. >>> p = TemporalOperatorParser()
  75. >>> expression = "{+, during, r}"
  76. >>> p.parse(expression, optype = 'raster')
  77. >>> print((p.relations, p.temporal, p.function))
  78. (['during'], 'r', '+')
  79. >>> p = TemporalOperatorParser()
  80. >>> expression = "{/, equal | contains}"
  81. >>> p.parse(expression, optype = 'raster')
  82. >>> print((p.relations, p.temporal, p.function))
  83. (['equal', 'contains'], 'l', '/')
  84. >>> p = TemporalOperatorParser()
  85. >>> expression = "{+, equal | contains,intersect}"
  86. >>> p.parse(expression, optype = 'raster')
  87. >>> print((p.relations, p.temporal, p.function))
  88. (['equal', 'contains'], 'i', '+')
  89. >>> p = TemporalOperatorParser()
  90. >>> expression = "{*, contains,disjoint}"
  91. >>> p.parse(expression, optype = 'raster')
  92. >>> print((p.relations, p.temporal, p.function))
  93. (['contains'], 'd', '*')
  94. >>> p = TemporalOperatorParser()
  95. >>> expression = "{~, equal,left}"
  96. >>> p.parse(expression, optype = 'overlay')
  97. >>> print((p.relations, p.temporal, p.function))
  98. (['equal'], 'l', '~')
  99. >>> p = TemporalOperatorParser()
  100. >>> expression = "{^, over,right}"
  101. >>> p.parse(expression, optype = 'overlay')
  102. >>> print((p.relations, p.temporal, p.function))
  103. (['overlaps', 'overlapped'], 'r', '^')
  104. >>> p = TemporalOperatorParser()
  105. >>> expression = "{&&, equal | during | contains | starts, &}"
  106. >>> p.parse(expression, optype = 'boolean')
  107. >>> print((p.relations, p.temporal, p.function, p.aggregate))
  108. (['equal', 'during', 'contains', 'starts'], 'l', '&&', '&')
  109. >>> p = TemporalOperatorParser()
  110. >>> expression = "{&&, equal | during | contains | starts, &&&&&}"
  111. >>> p.parse(expression, optype = 'boolean')
  112. Traceback (most recent call last):
  113. SyntaxError: Unexpected syntax error in expression "{&&, equal | during | contains | starts, &&&&&}" at position 42 near &
  114. >>> p = TemporalOperatorParser()
  115. >>> expression = "{+, starting}"
  116. >>> p.parse(expression)
  117. Traceback (most recent call last):
  118. SyntaxError: syntax error on line 1 position 4 near 'starting'
  119. >>> p = TemporalOperatorParser()
  120. >>> expression = "{nope, start, |, l}"
  121. >>> p.parse(expression)
  122. Traceback (most recent call last):
  123. SyntaxError: syntax error on line 1 position 1 near 'nope'
  124. >>> p = TemporalOperatorParser()
  125. >>> expression = "{++, start, |, l}"
  126. >>> p.parse(expression)
  127. Traceback (most recent call last):
  128. SyntaxError: Unexpected syntax error in expression "{++, start, |, l}" at position 2 near +
  129. >>> p = TemporalOperatorParser()
  130. >>> expression = "{^, over, right}"
  131. >>> p.parse(expression, optype='rter')
  132. Traceback (most recent call last):
  133. SyntaxError: Unknown optype rter, must be one of ['select', 'boolean', 'raster', 'hash', 'relation', 'overlay']
  134. """
  135. from __future__ import print_function
  136. try:
  137. import ply.lex as lex
  138. import ply.yacc as yacc
  139. except ImportError:
  140. pass
  141. class TemporalOperatorLexer(object):
  142. """Lexical analyzer for the GRASS GIS temporal operator"""
  143. # Functions that defines topological relations.
  144. relations = {
  145. # temporal relations
  146. "equal": "EQUAL",
  147. "follows": "FOLLOWS",
  148. "precedes": "PRECEDES",
  149. "overlaps": "OVERLAPS",
  150. "overlapped": "OVERLAPPED",
  151. "during": "DURING",
  152. "starts": "STARTS",
  153. "finishes": "FINISHES",
  154. "contains": "CONTAINS",
  155. "started": "STARTED",
  156. "finished": "FINISHED",
  157. "over": "OVER",
  158. # spatial relations
  159. "equivalent": "EQUIVALENT",
  160. "cover": "COVER",
  161. "overlap": "OVERLAP",
  162. "in": "IN",
  163. "contain": "CONTAIN",
  164. "meet": "MEET",
  165. }
  166. # This is the list of token names.
  167. tokens = (
  168. "COMMA",
  169. "LEFTREF",
  170. "RIGHTREF",
  171. "UNION",
  172. "DISJOINT",
  173. "INTERSECT",
  174. "HASH",
  175. "OR",
  176. "AND",
  177. "DISOR",
  178. "XOR",
  179. "NOT",
  180. "MOD",
  181. "DIV",
  182. "MULT",
  183. "ADD",
  184. "SUB",
  185. "T_SELECT",
  186. "T_NOT_SELECT",
  187. "CLPAREN",
  188. "CRPAREN",
  189. )
  190. # Build the token list
  191. tokens = tokens + tuple(relations.values())
  192. # Regular expression rules for simple tokens
  193. t_T_SELECT = r":"
  194. t_T_NOT_SELECT = r"!:"
  195. t_COMMA = r","
  196. t_LEFTREF = "^[l|left]"
  197. t_RIGHTREF = "^[r|right]"
  198. t_UNION = "^[u|union]"
  199. t_DISJOINT = "^[d|disjoint]"
  200. t_INTERSECT = "^[i|intersect]"
  201. t_HASH = r"\#"
  202. t_OR = r"[\|]"
  203. t_AND = r"[&]"
  204. t_DISOR = r"\+"
  205. t_XOR = r"\^"
  206. t_NOT = r"\~"
  207. t_MOD = r"[\%]"
  208. t_DIV = r"[\/]"
  209. t_MULT = r"[\*]"
  210. t_ADD = r"[\+]"
  211. t_SUB = r"[-]"
  212. t_CLPAREN = r"\{"
  213. t_CRPAREN = r"\}"
  214. # These are the things that should be ignored.
  215. t_ignore = " \t\n"
  216. # Track line numbers.
  217. def t_newline(self, t):
  218. r"\n+"
  219. t.lineno += len(t.value)
  220. def t_NAME(self, t):
  221. r"[a-zA-Z_][a-zA-Z_0-9]*"
  222. return self.temporal_symbol(t)
  223. # Parse symbols
  224. def temporal_symbol(self, t):
  225. # Check for reserved words
  226. if t.value in TemporalOperatorLexer.relations.keys():
  227. t.type = TemporalOperatorLexer.relations.get(t.value)
  228. elif t.value == "l" or t.value == "left":
  229. t.value = "l"
  230. t.type = "LEFTREF"
  231. elif t.value == "r" or t.value == "right":
  232. t.value = "r"
  233. t.type = "RIGHTREF"
  234. elif t.value == "u" or t.value == "union":
  235. t.value = "u"
  236. t.type = "UNION"
  237. elif t.value == "d" or t.value == "disjoint":
  238. t.value = "d"
  239. t.type = "DISJOINT"
  240. elif t.value == "i" or t.value == "intersect":
  241. t.value = "i"
  242. t.type = "INTERSECT"
  243. else:
  244. self.t_error(t)
  245. return t
  246. # Handle errors.
  247. def t_error(self, t):
  248. raise SyntaxError(
  249. "syntax error on line %d position %i near '%s'"
  250. % (t.lineno, t.lexpos, t.value)
  251. )
  252. # Build the lexer
  253. def build(self, **kwargs):
  254. self.lexer = lex.lex(
  255. module=self, optimize=False, nowarn=True, debug=0, **kwargs
  256. )
  257. # Just for testing
  258. def test(self, data):
  259. self.name_list = {}
  260. print(data)
  261. self.lexer.input(data)
  262. while True:
  263. tok = self.lexer.token()
  264. if not tok:
  265. break
  266. print(tok)
  267. ###############################################################################
  268. class TemporalOperatorParser(object):
  269. """The temporal operator class"""
  270. def __init__(self):
  271. self.lexer = TemporalOperatorLexer()
  272. self.lexer.build()
  273. self.parser = yacc.yacc(module=self, debug=0)
  274. self.relations = None # Temporal relations (equals, contain, during, ...)
  275. self.temporal = None # Temporal operation (intersect, left, right, ...)
  276. self.function = None # Actual operation (+, -, /, *, ... )
  277. self.aggregate = None # Aggregation function (|, &)
  278. self.optype_list = [
  279. "select",
  280. "boolean",
  281. "raster",
  282. "hash",
  283. "relation",
  284. "overlay",
  285. ]
  286. def parse(self, expression, optype="relation"):
  287. """Parse the expression and fill the object variables
  288. :param expression:
  289. :param optype: The parameter optype can be of type:
  290. - select { :, during, r}
  291. - boolean {&&, contains, |}
  292. - raster { *, equal, |}
  293. - overlay { |, starts, &}
  294. - hash { #, during, l}
  295. - relation {during}
  296. :return:
  297. """
  298. self.optype = optype
  299. if optype not in self.optype_list:
  300. raise SyntaxError(
  301. "Unknown optype %s, must be one of %s"
  302. % (self.optype, str(self.optype_list))
  303. )
  304. self.expression = expression
  305. self.parser.parse(expression)
  306. # Error rule for syntax errors.
  307. def p_error(self, t):
  308. raise SyntaxError(
  309. "Unexpected syntax error in expression"
  310. ' "%s" at position %i near %s' % (self.expression, t.lexpos, t.value)
  311. )
  312. # Get the tokens from the lexer class
  313. tokens = TemporalOperatorLexer.tokens
  314. def p_relation_operator(self, t):
  315. # {during}
  316. # {during | equal | starts}
  317. """
  318. operator : CLPAREN relation CRPAREN
  319. | CLPAREN relationlist CRPAREN
  320. """
  321. # Check for correct type.
  322. if not self.optype == "relation":
  323. raise SyntaxError('Wrong optype "%s" must be "relation"' % self.optype)
  324. else:
  325. # Set three operator components.
  326. if isinstance(t[2], list):
  327. self.relations = t[2]
  328. else:
  329. self.relations = [t[2]]
  330. self.temporal = None
  331. self.function = None
  332. t[0] = t[2]
  333. def p_relation_bool_operator(self, t):
  334. # {||, during}
  335. # {&&, during | equal | starts}
  336. """
  337. operator : CLPAREN OR OR COMMA relation CRPAREN
  338. | CLPAREN AND AND COMMA relation CRPAREN
  339. | CLPAREN OR OR COMMA relationlist CRPAREN
  340. | CLPAREN AND AND COMMA relationlist CRPAREN
  341. """
  342. if not self.optype == "boolean":
  343. raise SyntaxError('Wrong optype "%s" must be "boolean"' % self.optype)
  344. else:
  345. # Set three operator components.
  346. if isinstance(t[5], list):
  347. self.relations = t[5]
  348. else:
  349. self.relations = [t[5]]
  350. self.temporal = "l"
  351. self.function = t[2] + t[3]
  352. self.aggregate = t[2]
  353. t[0] = t[2]
  354. def p_relation_bool_combi_operator(self, t):
  355. # {||, during, &}
  356. # {&&, during | equal | starts, |}
  357. """
  358. operator : CLPAREN OR OR COMMA relation COMMA OR CRPAREN
  359. | CLPAREN OR OR COMMA relation COMMA AND CRPAREN
  360. | CLPAREN AND AND COMMA relation COMMA OR CRPAREN
  361. | CLPAREN AND AND COMMA relation COMMA AND CRPAREN
  362. | CLPAREN OR OR COMMA relationlist COMMA OR CRPAREN
  363. | CLPAREN OR OR COMMA relationlist COMMA AND CRPAREN
  364. | CLPAREN AND AND COMMA relationlist COMMA OR CRPAREN
  365. | CLPAREN AND AND COMMA relationlist COMMA AND CRPAREN
  366. """
  367. if not self.optype == "boolean":
  368. raise SyntaxError('Wrong optype "%s" must be "boolean"' % self.optype)
  369. else:
  370. # Set three operator components.
  371. if isinstance(t[5], list):
  372. self.relations = t[5]
  373. else:
  374. self.relations = [t[5]]
  375. self.temporal = "l"
  376. self.function = t[2] + t[3]
  377. self.aggregate = t[7]
  378. t[0] = t[2]
  379. def p_relation_bool_combi_operator2(self, t):
  380. # {||, during, left}
  381. # {&&, during | equal | starts, union}
  382. """
  383. operator : CLPAREN OR OR COMMA relation COMMA temporal CRPAREN
  384. | CLPAREN AND AND COMMA relation COMMA temporal CRPAREN
  385. | CLPAREN OR OR COMMA relationlist COMMA temporal CRPAREN
  386. | CLPAREN AND AND COMMA relationlist COMMA temporal CRPAREN
  387. """
  388. if not self.optype == "boolean":
  389. raise SyntaxError('Wrong optype "%s" must be "boolean"' % self.optype)
  390. else:
  391. # Set three operator components.
  392. if isinstance(t[5], list):
  393. self.relations = t[5]
  394. else:
  395. self.relations = [t[5]]
  396. self.temporal = t[7]
  397. self.function = t[2] + t[3]
  398. self.aggregate = t[2]
  399. t[0] = t[2]
  400. def p_relation_bool_combi_operator3(self, t):
  401. # {||, during, |, left}
  402. # {&&, during | equal | starts, &, union}
  403. """
  404. operator : CLPAREN OR OR COMMA relation COMMA OR COMMA temporal CRPAREN
  405. | CLPAREN OR OR COMMA relation COMMA AND COMMA temporal CRPAREN
  406. | CLPAREN AND AND COMMA relation COMMA OR COMMA temporal CRPAREN
  407. | CLPAREN AND AND COMMA relation COMMA AND COMMA temporal CRPAREN
  408. | CLPAREN OR OR COMMA relationlist COMMA OR COMMA temporal CRPAREN
  409. | CLPAREN OR OR COMMA relationlist COMMA AND COMMA temporal CRPAREN
  410. | CLPAREN AND AND COMMA relationlist COMMA OR COMMA temporal CRPAREN
  411. | CLPAREN AND AND COMMA relationlist COMMA AND COMMA temporal CRPAREN
  412. """
  413. if not self.optype == "boolean":
  414. raise SyntaxError('Wrong optype "%s" must be "relation"' % self.optype)
  415. else:
  416. # Set three operator components.
  417. if isinstance(t[5], list):
  418. self.relations = t[5]
  419. else:
  420. self.relations = [t[5]]
  421. self.temporal = t[9]
  422. self.function = t[2] + t[3]
  423. self.aggregate = t[7]
  424. t[0] = t[2]
  425. def p_select_relation_operator(self, t):
  426. # {!:}
  427. # { :, during}
  428. # {!:, during | equal | starts}
  429. # { :, during | equal | starts, l}
  430. """
  431. operator : CLPAREN select CRPAREN
  432. | CLPAREN select COMMA relation CRPAREN
  433. | CLPAREN select COMMA relationlist CRPAREN
  434. | CLPAREN select COMMA relation COMMA temporal CRPAREN
  435. | CLPAREN select COMMA relationlist COMMA temporal CRPAREN
  436. """
  437. if not self.optype == "select":
  438. raise SyntaxError('Wrong optype "%s" must be "select"' % self.optype)
  439. else:
  440. if len(t) == 4:
  441. # Set three operator components.
  442. self.relations = ["equal", "equivalent"]
  443. self.temporal = "l"
  444. self.function = t[2]
  445. elif len(t) == 6:
  446. if isinstance(t[4], list):
  447. self.relations = t[4]
  448. else:
  449. self.relations = [t[4]]
  450. self.temporal = "l"
  451. self.function = t[2]
  452. elif len(t) == 8:
  453. if isinstance(t[4], list):
  454. self.relations = t[4]
  455. else:
  456. self.relations = [t[4]]
  457. self.temporal = t[6]
  458. self.function = t[2]
  459. t[0] = t[2]
  460. def p_hash_relation_operator(self, t):
  461. # {#}
  462. # {#, during}
  463. # {#, during | equal | starts}
  464. # {#, during | equal | starts, l}
  465. """
  466. operator : CLPAREN HASH CRPAREN
  467. | CLPAREN HASH COMMA relation CRPAREN
  468. | CLPAREN HASH COMMA relationlist CRPAREN
  469. | CLPAREN HASH COMMA relation COMMA temporal CRPAREN
  470. | CLPAREN HASH COMMA relationlist COMMA temporal CRPAREN
  471. """
  472. if not self.optype == "hash":
  473. raise SyntaxError('Wrong optype "%s" must be "hash"' % self.optype)
  474. else:
  475. if len(t) == 4:
  476. # Set three operator components.
  477. self.relations = ["equal"]
  478. self.temporal = "l"
  479. self.function = t[2]
  480. elif len(t) == 6:
  481. if isinstance(t[4], list):
  482. self.relations = t[4]
  483. else:
  484. self.relations = [t[4]]
  485. self.temporal = "l"
  486. self.function = t[2]
  487. elif len(t) == 8:
  488. if isinstance(t[4], list):
  489. self.relations = t[4]
  490. else:
  491. self.relations = [t[4]]
  492. self.temporal = t[6]
  493. self.function = t[2]
  494. t[0] = t[2]
  495. def p_raster_relation_operator(self, t):
  496. # {+}
  497. # {-, during}
  498. # {*, during | equal | starts}
  499. # {/, during | equal | starts, l}
  500. """
  501. operator : CLPAREN arithmetic CRPAREN
  502. | CLPAREN arithmetic COMMA relation CRPAREN
  503. | CLPAREN arithmetic COMMA relationlist CRPAREN
  504. | CLPAREN arithmetic COMMA relation COMMA temporal CRPAREN
  505. | CLPAREN arithmetic COMMA relationlist COMMA temporal CRPAREN
  506. """
  507. if not self.optype == "raster":
  508. raise SyntaxError('Wrong optype "%s" must be "raster"' % self.optype)
  509. else:
  510. if len(t) == 4:
  511. # Set three operator components.
  512. self.relations = ["equal"]
  513. self.temporal = "l"
  514. self.function = t[2]
  515. elif len(t) == 6:
  516. if isinstance(t[4], list):
  517. self.relations = t[4]
  518. else:
  519. self.relations = [t[4]]
  520. self.temporal = "l"
  521. self.function = t[2]
  522. elif len(t) == 8:
  523. if isinstance(t[4], list):
  524. self.relations = t[4]
  525. else:
  526. self.relations = [t[4]]
  527. self.temporal = t[6]
  528. self.function = t[2]
  529. t[0] = t[2]
  530. def p_overlay_relation_operator(self, t):
  531. # {+}
  532. # {-, during}
  533. # {~, during | equal | starts}
  534. # {^, during | equal | starts, l}
  535. """
  536. operator : CLPAREN overlay CRPAREN
  537. | CLPAREN overlay COMMA relation CRPAREN
  538. | CLPAREN overlay COMMA relationlist CRPAREN
  539. | CLPAREN overlay COMMA relation COMMA temporal CRPAREN
  540. | CLPAREN overlay COMMA relationlist COMMA temporal CRPAREN
  541. """
  542. if not self.optype == "overlay":
  543. raise SyntaxError('Wrong optype "%s" must be "overlay"' % self.optype)
  544. else:
  545. if len(t) == 4:
  546. # Set three operator components.
  547. self.relations = ["equal"]
  548. self.temporal = "l"
  549. self.function = t[2]
  550. elif len(t) == 6:
  551. if isinstance(t[4], list):
  552. self.relations = t[4]
  553. else:
  554. self.relations = [t[4]]
  555. self.temporal = "l"
  556. self.function = t[2]
  557. elif len(t) == 8:
  558. if isinstance(t[4], list):
  559. self.relations = t[4]
  560. else:
  561. self.relations = [t[4]]
  562. self.temporal = t[6]
  563. self.function = t[2]
  564. t[0] = t[2]
  565. def p_relation(self, t):
  566. # The list of relations. Temporal and spatial relations are supported
  567. """
  568. relation : EQUAL
  569. | FOLLOWS
  570. | PRECEDES
  571. | OVERLAPS
  572. | OVERLAPPED
  573. | DURING
  574. | STARTS
  575. | FINISHES
  576. | CONTAINS
  577. | STARTED
  578. | FINISHED
  579. | EQUIVALENT
  580. | COVER
  581. | OVERLAP
  582. | IN
  583. | CONTAIN
  584. | MEET
  585. """
  586. t[0] = t[1]
  587. def p_over(self, t):
  588. # The the over keyword
  589. """
  590. relation : OVER
  591. """
  592. over_list = ["overlaps", "overlapped"]
  593. t[0] = over_list
  594. def p_relationlist(self, t):
  595. # The list of relations.
  596. """
  597. relationlist : relation OR relation
  598. | relation OR relationlist
  599. """
  600. rel_list = []
  601. rel_list.append(t[1])
  602. if isinstance(t[3], list):
  603. rel_list = rel_list + t[3]
  604. else:
  605. rel_list.append(t[3])
  606. t[0] = rel_list
  607. def p_temporal_operator(self, t):
  608. # The list of relations.
  609. """
  610. temporal : LEFTREF
  611. | RIGHTREF
  612. | UNION
  613. | DISJOINT
  614. | INTERSECT
  615. """
  616. t[0] = t[1]
  617. def p_select_operator(self, t):
  618. # The list of relations.
  619. """
  620. select : T_SELECT
  621. | T_NOT_SELECT
  622. """
  623. t[0] = t[1]
  624. def p_arithmetic_operator(self, t):
  625. # The list of relations.
  626. """
  627. arithmetic : MOD
  628. | DIV
  629. | MULT
  630. | ADD
  631. | SUB
  632. """
  633. t[0] = t[1]
  634. def p_overlay_operator(self, t):
  635. # The list of relations.
  636. """
  637. overlay : AND
  638. | OR
  639. | XOR
  640. | DISOR
  641. | NOT
  642. """
  643. t[0] = t[1]
  644. ###############################################################################
  645. if __name__ == "__main__":
  646. import doctest
  647. doctest.testmod()