temporal_operator.py 23 KB

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