temporal_operator.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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:
  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("syntax error on line %d position %i near '%s'" %
  249. (t.lineno, t.lexpos, t.value))
  250. # Build the lexer
  251. def build(self,**kwargs):
  252. self.lexer = lex.lex(module=self, optimize=False,
  253. nowarn=True, debug=0, **kwargs)
  254. # Just for testing
  255. def test(self,data):
  256. self.name_list = {}
  257. print(data)
  258. self.lexer.input(data)
  259. while True:
  260. tok = self.lexer.token()
  261. if not tok:
  262. break
  263. print(tok)
  264. ###############################################################################
  265. class TemporalOperatorParser(object):
  266. """The temporal operator class"""
  267. def __init__(self):
  268. self.lexer = TemporalOperatorLexer()
  269. self.lexer.build()
  270. self.parser = yacc.yacc(module=self, debug=0)
  271. self.relations = None # Temporal relations (equals, contain, during, ...)
  272. self.temporal = None # Temporal operation (intersect, left, right, ...)
  273. self.function = None # Actual operation (+, -, /, *, ... )
  274. self.aggregate = None # Aggregation function (|, &)
  275. self.optype_list = ["select", "boolean", "raster", "hash", "relation", "overlay"]
  276. def parse(self, expression, optype='relation'):
  277. """Parse the expression and fill the object variables
  278. :param expression:
  279. :param optype: The parameter optype can be of type:
  280. - select { :, during, r}
  281. - boolean {&&, contains, |}
  282. - raster { *, equal, |}
  283. - overlay { |, starts, &}
  284. - hash { #, during, l}
  285. - relation {during}
  286. :return:
  287. """
  288. self.optype = optype
  289. if optype not in self.optype_list:
  290. raise SyntaxError("Unknown optype %s, must be one of %s"%(self.optype, str(self.optype_list)))
  291. self.expression = expression
  292. self.parser.parse(expression)
  293. # Error rule for syntax errors.
  294. def p_error(self, t):
  295. raise SyntaxError("Unexpected syntax error in expression"
  296. " \"%s\" at position %i near %s"%(self.expression,
  297. t.lexpos,
  298. t.value))
  299. # Get the tokens from the lexer class
  300. tokens = TemporalOperatorLexer.tokens
  301. def p_relation_operator(self, t):
  302. # {during}
  303. # {during | equal | starts}
  304. """
  305. operator : CLPAREN relation CRPAREN
  306. | CLPAREN relationlist CRPAREN
  307. """
  308. # Check for correct type.
  309. if not self.optype == 'relation':
  310. raise SyntaxError("Wrong optype \"%s\" must be \"relation\""%self.optype)
  311. else:
  312. # Set three operator components.
  313. if isinstance(t[2], list):
  314. self.relations = t[2]
  315. else:
  316. self.relations = [t[2]]
  317. self.temporal = None
  318. self.function = None
  319. t[0] = t[2]
  320. def p_relation_bool_operator(self, t):
  321. # {||, during}
  322. # {&&, during | equal | starts}
  323. """
  324. operator : CLPAREN OR OR COMMA relation CRPAREN
  325. | CLPAREN AND AND COMMA relation CRPAREN
  326. | CLPAREN OR OR COMMA relationlist CRPAREN
  327. | CLPAREN AND AND COMMA relationlist CRPAREN
  328. """
  329. if not self.optype == 'boolean':
  330. raise SyntaxError("Wrong optype \"%s\" must be \"boolean\""%self.optype)
  331. else:
  332. # Set three operator components.
  333. if isinstance(t[5], list):
  334. self.relations = t[5]
  335. else:
  336. self.relations = [t[5]]
  337. self.temporal = "l"
  338. self.function = t[2] + t[3]
  339. self.aggregate = t[2]
  340. t[0] = t[2]
  341. def p_relation_bool_combi_operator(self, t):
  342. # {||, during, &}
  343. # {&&, during | equal | starts, |}
  344. """
  345. operator : CLPAREN OR OR COMMA relation COMMA OR CRPAREN
  346. | CLPAREN OR OR COMMA relation COMMA AND CRPAREN
  347. | CLPAREN AND AND COMMA relation COMMA OR CRPAREN
  348. | CLPAREN AND AND COMMA relation COMMA AND CRPAREN
  349. | CLPAREN OR OR COMMA relationlist COMMA OR CRPAREN
  350. | CLPAREN OR OR COMMA relationlist COMMA AND CRPAREN
  351. | CLPAREN AND AND COMMA relationlist COMMA OR CRPAREN
  352. | CLPAREN AND AND COMMA relationlist COMMA AND CRPAREN
  353. """
  354. if not self.optype == 'boolean':
  355. raise SyntaxError("Wrong optype \"%s\" must be \"boolean\""%self.optype)
  356. else:
  357. # Set three operator components.
  358. if isinstance(t[5], list):
  359. self.relations = t[5]
  360. else:
  361. self.relations = [t[5]]
  362. self.temporal = "l"
  363. self.function = t[2] + t[3]
  364. self.aggregate = t[7]
  365. t[0] = t[2]
  366. def p_relation_bool_combi_operator2(self, t):
  367. # {||, during, left}
  368. # {&&, during | equal | starts, union}
  369. """
  370. operator : CLPAREN OR OR COMMA relation COMMA temporal CRPAREN
  371. | CLPAREN AND AND COMMA relation COMMA temporal CRPAREN
  372. | CLPAREN OR OR COMMA relationlist COMMA temporal CRPAREN
  373. | CLPAREN AND AND COMMA relationlist COMMA temporal CRPAREN
  374. """
  375. if not self.optype == 'boolean':
  376. raise SyntaxError("Wrong optype \"%s\" must be \"boolean\""%self.optype)
  377. else:
  378. # Set three operator components.
  379. if isinstance(t[5], list):
  380. self.relations = t[5]
  381. else:
  382. self.relations = [t[5]]
  383. self.temporal = t[7]
  384. self.function = t[2] + t[3]
  385. self.aggregate = t[2]
  386. t[0] = t[2]
  387. def p_relation_bool_combi_operator3(self, t):
  388. # {||, during, |, left}
  389. # {&&, during | equal | starts, &, union}
  390. """
  391. operator : CLPAREN OR OR COMMA relation COMMA OR COMMA temporal CRPAREN
  392. | CLPAREN OR OR COMMA relation COMMA AND COMMA temporal CRPAREN
  393. | CLPAREN AND AND COMMA relation COMMA OR COMMA temporal CRPAREN
  394. | CLPAREN AND AND COMMA relation COMMA AND COMMA temporal CRPAREN
  395. | CLPAREN OR OR COMMA relationlist COMMA OR COMMA temporal CRPAREN
  396. | CLPAREN OR OR COMMA relationlist COMMA AND COMMA temporal CRPAREN
  397. | CLPAREN AND AND COMMA relationlist COMMA OR COMMA temporal CRPAREN
  398. | CLPAREN AND AND COMMA relationlist COMMA AND COMMA temporal CRPAREN
  399. """
  400. if not self.optype == 'boolean':
  401. raise SyntaxError("Wrong optype \"%s\" must be \"relation\""%self.optype)
  402. else:
  403. # Set three operator components.
  404. if isinstance(t[5], list):
  405. self.relations = t[5]
  406. else:
  407. self.relations = [t[5]]
  408. self.temporal = t[9]
  409. self.function = t[2] + t[3]
  410. self.aggregate = t[7]
  411. t[0] = t[2]
  412. def p_select_relation_operator(self, t):
  413. # {!:}
  414. # { :, during}
  415. # {!:, during | equal | starts}
  416. # { :, during | equal | starts, l}
  417. """
  418. operator : CLPAREN select CRPAREN
  419. | CLPAREN select COMMA relation CRPAREN
  420. | CLPAREN select COMMA relationlist CRPAREN
  421. | CLPAREN select COMMA relation COMMA temporal CRPAREN
  422. | CLPAREN select COMMA relationlist COMMA temporal CRPAREN
  423. """
  424. if not self.optype == 'select':
  425. raise SyntaxError("Wrong optype \"%s\" must be \"select\""%self.optype)
  426. else:
  427. if len(t) == 4:
  428. # Set three operator components.
  429. self.relations = ['equal', 'equivalent']
  430. self.temporal = "l"
  431. self.function = t[2]
  432. elif len(t) == 6:
  433. if isinstance(t[4], list):
  434. self.relations = t[4]
  435. else:
  436. self.relations = [t[4]]
  437. self.temporal = "l"
  438. self.function = t[2]
  439. elif len(t) == 8:
  440. if isinstance(t[4], list):
  441. self.relations = t[4]
  442. else:
  443. self.relations = [t[4]]
  444. self.temporal = t[6]
  445. self.function = t[2]
  446. t[0] = t[2]
  447. def p_hash_relation_operator(self, t):
  448. # {#}
  449. # {#, during}
  450. # {#, during | equal | starts}
  451. # {#, during | equal | starts, l}
  452. """
  453. operator : CLPAREN HASH CRPAREN
  454. | CLPAREN HASH COMMA relation CRPAREN
  455. | CLPAREN HASH COMMA relationlist CRPAREN
  456. | CLPAREN HASH COMMA relation COMMA temporal CRPAREN
  457. | CLPAREN HASH COMMA relationlist COMMA temporal CRPAREN
  458. """
  459. if not self.optype == 'hash':
  460. raise SyntaxError("Wrong optype \"%s\" must be \"hash\""%self.optype)
  461. else:
  462. if len(t) == 4:
  463. # Set three operator components.
  464. self.relations = ['equal']
  465. self.temporal = "l"
  466. self.function = t[2]
  467. elif len(t) == 6:
  468. if isinstance(t[4], list):
  469. self.relations = t[4]
  470. else:
  471. self.relations = [t[4]]
  472. self.temporal = "l"
  473. self.function = t[2]
  474. elif len(t) == 8:
  475. if isinstance(t[4], list):
  476. self.relations = t[4]
  477. else:
  478. self.relations = [t[4]]
  479. self.temporal = t[6]
  480. self.function = t[2]
  481. t[0] = t[2]
  482. def p_raster_relation_operator(self, t):
  483. # {+}
  484. # {-, during}
  485. # {*, during | equal | starts}
  486. # {/, during | equal | starts, l}
  487. """
  488. operator : CLPAREN arithmetic CRPAREN
  489. | CLPAREN arithmetic COMMA relation CRPAREN
  490. | CLPAREN arithmetic COMMA relationlist CRPAREN
  491. | CLPAREN arithmetic COMMA relation COMMA temporal CRPAREN
  492. | CLPAREN arithmetic COMMA relationlist COMMA temporal CRPAREN
  493. """
  494. if not self.optype == 'raster':
  495. raise SyntaxError("Wrong optype \"%s\" must be \"raster\""%self.optype)
  496. else:
  497. if len(t) == 4:
  498. # Set three operator components.
  499. self.relations = ['equal']
  500. self.temporal = "l"
  501. self.function = t[2]
  502. elif len(t) == 6:
  503. if isinstance(t[4], list):
  504. self.relations = t[4]
  505. else:
  506. self.relations = [t[4]]
  507. self.temporal = "l"
  508. self.function = t[2]
  509. elif len(t) == 8:
  510. if isinstance(t[4], list):
  511. self.relations = t[4]
  512. else:
  513. self.relations = [t[4]]
  514. self.temporal = t[6]
  515. self.function = t[2]
  516. t[0] = t[2]
  517. def p_overlay_relation_operator(self, t):
  518. # {+}
  519. # {-, during}
  520. # {~, during | equal | starts}
  521. # {^, during | equal | starts, l}
  522. """
  523. operator : CLPAREN overlay CRPAREN
  524. | CLPAREN overlay COMMA relation CRPAREN
  525. | CLPAREN overlay COMMA relationlist CRPAREN
  526. | CLPAREN overlay COMMA relation COMMA temporal CRPAREN
  527. | CLPAREN overlay COMMA relationlist COMMA temporal CRPAREN
  528. """
  529. if not self.optype == 'overlay':
  530. raise SyntaxError("Wrong optype \"%s\" must be \"overlay\""%self.optype)
  531. else:
  532. if len(t) == 4:
  533. # Set three operator components.
  534. self.relations = ['equal']
  535. self.temporal = "l"
  536. self.function = t[2]
  537. elif len(t) == 6:
  538. if isinstance(t[4], list):
  539. self.relations = t[4]
  540. else:
  541. self.relations = [t[4]]
  542. self.temporal = "l"
  543. self.function = t[2]
  544. elif len(t) == 8:
  545. if isinstance(t[4], list):
  546. self.relations = t[4]
  547. else:
  548. self.relations = [t[4]]
  549. self.temporal = t[6]
  550. self.function = t[2]
  551. t[0] = t[2]
  552. def p_relation(self, t):
  553. # The list of relations. Temporal and spatial relations are supported
  554. """
  555. relation : EQUAL
  556. | FOLLOWS
  557. | PRECEDES
  558. | OVERLAPS
  559. | OVERLAPPED
  560. | DURING
  561. | STARTS
  562. | FINISHES
  563. | CONTAINS
  564. | STARTED
  565. | FINISHED
  566. | EQUIVALENT
  567. | COVER
  568. | OVERLAP
  569. | IN
  570. | CONTAIN
  571. | MEET
  572. """
  573. t[0] = t[1]
  574. def p_over(self, t):
  575. # The the over keyword
  576. """
  577. relation : OVER
  578. """
  579. over_list = ["overlaps", "overlapped"]
  580. t[0] = over_list
  581. def p_relationlist(self, t):
  582. # The list of relations.
  583. """
  584. relationlist : relation OR relation
  585. | relation OR relationlist
  586. """
  587. rel_list = []
  588. rel_list.append(t[1])
  589. if isinstance(t[3], list):
  590. rel_list = rel_list + t[3]
  591. else:
  592. rel_list.append(t[3])
  593. t[0] = rel_list
  594. def p_temporal_operator(self, t):
  595. # The list of relations.
  596. """
  597. temporal : LEFTREF
  598. | RIGHTREF
  599. | UNION
  600. | DISJOINT
  601. | INTERSECT
  602. """
  603. t[0] = t[1]
  604. def p_select_operator(self, t):
  605. # The list of relations.
  606. """
  607. select : T_SELECT
  608. | T_NOT_SELECT
  609. """
  610. t[0] = t[1]
  611. def p_arithmetic_operator(self, t):
  612. # The list of relations.
  613. """
  614. arithmetic : MOD
  615. | DIV
  616. | MULT
  617. | ADD
  618. | SUB
  619. """
  620. t[0] = t[1]
  621. def p_overlay_operator(self, t):
  622. # The list of relations.
  623. """
  624. overlay : AND
  625. | OR
  626. | XOR
  627. | DISOR
  628. | NOT
  629. """
  630. t[0] = t[1]
  631. ###############################################################################
  632. if __name__ == "__main__":
  633. import doctest
  634. doctest.testmod()