clipsruby 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. checksums.yaml +7 -0
  2. data/ext/clipsruby/agenda.c +1373 -0
  3. data/ext/clipsruby/agenda.h +169 -0
  4. data/ext/clipsruby/analysis.c +1142 -0
  5. data/ext/clipsruby/analysis.h +61 -0
  6. data/ext/clipsruby/argacces.c +526 -0
  7. data/ext/clipsruby/argacces.h +77 -0
  8. data/ext/clipsruby/bload.c +884 -0
  9. data/ext/clipsruby/bload.h +94 -0
  10. data/ext/clipsruby/bmathfun.c +557 -0
  11. data/ext/clipsruby/bmathfun.h +66 -0
  12. data/ext/clipsruby/bsave.c +634 -0
  13. data/ext/clipsruby/bsave.h +130 -0
  14. data/ext/clipsruby/classcom.c +976 -0
  15. data/ext/clipsruby/classcom.h +115 -0
  16. data/ext/clipsruby/classexm.c +1376 -0
  17. data/ext/clipsruby/classexm.h +97 -0
  18. data/ext/clipsruby/classfun.c +1392 -0
  19. data/ext/clipsruby/classfun.h +164 -0
  20. data/ext/clipsruby/classinf.c +1245 -0
  21. data/ext/clipsruby/classinf.h +94 -0
  22. data/ext/clipsruby/classini.c +843 -0
  23. data/ext/clipsruby/classini.h +75 -0
  24. data/ext/clipsruby/classpsr.c +957 -0
  25. data/ext/clipsruby/classpsr.h +73 -0
  26. data/ext/clipsruby/clips.h +133 -0
  27. data/ext/clipsruby/clipsruby.c +619 -0
  28. data/ext/clipsruby/clsltpsr.c +931 -0
  29. data/ext/clipsruby/clsltpsr.h +72 -0
  30. data/ext/clipsruby/commline.c +1217 -0
  31. data/ext/clipsruby/commline.h +131 -0
  32. data/ext/clipsruby/conscomp.c +1593 -0
  33. data/ext/clipsruby/conscomp.h +150 -0
  34. data/ext/clipsruby/constant.h +264 -0
  35. data/ext/clipsruby/constrct.c +1090 -0
  36. data/ext/clipsruby/constrct.h +216 -0
  37. data/ext/clipsruby/constrnt.c +554 -0
  38. data/ext/clipsruby/constrnt.h +132 -0
  39. data/ext/clipsruby/crstrtgy.c +1088 -0
  40. data/ext/clipsruby/crstrtgy.h +85 -0
  41. data/ext/clipsruby/cstrcbin.c +185 -0
  42. data/ext/clipsruby/cstrcbin.h +61 -0
  43. data/ext/clipsruby/cstrccmp.h +43 -0
  44. data/ext/clipsruby/cstrccom.c +1791 -0
  45. data/ext/clipsruby/cstrccom.h +115 -0
  46. data/ext/clipsruby/cstrcpsr.c +835 -0
  47. data/ext/clipsruby/cstrcpsr.h +97 -0
  48. data/ext/clipsruby/cstrnbin.c +282 -0
  49. data/ext/clipsruby/cstrnbin.h +55 -0
  50. data/ext/clipsruby/cstrnchk.c +826 -0
  51. data/ext/clipsruby/cstrnchk.h +91 -0
  52. data/ext/clipsruby/cstrncmp.c +238 -0
  53. data/ext/clipsruby/cstrncmp.h +57 -0
  54. data/ext/clipsruby/cstrnops.c +1176 -0
  55. data/ext/clipsruby/cstrnops.h +47 -0
  56. data/ext/clipsruby/cstrnpsr.c +1394 -0
  57. data/ext/clipsruby/cstrnpsr.h +88 -0
  58. data/ext/clipsruby/cstrnutl.c +564 -0
  59. data/ext/clipsruby/cstrnutl.h +54 -0
  60. data/ext/clipsruby/default.c +454 -0
  61. data/ext/clipsruby/default.h +57 -0
  62. data/ext/clipsruby/defins.c +971 -0
  63. data/ext/clipsruby/defins.h +127 -0
  64. data/ext/clipsruby/developr.c +677 -0
  65. data/ext/clipsruby/developr.h +69 -0
  66. data/ext/clipsruby/dffctbin.c +477 -0
  67. data/ext/clipsruby/dffctbin.h +76 -0
  68. data/ext/clipsruby/dffctbsc.c +308 -0
  69. data/ext/clipsruby/dffctbsc.h +72 -0
  70. data/ext/clipsruby/dffctcmp.c +297 -0
  71. data/ext/clipsruby/dffctcmp.h +44 -0
  72. data/ext/clipsruby/dffctdef.c +364 -0
  73. data/ext/clipsruby/dffctdef.h +104 -0
  74. data/ext/clipsruby/dffctpsr.c +179 -0
  75. data/ext/clipsruby/dffctpsr.h +49 -0
  76. data/ext/clipsruby/dffnxbin.c +520 -0
  77. data/ext/clipsruby/dffnxbin.h +67 -0
  78. data/ext/clipsruby/dffnxcmp.c +378 -0
  79. data/ext/clipsruby/dffnxcmp.h +54 -0
  80. data/ext/clipsruby/dffnxexe.c +241 -0
  81. data/ext/clipsruby/dffnxexe.h +58 -0
  82. data/ext/clipsruby/dffnxfun.c +1192 -0
  83. data/ext/clipsruby/dffnxfun.h +155 -0
  84. data/ext/clipsruby/dffnxpsr.c +514 -0
  85. data/ext/clipsruby/dffnxpsr.h +57 -0
  86. data/ext/clipsruby/dfinsbin.c +509 -0
  87. data/ext/clipsruby/dfinsbin.h +66 -0
  88. data/ext/clipsruby/dfinscmp.c +345 -0
  89. data/ext/clipsruby/dfinscmp.h +48 -0
  90. data/ext/clipsruby/drive.c +1191 -0
  91. data/ext/clipsruby/drive.h +65 -0
  92. data/ext/clipsruby/emathfun.c +1213 -0
  93. data/ext/clipsruby/emathfun.h +99 -0
  94. data/ext/clipsruby/engine.c +1568 -0
  95. data/ext/clipsruby/engine.h +203 -0
  96. data/ext/clipsruby/entities.h +276 -0
  97. data/ext/clipsruby/envrnbld.c +514 -0
  98. data/ext/clipsruby/envrnbld.h +40 -0
  99. data/ext/clipsruby/envrnmnt.c +257 -0
  100. data/ext/clipsruby/envrnmnt.h +112 -0
  101. data/ext/clipsruby/evaluatn.c +1736 -0
  102. data/ext/clipsruby/evaluatn.h +211 -0
  103. data/ext/clipsruby/expressn.c +494 -0
  104. data/ext/clipsruby/expressn.h +154 -0
  105. data/ext/clipsruby/exprnbin.c +538 -0
  106. data/ext/clipsruby/exprnbin.h +60 -0
  107. data/ext/clipsruby/exprnops.c +564 -0
  108. data/ext/clipsruby/exprnops.h +67 -0
  109. data/ext/clipsruby/exprnpsr.c +1112 -0
  110. data/ext/clipsruby/exprnpsr.h +98 -0
  111. data/ext/clipsruby/extconf.rb +2 -0
  112. data/ext/clipsruby/extnfunc.c +1015 -0
  113. data/ext/clipsruby/extnfunc.h +157 -0
  114. data/ext/clipsruby/factbin.c +447 -0
  115. data/ext/clipsruby/factbin.h +56 -0
  116. data/ext/clipsruby/factbld.c +1035 -0
  117. data/ext/clipsruby/factbld.h +63 -0
  118. data/ext/clipsruby/factcmp.c +386 -0
  119. data/ext/clipsruby/factcmp.h +46 -0
  120. data/ext/clipsruby/factcom.c +759 -0
  121. data/ext/clipsruby/factcom.h +80 -0
  122. data/ext/clipsruby/factfile.c +1761 -0
  123. data/ext/clipsruby/factfile.h +54 -0
  124. data/ext/clipsruby/factfun.c +682 -0
  125. data/ext/clipsruby/factfun.h +77 -0
  126. data/ext/clipsruby/factgen.c +1305 -0
  127. data/ext/clipsruby/factgen.h +229 -0
  128. data/ext/clipsruby/facthsh.c +438 -0
  129. data/ext/clipsruby/facthsh.h +81 -0
  130. data/ext/clipsruby/factlhs.c +250 -0
  131. data/ext/clipsruby/factlhs.h +54 -0
  132. data/ext/clipsruby/factmch.c +905 -0
  133. data/ext/clipsruby/factmch.h +68 -0
  134. data/ext/clipsruby/factmngr.c +3373 -0
  135. data/ext/clipsruby/factmngr.h +325 -0
  136. data/ext/clipsruby/factprt.c +498 -0
  137. data/ext/clipsruby/factprt.h +60 -0
  138. data/ext/clipsruby/factqpsr.c +796 -0
  139. data/ext/clipsruby/factqpsr.h +61 -0
  140. data/ext/clipsruby/factqury.c +1267 -0
  141. data/ext/clipsruby/factqury.h +112 -0
  142. data/ext/clipsruby/factrete.c +978 -0
  143. data/ext/clipsruby/factrete.h +70 -0
  144. data/ext/clipsruby/factrhs.c +667 -0
  145. data/ext/clipsruby/factrhs.h +55 -0
  146. data/ext/clipsruby/filecom.c +353 -0
  147. data/ext/clipsruby/filecom.h +137 -0
  148. data/ext/clipsruby/filertr.c +481 -0
  149. data/ext/clipsruby/filertr.h +94 -0
  150. data/ext/clipsruby/fileutil.c +1020 -0
  151. data/ext/clipsruby/fileutil.h +50 -0
  152. data/ext/clipsruby/generate.c +1079 -0
  153. data/ext/clipsruby/generate.h +57 -0
  154. data/ext/clipsruby/genrcbin.c +902 -0
  155. data/ext/clipsruby/genrcbin.h +69 -0
  156. data/ext/clipsruby/genrccmp.c +640 -0
  157. data/ext/clipsruby/genrccmp.h +59 -0
  158. data/ext/clipsruby/genrccom.c +2017 -0
  159. data/ext/clipsruby/genrccom.h +119 -0
  160. data/ext/clipsruby/genrcexe.c +737 -0
  161. data/ext/clipsruby/genrcexe.h +73 -0
  162. data/ext/clipsruby/genrcfun.c +890 -0
  163. data/ext/clipsruby/genrcfun.h +185 -0
  164. data/ext/clipsruby/genrcpsr.c +1618 -0
  165. data/ext/clipsruby/genrcpsr.h +80 -0
  166. data/ext/clipsruby/globlbin.c +458 -0
  167. data/ext/clipsruby/globlbin.h +71 -0
  168. data/ext/clipsruby/globlbsc.c +361 -0
  169. data/ext/clipsruby/globlbsc.h +83 -0
  170. data/ext/clipsruby/globlcmp.c +330 -0
  171. data/ext/clipsruby/globlcmp.h +52 -0
  172. data/ext/clipsruby/globlcom.c +289 -0
  173. data/ext/clipsruby/globlcom.h +63 -0
  174. data/ext/clipsruby/globldef.c +1087 -0
  175. data/ext/clipsruby/globldef.h +151 -0
  176. data/ext/clipsruby/globlpsr.c +530 -0
  177. data/ext/clipsruby/globlpsr.h +59 -0
  178. data/ext/clipsruby/immthpsr.c +431 -0
  179. data/ext/clipsruby/immthpsr.h +55 -0
  180. data/ext/clipsruby/incrrset.c +530 -0
  181. data/ext/clipsruby/incrrset.h +73 -0
  182. data/ext/clipsruby/inherpsr.c +850 -0
  183. data/ext/clipsruby/inherpsr.h +52 -0
  184. data/ext/clipsruby/inscom.c +2076 -0
  185. data/ext/clipsruby/inscom.h +182 -0
  186. data/ext/clipsruby/insfile.c +1764 -0
  187. data/ext/clipsruby/insfile.h +96 -0
  188. data/ext/clipsruby/insfun.c +1451 -0
  189. data/ext/clipsruby/insfun.h +134 -0
  190. data/ext/clipsruby/insmngr.c +2550 -0
  191. data/ext/clipsruby/insmngr.h +125 -0
  192. data/ext/clipsruby/insmoddp.c +1041 -0
  193. data/ext/clipsruby/insmoddp.h +91 -0
  194. data/ext/clipsruby/insmult.c +804 -0
  195. data/ext/clipsruby/insmult.h +62 -0
  196. data/ext/clipsruby/inspsr.c +602 -0
  197. data/ext/clipsruby/inspsr.h +60 -0
  198. data/ext/clipsruby/insquery.c +1278 -0
  199. data/ext/clipsruby/insquery.h +115 -0
  200. data/ext/clipsruby/insqypsr.c +729 -0
  201. data/ext/clipsruby/insqypsr.h +63 -0
  202. data/ext/clipsruby/iofun.c +2045 -0
  203. data/ext/clipsruby/iofun.h +116 -0
  204. data/ext/clipsruby/lgcldpnd.c +644 -0
  205. data/ext/clipsruby/lgcldpnd.h +75 -0
  206. data/ext/clipsruby/main.c +112 -0
  207. data/ext/clipsruby/match.h +142 -0
  208. data/ext/clipsruby/memalloc.c +481 -0
  209. data/ext/clipsruby/memalloc.h +197 -0
  210. data/ext/clipsruby/miscfun.c +1801 -0
  211. data/ext/clipsruby/miscfun.h +132 -0
  212. data/ext/clipsruby/modulbin.c +607 -0
  213. data/ext/clipsruby/modulbin.h +84 -0
  214. data/ext/clipsruby/modulbsc.c +347 -0
  215. data/ext/clipsruby/modulbsc.h +67 -0
  216. data/ext/clipsruby/modulcmp.c +499 -0
  217. data/ext/clipsruby/modulcmp.h +54 -0
  218. data/ext/clipsruby/moduldef.c +817 -0
  219. data/ext/clipsruby/moduldef.h +271 -0
  220. data/ext/clipsruby/modulpsr.c +1150 -0
  221. data/ext/clipsruby/modulpsr.h +69 -0
  222. data/ext/clipsruby/modulutl.c +1036 -0
  223. data/ext/clipsruby/modulutl.h +84 -0
  224. data/ext/clipsruby/msgcom.c +1221 -0
  225. data/ext/clipsruby/msgcom.h +125 -0
  226. data/ext/clipsruby/msgfun.c +1076 -0
  227. data/ext/clipsruby/msgfun.h +118 -0
  228. data/ext/clipsruby/msgpass.c +1441 -0
  229. data/ext/clipsruby/msgpass.h +103 -0
  230. data/ext/clipsruby/msgpsr.c +698 -0
  231. data/ext/clipsruby/msgpsr.h +73 -0
  232. data/ext/clipsruby/multifld.c +1404 -0
  233. data/ext/clipsruby/multifld.h +130 -0
  234. data/ext/clipsruby/multifun.c +2182 -0
  235. data/ext/clipsruby/multifun.h +102 -0
  236. data/ext/clipsruby/network.h +142 -0
  237. data/ext/clipsruby/objbin.c +1522 -0
  238. data/ext/clipsruby/objbin.h +79 -0
  239. data/ext/clipsruby/objcmp.c +1507 -0
  240. data/ext/clipsruby/objcmp.h +71 -0
  241. data/ext/clipsruby/object.h +260 -0
  242. data/ext/clipsruby/objrtbin.c +701 -0
  243. data/ext/clipsruby/objrtbin.h +79 -0
  244. data/ext/clipsruby/objrtbld.c +2393 -0
  245. data/ext/clipsruby/objrtbld.h +66 -0
  246. data/ext/clipsruby/objrtcmp.c +734 -0
  247. data/ext/clipsruby/objrtcmp.h +66 -0
  248. data/ext/clipsruby/objrtfnx.c +1330 -0
  249. data/ext/clipsruby/objrtfnx.h +222 -0
  250. data/ext/clipsruby/objrtgen.c +736 -0
  251. data/ext/clipsruby/objrtgen.h +63 -0
  252. data/ext/clipsruby/objrtmch.c +1524 -0
  253. data/ext/clipsruby/objrtmch.h +160 -0
  254. data/ext/clipsruby/parsefun.c +415 -0
  255. data/ext/clipsruby/parsefun.h +67 -0
  256. data/ext/clipsruby/pattern.c +1265 -0
  257. data/ext/clipsruby/pattern.h +163 -0
  258. data/ext/clipsruby/pprint.c +328 -0
  259. data/ext/clipsruby/pprint.h +79 -0
  260. data/ext/clipsruby/prccode.c +1478 -0
  261. data/ext/clipsruby/prccode.h +145 -0
  262. data/ext/clipsruby/prcdrfun.c +640 -0
  263. data/ext/clipsruby/prcdrfun.h +95 -0
  264. data/ext/clipsruby/prcdrpsr.c +1068 -0
  265. data/ext/clipsruby/prcdrpsr.h +79 -0
  266. data/ext/clipsruby/prdctfun.c +869 -0
  267. data/ext/clipsruby/prdctfun.h +77 -0
  268. data/ext/clipsruby/prntutil.c +878 -0
  269. data/ext/clipsruby/prntutil.h +125 -0
  270. data/ext/clipsruby/proflfun.c +827 -0
  271. data/ext/clipsruby/proflfun.h +118 -0
  272. data/ext/clipsruby/reorder.c +2082 -0
  273. data/ext/clipsruby/reorder.h +172 -0
  274. data/ext/clipsruby/reteutil.c +1732 -0
  275. data/ext/clipsruby/reteutil.h +111 -0
  276. data/ext/clipsruby/retract.c +710 -0
  277. data/ext/clipsruby/retract.h +74 -0
  278. data/ext/clipsruby/router.c +737 -0
  279. data/ext/clipsruby/router.h +147 -0
  280. data/ext/clipsruby/rulebin.c +1136 -0
  281. data/ext/clipsruby/rulebin.h +153 -0
  282. data/ext/clipsruby/rulebld.c +1328 -0
  283. data/ext/clipsruby/rulebld.h +62 -0
  284. data/ext/clipsruby/rulebsc.c +517 -0
  285. data/ext/clipsruby/rulebsc.h +91 -0
  286. data/ext/clipsruby/rulecmp.c +733 -0
  287. data/ext/clipsruby/rulecmp.h +63 -0
  288. data/ext/clipsruby/rulecom.c +1583 -0
  289. data/ext/clipsruby/rulecom.h +116 -0
  290. data/ext/clipsruby/rulecstr.c +892 -0
  291. data/ext/clipsruby/rulecstr.h +53 -0
  292. data/ext/clipsruby/ruledef.c +559 -0
  293. data/ext/clipsruby/ruledef.h +179 -0
  294. data/ext/clipsruby/ruledlt.c +599 -0
  295. data/ext/clipsruby/ruledlt.h +58 -0
  296. data/ext/clipsruby/rulelhs.c +1216 -0
  297. data/ext/clipsruby/rulelhs.h +52 -0
  298. data/ext/clipsruby/rulepsr.c +1073 -0
  299. data/ext/clipsruby/rulepsr.h +61 -0
  300. data/ext/clipsruby/scanner.c +856 -0
  301. data/ext/clipsruby/scanner.h +112 -0
  302. data/ext/clipsruby/setup.h +488 -0
  303. data/ext/clipsruby/sortfun.c +433 -0
  304. data/ext/clipsruby/sortfun.h +55 -0
  305. data/ext/clipsruby/strngfun.c +1173 -0
  306. data/ext/clipsruby/strngfun.h +96 -0
  307. data/ext/clipsruby/strngrtr.c +523 -0
  308. data/ext/clipsruby/strngrtr.h +97 -0
  309. data/ext/clipsruby/symblbin.c +648 -0
  310. data/ext/clipsruby/symblbin.h +64 -0
  311. data/ext/clipsruby/symblcmp.c +893 -0
  312. data/ext/clipsruby/symblcmp.h +61 -0
  313. data/ext/clipsruby/symbol.c +1961 -0
  314. data/ext/clipsruby/symbol.h +243 -0
  315. data/ext/clipsruby/sysdep.c +894 -0
  316. data/ext/clipsruby/sysdep.h +164 -0
  317. data/ext/clipsruby/textpro.c +1388 -0
  318. data/ext/clipsruby/textpro.h +77 -0
  319. data/ext/clipsruby/tmpltbin.c +609 -0
  320. data/ext/clipsruby/tmpltbin.h +108 -0
  321. data/ext/clipsruby/tmpltbsc.c +327 -0
  322. data/ext/clipsruby/tmpltbsc.h +87 -0
  323. data/ext/clipsruby/tmpltcmp.c +450 -0
  324. data/ext/clipsruby/tmpltcmp.h +57 -0
  325. data/ext/clipsruby/tmpltdef.c +584 -0
  326. data/ext/clipsruby/tmpltdef.h +155 -0
  327. data/ext/clipsruby/tmpltfun.c +2477 -0
  328. data/ext/clipsruby/tmpltfun.h +122 -0
  329. data/ext/clipsruby/tmpltlhs.c +379 -0
  330. data/ext/clipsruby/tmpltlhs.h +50 -0
  331. data/ext/clipsruby/tmpltpsr.c +819 -0
  332. data/ext/clipsruby/tmpltpsr.h +59 -0
  333. data/ext/clipsruby/tmpltrhs.c +595 -0
  334. data/ext/clipsruby/tmpltrhs.h +55 -0
  335. data/ext/clipsruby/tmpltutl.c +637 -0
  336. data/ext/clipsruby/tmpltutl.h +82 -0
  337. data/ext/clipsruby/userdata.c +156 -0
  338. data/ext/clipsruby/userdata.h +72 -0
  339. data/ext/clipsruby/userfunctions.c +70 -0
  340. data/ext/clipsruby/usrsetup.h +7 -0
  341. data/ext/clipsruby/utility.c +1594 -0
  342. data/ext/clipsruby/utility.h +250 -0
  343. data/ext/clipsruby/watch.c +865 -0
  344. data/ext/clipsruby/watch.h +124 -0
  345. data/lib/clipsruby.rb +1 -0
  346. metadata +388 -0
@@ -0,0 +1,1216 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 08/25/16 */
5
+ /* */
6
+ /* DEFRULE LHS PARSING MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Coordinates parsing of the LHS conditional */
11
+ /* elements of a rule. */
12
+ /* */
13
+ /* Principal Programmer(s): */
14
+ /* Gary D. Riley */
15
+ /* */
16
+ /* Contributing Programmer(s): */
17
+ /* */
18
+ /* Revision History: */
19
+ /* */
20
+ /* 6.30: Added const qualifiers to remove C++ */
21
+ /* deprecation warnings. */
22
+ /* */
23
+ /* 6.40: Added Env prefix to GetEvaluationError and */
24
+ /* SetEvaluationError functions. */
25
+ /* */
26
+ /* Pragma once and other inclusion changes. */
27
+ /* */
28
+ /* Added support for booleans with <stdbool.h>. */
29
+ /* */
30
+ /* Removed use of void pointers for specific */
31
+ /* data structures. */
32
+ /* */
33
+ /* UDF redesign. */
34
+ /* */
35
+ /*************************************************************/
36
+
37
+ #include "setup.h"
38
+
39
+ #if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
40
+
41
+ #include <stdio.h>
42
+ #include <string.h>
43
+
44
+ #include "agenda.h"
45
+ #include "argacces.h"
46
+ #include "constant.h"
47
+ #include "constrct.h"
48
+ #include "constrnt.h"
49
+ #include "cstrnchk.h"
50
+ #include "envrnmnt.h"
51
+ #include "exprnpsr.h"
52
+ #include "memalloc.h"
53
+ #include "pattern.h"
54
+ #include "pprint.h"
55
+ #include "prntutil.h"
56
+ #include "reorder.h"
57
+ #include "router.h"
58
+ #include "ruledef.h"
59
+ #include "scanner.h"
60
+ #include "symbol.h"
61
+
62
+ #include "rulelhs.h"
63
+
64
+ /***************************************/
65
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
66
+ /***************************************/
67
+
68
+ static struct lhsParseNode *RuleBodyParse(Environment *,const char *,struct token *,const char *,bool *);
69
+ static void DeclarationParse(Environment *,const char *,const char *,bool *);
70
+ static struct lhsParseNode *LHSPattern(Environment *,const char *,TokenType,const char *,bool *,bool,
71
+ struct token *,const char *);
72
+ static struct lhsParseNode *ConnectedPatternParse(Environment *,const char *,struct token *,bool *);
73
+ static struct lhsParseNode *GroupPatterns(Environment *,const char *,TokenType,const char *,bool *);
74
+ static struct lhsParseNode *TestPattern(Environment *,const char *,bool *);
75
+ static struct lhsParseNode *AssignmentParse(Environment *,const char *,CLIPSLexeme *,bool *);
76
+ static void TagLHSLogicalNodes(struct lhsParseNode *);
77
+ static struct lhsParseNode *SimplePatternParse(Environment *,const char *,struct token *,bool *);
78
+ static void ParseSalience(Environment *,const char *,const char *,bool *);
79
+ static void ParseAutoFocus(Environment *,const char *,bool *);
80
+
81
+ /*******************************************************************/
82
+ /* ParseRuleLHS: Coordinates all the actions necessary for parsing */
83
+ /* the LHS of a rule including the reordering of pattern */
84
+ /* conditional elements to conform with the KB Rete topology. */
85
+ /*******************************************************************/
86
+ struct lhsParseNode *ParseRuleLHS(
87
+ Environment *theEnv,
88
+ const char *readSource,
89
+ struct token *theToken,
90
+ const char *ruleName,
91
+ bool *error)
92
+ {
93
+ struct lhsParseNode *theLHS;
94
+ bool result;
95
+
96
+ *error = false;
97
+
98
+ /*========================================*/
99
+ /* Initialize salience parsing variables. */
100
+ /*========================================*/
101
+
102
+ PatternData(theEnv)->GlobalSalience = 0;
103
+ PatternData(theEnv)->GlobalAutoFocus = false;
104
+ PatternData(theEnv)->SalienceExpression = NULL;
105
+
106
+ /*============================*/
107
+ /* Set the indentation depth. */
108
+ /*============================*/
109
+
110
+ SetIndentDepth(theEnv,3);
111
+
112
+ /*=====================================================*/
113
+ /* Get the raw representation for the LHS of the rule. */
114
+ /*=====================================================*/
115
+
116
+ theLHS = RuleBodyParse(theEnv,readSource,theToken,ruleName,error);
117
+
118
+ if (*error) return NULL;
119
+
120
+ /*====================================================*/
121
+ /* Reorder the raw representation so that it consists */
122
+ /* of at most a single top level OR CE containing one */
123
+ /* or more AND CEs. */
124
+ /*====================================================*/
125
+
126
+ theLHS = ReorderPatterns(theEnv,theLHS,&result);
127
+
128
+ /*================================*/
129
+ /* Return the LHS representation. */
130
+ /*================================*/
131
+
132
+ return(theLHS);
133
+ }
134
+
135
+ /*********************************************************/
136
+ /* RuleBodyParse: Parses the LHS of a rule, but does not */
137
+ /* reorder any of the LHS patterns to conform with the */
138
+ /* KB Rete Topology. */
139
+ /* */
140
+ /* <rule-body> ::= [<declaration>] */
141
+ /* <conditional-element>* */
142
+ /* => */
143
+ /*********************************************************/
144
+ static struct lhsParseNode *RuleBodyParse(
145
+ Environment *theEnv,
146
+ const char *readSource,
147
+ struct token *theToken,
148
+ const char *ruleName,
149
+ bool *error)
150
+ {
151
+ struct lhsParseNode *theNode, *otherNodes;
152
+
153
+ /*=============================*/
154
+ /* Set the error return value. */
155
+ /*=============================*/
156
+
157
+ *error = false;
158
+
159
+ /*==================================================*/
160
+ /* If we're already at the separator, "=>", between */
161
+ /* the LHS and RHS, then the LHS is empty. */
162
+ /*==================================================*/
163
+
164
+ if ((theToken->tknType == SYMBOL_TOKEN) ?
165
+ (strcmp(theToken->lexemeValue->contents,"=>") == 0) : false)
166
+ { return NULL; }
167
+
168
+ /*===========================================*/
169
+ /* Parse the first pattern as a special case */
170
+ /* (the declare statement is allowed). */
171
+ /*===========================================*/
172
+
173
+ theNode = LHSPattern(theEnv,readSource,SYMBOL_TOKEN,"=>",error,true,theToken,ruleName);
174
+
175
+ if (*error == true)
176
+ {
177
+ ReturnLHSParseNodes(theEnv,theNode);
178
+ return NULL;
179
+ }
180
+
181
+ PPCRAndIndent(theEnv);
182
+
183
+ /*======================================*/
184
+ /* Parse the other patterns in the LHS. */
185
+ /*======================================*/
186
+
187
+ otherNodes = GroupPatterns(theEnv,readSource,SYMBOL_TOKEN,"=>",error);
188
+
189
+ if (*error == true)
190
+ {
191
+ ReturnLHSParseNodes(theEnv,theNode);
192
+ return NULL;
193
+ }
194
+
195
+ /*================================================*/
196
+ /* Construct the final LHS by combining the first */
197
+ /* pattern with the remaining patterns. */
198
+ /*================================================*/
199
+
200
+ if (theNode == NULL)
201
+ { theNode = otherNodes; }
202
+ else
203
+ { theNode->bottom = otherNodes; }
204
+
205
+ /*=======================*/
206
+ /* Return the final LHS. */
207
+ /*=======================*/
208
+
209
+ return(theNode);
210
+ }
211
+
212
+ /********************************************************/
213
+ /* DeclarationParse: Parses a defrule declaration. */
214
+ /* */
215
+ /* <declaration> ::= (declare <rule-property>+) */
216
+ /* */
217
+ /* <rule-property> ::= (salience <integer-expression>) */
218
+ /* <rule-property> ::= (auto-focus TRUE | FALSE) */
219
+ /********************************************************/
220
+ static void DeclarationParse(
221
+ Environment *theEnv,
222
+ const char *readSource,
223
+ const char *ruleName,
224
+ bool *error)
225
+ {
226
+ struct token theToken;
227
+ struct expr *packPtr;
228
+ bool notDone = true;
229
+ bool salienceParsed = false, autoFocusParsed = false;
230
+
231
+ /*===========================*/
232
+ /* Next token must be a '('. */
233
+ /*===========================*/
234
+
235
+ SavePPBuffer(theEnv," ");
236
+
237
+ GetToken(theEnv,readSource,&theToken);
238
+ if (theToken.tknType != LEFT_PARENTHESIS_TOKEN)
239
+ {
240
+ SyntaxErrorMessage(theEnv,"declare statement");
241
+ *error = true;
242
+ return;
243
+ }
244
+
245
+ /*==========================================*/
246
+ /* Continue parsing until there are no more */
247
+ /* valid rule property declarations. */
248
+ /*==========================================*/
249
+
250
+ while (notDone)
251
+ {
252
+ /*=============================================*/
253
+ /* The name of a rule property must be symbol. */
254
+ /*=============================================*/
255
+
256
+ GetToken(theEnv,readSource,&theToken);
257
+ if (theToken.tknType != SYMBOL_TOKEN)
258
+ {
259
+ SyntaxErrorMessage(theEnv,"declare statement");
260
+ *error = true;
261
+ }
262
+
263
+ /*==============================================*/
264
+ /* Parse a salience declaration if encountered. */
265
+ /*==============================================*/
266
+
267
+ else if (strcmp(theToken.lexemeValue->contents,"salience") == 0)
268
+ {
269
+ if (salienceParsed)
270
+ {
271
+ AlreadyParsedErrorMessage(theEnv,"salience declaration",NULL);
272
+ *error = true;
273
+ }
274
+ else
275
+ {
276
+ ParseSalience(theEnv,readSource,ruleName,error);
277
+ salienceParsed = true;
278
+ }
279
+ }
280
+
281
+ /*=================================================*/
282
+ /* Parse an auto-focus declaration if encountered. */
283
+ /* A global flag is used to indicate if the */
284
+ /* auto-focus feature for a rule was parsed. */
285
+ /*=================================================*/
286
+
287
+ else if (strcmp(theToken.lexemeValue->contents,"auto-focus") == 0)
288
+ {
289
+ if (autoFocusParsed)
290
+ {
291
+ AlreadyParsedErrorMessage(theEnv,"auto-focus declaration",NULL);
292
+ *error = true;
293
+ }
294
+ else
295
+ {
296
+ ParseAutoFocus(theEnv,readSource,error);
297
+ autoFocusParsed = true;
298
+ }
299
+ }
300
+
301
+ /*==========================================*/
302
+ /* Otherwise the symbol does not correspond */
303
+ /* to a valid rule property. */
304
+ /*==========================================*/
305
+
306
+ else
307
+ {
308
+ SyntaxErrorMessage(theEnv,"declare statement");
309
+ *error = true;
310
+ }
311
+
312
+ /*=====================================*/
313
+ /* Return if an error was encountered. */
314
+ /*=====================================*/
315
+
316
+ if (*error)
317
+ {
318
+ ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
319
+ PatternData(theEnv)->SalienceExpression = NULL;
320
+ return;
321
+ }
322
+
323
+ /*=======================================*/
324
+ /* Both the salience and auto-focus rule */
325
+ /* properties are closed with a ')'. */
326
+ /*=======================================*/
327
+
328
+ GetToken(theEnv,readSource,&theToken);
329
+ if (theToken.tknType != RIGHT_PARENTHESIS_TOKEN)
330
+ {
331
+ PPBackup(theEnv);
332
+ SavePPBuffer(theEnv," ");
333
+ SavePPBuffer(theEnv,theToken.printForm);
334
+ ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
335
+ PatternData(theEnv)->SalienceExpression = NULL;
336
+ SyntaxErrorMessage(theEnv,"declare statement");
337
+ *error = true;
338
+ return;
339
+ }
340
+
341
+ /*=============================================*/
342
+ /* The declare statement is closed with a ')'. */
343
+ /*=============================================*/
344
+
345
+ GetToken(theEnv,readSource,&theToken);
346
+ if (theToken.tknType == RIGHT_PARENTHESIS_TOKEN) notDone = false;
347
+ else if (theToken.tknType != LEFT_PARENTHESIS_TOKEN)
348
+ {
349
+ ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
350
+ PatternData(theEnv)->SalienceExpression = NULL;
351
+ SyntaxErrorMessage(theEnv,"declare statement");
352
+ *error = true;
353
+ return;
354
+ }
355
+ else
356
+ {
357
+ PPBackup(theEnv);
358
+ SavePPBuffer(theEnv," (");
359
+ }
360
+ }
361
+
362
+ /*==========================================*/
363
+ /* Return the value of the salience through */
364
+ /* the global variable SalienceExpression. */
365
+ /*==========================================*/
366
+
367
+ packPtr = PackExpression(theEnv,PatternData(theEnv)->SalienceExpression);
368
+ ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
369
+ PatternData(theEnv)->SalienceExpression = packPtr;
370
+ return;
371
+ }
372
+
373
+ /************************************************************/
374
+ /* ParseSalience: Parses the rest of a defrule salience */
375
+ /* declaration once the salience keyword has been parsed. */
376
+ /************************************************************/
377
+ static void ParseSalience(
378
+ Environment *theEnv,
379
+ const char *readSource,
380
+ const char *ruleName,
381
+ bool *error)
382
+ {
383
+ int salience;
384
+ UDFValue salienceValue;
385
+
386
+ /*==============================*/
387
+ /* Get the salience expression. */
388
+ /*==============================*/
389
+
390
+ SavePPBuffer(theEnv," ");
391
+
392
+ PatternData(theEnv)->SalienceExpression = ParseAtomOrExpression(theEnv,readSource,NULL);
393
+ if (PatternData(theEnv)->SalienceExpression == NULL)
394
+ {
395
+ *error = true;
396
+ return;
397
+ }
398
+
399
+ /*============================================================*/
400
+ /* Evaluate the expression and determine if it is an integer. */
401
+ /*============================================================*/
402
+
403
+ SetEvaluationError(theEnv,false);
404
+ if (EvaluateExpression(theEnv,PatternData(theEnv)->SalienceExpression,&salienceValue))
405
+ {
406
+ SalienceInformationError(theEnv,"defrule",ruleName);
407
+ *error = true;
408
+ return;
409
+ }
410
+
411
+ if (salienceValue.header->type != INTEGER_TYPE)
412
+ {
413
+ SalienceNonIntegerError(theEnv);
414
+ *error = true;
415
+ return;
416
+ }
417
+
418
+ /*=======================================================*/
419
+ /* Salience number must be in the range -10000 to 10000. */
420
+ /*=======================================================*/
421
+
422
+ salience = (int) salienceValue.integerValue->contents;
423
+
424
+ if ((salience > MAX_DEFRULE_SALIENCE) || (salience < MIN_DEFRULE_SALIENCE))
425
+ {
426
+ SalienceRangeError(theEnv,MIN_DEFRULE_SALIENCE,MAX_DEFRULE_SALIENCE);
427
+ *error = true;
428
+ return;
429
+ }
430
+
431
+ /*==========================================*/
432
+ /* If the expression is a constant integer, */
433
+ /* don't bother storing the expression. */
434
+ /*==========================================*/
435
+
436
+ if (PatternData(theEnv)->SalienceExpression->type == INTEGER_TYPE)
437
+ {
438
+ ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
439
+ PatternData(theEnv)->SalienceExpression = NULL;
440
+ }
441
+
442
+ PatternData(theEnv)->GlobalSalience = salience;
443
+ }
444
+
445
+ /**************************************************************/
446
+ /* ParseAutoFocus: Parses the rest of a defrule auto-focus */
447
+ /* declaration once the auto-focus keyword has been parsed. */
448
+ /**************************************************************/
449
+ static void ParseAutoFocus(
450
+ Environment *theEnv,
451
+ const char *readSource,
452
+ bool *error)
453
+ {
454
+ struct token theToken;
455
+
456
+ /*========================================*/
457
+ /* The auto-focus value must be a symbol. */
458
+ /*========================================*/
459
+
460
+ SavePPBuffer(theEnv," ");
461
+
462
+ GetToken(theEnv,readSource,&theToken);
463
+ if (theToken.tknType != SYMBOL_TOKEN)
464
+ {
465
+ SyntaxErrorMessage(theEnv,"auto-focus statement");
466
+ *error = true;
467
+ return;
468
+ }
469
+
470
+ /*====================================================*/
471
+ /* The auto-focus value must be either TRUE or FALSE. */
472
+ /* If a valid value is parsed, then set the value of */
473
+ /* the global variable GlobalAutoFocus. */
474
+ /*====================================================*/
475
+
476
+ if (strcmp(theToken.lexemeValue->contents,"TRUE") == 0)
477
+ { PatternData(theEnv)->GlobalAutoFocus = true; }
478
+ else if (strcmp(theToken.lexemeValue->contents,"FALSE") == 0)
479
+ { PatternData(theEnv)->GlobalAutoFocus = false; }
480
+ else
481
+ {
482
+ SyntaxErrorMessage(theEnv,"auto-focus statement");
483
+ *error = true;
484
+ }
485
+ }
486
+
487
+ /*****************************************************************/
488
+ /* LHSPattern: Parses a single conditional element found on the */
489
+ /* LHS of a rule. Conditonal element types include pattern CEs */
490
+ /* (which may be assigned to a variable), test CEs, not CEs, */
491
+ /* logical CEs, and CEs, and or CEs. */
492
+ /* */
493
+ /* <conditional-element> ::= <pattern-CE> | */
494
+ /* <assigned-pattern-CE> | */
495
+ /* <not-CE> | <and-CE> | <or-CE> | */
496
+ /* <logical-CE> | <test-CE> | */
497
+ /* <forall-CE> | <exists-CE> */
498
+ /*****************************************************************/
499
+ static struct lhsParseNode *LHSPattern(
500
+ Environment *theEnv,
501
+ const char *readSource,
502
+ TokenType terminator,
503
+ const char *terminatorString,
504
+ bool *error,
505
+ bool allowDeclaration,
506
+ struct token *firstToken,
507
+ const char *ruleName)
508
+ {
509
+ struct token theToken;
510
+ struct lhsParseNode *theNode;
511
+
512
+ /*=========================================================*/
513
+ /* Check to see if the first token has already been read. */
514
+ /* This should only occur for the first pattern in a rule. */
515
+ /*=========================================================*/
516
+
517
+ if (firstToken == NULL) GetToken(theEnv,readSource,&theToken);
518
+ else CopyToken(&theToken,firstToken);
519
+
520
+ /*=====================================================*/
521
+ /* A left parenthesis begins all CEs and declarations. */
522
+ /*=====================================================*/
523
+
524
+ if (theToken.tknType == LEFT_PARENTHESIS_TOKEN)
525
+ {
526
+ /*================================================*/
527
+ /* The first field of a pattern must be a symbol. */
528
+ /*================================================*/
529
+
530
+ GetToken(theEnv,readSource,&theToken);
531
+ if (theToken.tknType != SYMBOL_TOKEN)
532
+ {
533
+ SyntaxErrorMessage(theEnv,"the first field of a pattern");
534
+ *error = true;
535
+ return NULL;
536
+ }
537
+
538
+ /*====================================*/
539
+ /* If this is the first CE of a rule, */
540
+ /* then a declare statement is valid. */
541
+ /*====================================*/
542
+
543
+ if (allowDeclaration &&
544
+ (strcmp(theToken.lexemeValue->contents,"declare") == 0))
545
+ {
546
+ if (ruleName == NULL) SystemError(theEnv,"RULELHS",1);
547
+ DeclarationParse(theEnv,readSource,ruleName,error);
548
+ theNode = NULL;
549
+ }
550
+
551
+ /*==================================*/
552
+ /* Otherwise check for a *test* CE. */
553
+ /*==================================*/
554
+
555
+ else if (strcmp(theToken.lexemeValue->contents,"test") == 0)
556
+ { theNode = TestPattern(theEnv,readSource,error); }
557
+
558
+ /*============================================*/
559
+ /* Otherwise check for an *and*, *or*, *not*, */
560
+ /* *logical*, *exists*, or *forall* CE. */
561
+ /*============================================*/
562
+
563
+ else if ((strcmp(theToken.lexemeValue->contents,"and") == 0) ||
564
+ (strcmp(theToken.lexemeValue->contents,"logical") == 0) ||
565
+ (strcmp(theToken.lexemeValue->contents,"not") == 0) ||
566
+ (strcmp(theToken.lexemeValue->contents,"exists") == 0) ||
567
+ (strcmp(theToken.lexemeValue->contents,"forall") == 0) ||
568
+ (strcmp(theToken.lexemeValue->contents,"or") == 0))
569
+ { theNode = ConnectedPatternParse(theEnv,readSource,&theToken,error); }
570
+
571
+ /*=================================*/
572
+ /* Otherwise parse a *pattern* CE. */
573
+ /*=================================*/
574
+
575
+ else
576
+ { theNode = SimplePatternParse(theEnv,readSource,&theToken,error); }
577
+ }
578
+
579
+ /*=======================================*/
580
+ /* Check for a pattern address variable. */
581
+ /*=======================================*/
582
+
583
+ else if (theToken.tknType == SF_VARIABLE_TOKEN)
584
+ { theNode = AssignmentParse(theEnv,readSource,theToken.lexemeValue,error); }
585
+
586
+ /*=================================================*/
587
+ /* Check for the group terminator (either a "=>" */
588
+ /* separating the LHS from the RHS or a ")" ending */
589
+ /* a CE containing other CEs such as an *and* CE). */
590
+ /*=================================================*/
591
+
592
+ else if ((theToken.tknType == terminator) ?
593
+ (strcmp(theToken.printForm,terminatorString) == 0) : false)
594
+ { return NULL; }
595
+
596
+ /*====================================*/
597
+ /* Otherwise invalid syntax was used. */
598
+ /*====================================*/
599
+
600
+ else
601
+ {
602
+ SyntaxErrorMessage(theEnv,"defrule");
603
+ *error = true;
604
+ return NULL;
605
+ }
606
+
607
+ /*================================*/
608
+ /* If an error occurred, free any */
609
+ /* allocated data structures. */
610
+ /*================================*/
611
+
612
+ if (*error == true)
613
+ {
614
+ ReturnLHSParseNodes(theEnv,theNode);
615
+ return NULL;
616
+ }
617
+
618
+ /*=========================*/
619
+ /* Return the LHS pattern. */
620
+ /*=========================*/
621
+
622
+ return(theNode);
623
+ }
624
+
625
+ /*********************************************************************/
626
+ /* ConnectedPatternParse: Handles parsing of the connected */
627
+ /* conditional elements (i.e. those conditional elements that may */
628
+ /* contain one or more other conditional elements). The connected */
629
+ /* conditional elements include the *and*, *or*, *not*, *logical*, */
630
+ /* *exists*, and *forall* CEs. This routine is entered with the */
631
+ /* parsing pointing to the name of the connected CE. It is exited */
632
+ /* with the parser pointing to the closing right parenthesis of */
633
+ /* the connected CE. */
634
+ /* */
635
+ /* <and-CE> ::= (and <conditional-element>+) */
636
+ /* */
637
+ /* <or-CE> ::= (or <conditional-element>+) */
638
+ /* */
639
+ /* <logical-CE> ::= (logical <conditional-element>+) */
640
+ /* */
641
+ /* <not-CE> ::= (not <conditional-element>) */
642
+ /* */
643
+ /* <exists-CE> ::= (exists <conditional-element>+) */
644
+ /* */
645
+ /* <forall-CE> ::= (forall <conditional-element> */
646
+ /* <conditional-element>+) */
647
+ /*********************************************************************/
648
+ static struct lhsParseNode *ConnectedPatternParse(
649
+ Environment *theEnv,
650
+ const char *readSource,
651
+ struct token *theToken,
652
+ bool *error)
653
+ {
654
+ ParseNodeType connectorValue = AND_CE_NODE;
655
+ struct lhsParseNode *theNode, *tempNode, *theGroup;
656
+ const char *errorCE = NULL;
657
+ bool logical = false;
658
+ bool tempValue;
659
+
660
+ /*==========================================================*/
661
+ /* Use appropriate spacing for pretty printing of the rule. */
662
+ /*==========================================================*/
663
+
664
+ IncrementIndentDepth(theEnv,5);
665
+ if (strcmp(theToken->lexemeValue->contents,"or") == 0)
666
+ {
667
+ connectorValue = OR_CE_NODE;
668
+ errorCE = "the or conditional element";
669
+ SavePPBuffer(theEnv," ");
670
+ }
671
+ else if (strcmp(theToken->lexemeValue->contents,"and") == 0)
672
+ {
673
+ connectorValue = AND_CE_NODE;
674
+ errorCE = "the and conditional element";
675
+ SavePPBuffer(theEnv," ");
676
+ }
677
+ else if (strcmp(theToken->lexemeValue->contents,"not") == 0)
678
+ {
679
+ connectorValue = NOT_CE_NODE;
680
+ errorCE = "the not conditional element";
681
+ SavePPBuffer(theEnv," ");
682
+ }
683
+ else if (strcmp(theToken->lexemeValue->contents,"exists") == 0)
684
+ {
685
+ connectorValue = EXISTS_CE_NODE;
686
+ errorCE = "the exists conditional element";
687
+ PPCRAndIndent(theEnv);
688
+ }
689
+ else if (strcmp(theToken->lexemeValue->contents,"forall") == 0)
690
+ {
691
+ connectorValue = FORALL_CE_NODE;
692
+ errorCE = "the forall conditional element";
693
+ PPCRAndIndent(theEnv);
694
+ }
695
+ else if (strcmp(theToken->lexemeValue->contents,"logical") == 0)
696
+ {
697
+ connectorValue = AND_CE_NODE;
698
+ errorCE = "the logical conditional element";
699
+ logical = true;
700
+ PPCRAndIndent(theEnv);
701
+ }
702
+
703
+ /*=====================================================*/
704
+ /* The logical CE cannot be contained within a not CE. */
705
+ /*=====================================================*/
706
+
707
+ if (PatternData(theEnv)->WithinNotCE && logical)
708
+ {
709
+ PrintErrorID(theEnv,"RULELHS",1,true);
710
+ WriteString(theEnv,STDERR,"The logical CE cannot be used within a not/exists/forall CE.\n");
711
+ *error = true;
712
+ return NULL;
713
+ }
714
+
715
+ /*=====================================================*/
716
+ /* Remember if we're currently within a *not* CE and */
717
+ /* then check to see if we're entering a new *not* CE. */
718
+ /*=====================================================*/
719
+
720
+ tempValue = PatternData(theEnv)->WithinNotCE;
721
+ if ((connectorValue == NOT_CE_NODE) ||
722
+ (connectorValue == EXISTS_CE_NODE) ||
723
+ (connectorValue == FORALL_CE_NODE))
724
+ { PatternData(theEnv)->WithinNotCE = true; }
725
+
726
+ /*===========================================*/
727
+ /* Parse all of the CEs contained with the */
728
+ /* CE. A ) will terminate the end of the CE. */
729
+ /*===========================================*/
730
+
731
+ theGroup = GroupPatterns(theEnv,readSource,RIGHT_PARENTHESIS_TOKEN,")",error);
732
+
733
+ /*====================================*/
734
+ /* Restore the "with a *not* CE" flag */
735
+ /* and reset the indentation depth. */
736
+ /*====================================*/
737
+
738
+ PatternData(theEnv)->WithinNotCE = tempValue;
739
+ DecrementIndentDepth(theEnv,5);
740
+
741
+ /*============================================*/
742
+ /* If an error occured while parsing, return. */
743
+ /*============================================*/
744
+
745
+ if (*error == true)
746
+ {
747
+ ReturnLHSParseNodes(theEnv,theGroup);
748
+ return NULL;
749
+ }
750
+
751
+ /*=========================================================*/
752
+ /* If we parsed a *logical* CE, then mark the logical flag */
753
+ /* for all of the CEs contained within the logical CE. */
754
+ /*=========================================================*/
755
+
756
+ if (logical) TagLHSLogicalNodes(theGroup);
757
+
758
+ /*=====================================================*/
759
+ /* All the connected CEs must contain at least one CE. */
760
+ /*=====================================================*/
761
+
762
+ if (theGroup == NULL)
763
+ {
764
+ SyntaxErrorMessage(theEnv,errorCE);
765
+ *error = true;
766
+ return NULL;
767
+ }
768
+
769
+ /*============================================*/
770
+ /* A not CE may not contain more than one CE. */
771
+ /*============================================*/
772
+
773
+ if ((connectorValue == NOT_CE_NODE) && (theGroup->bottom != NULL))
774
+ {
775
+ SyntaxErrorMessage(theEnv,errorCE);
776
+ ReturnLHSParseNodes(theEnv,theGroup);
777
+ *error = true;
778
+ return NULL;
779
+ }
780
+
781
+ /*============================================*/
782
+ /* A forall CE must contain at least two CEs. */
783
+ /*============================================*/
784
+
785
+ if ((connectorValue == FORALL_CE_NODE) && (theGroup->bottom == NULL))
786
+ {
787
+ SyntaxErrorMessage(theEnv,errorCE);
788
+ ReturnLHSParseNodes(theEnv,theGroup);
789
+ *error = true;
790
+ return NULL;
791
+ }
792
+
793
+ /*========================================================*/
794
+ /* Remove an "and" and "or" CE that only contains one CE. */
795
+ /*========================================================*/
796
+
797
+ if (((connectorValue == AND_CE_NODE) || (connectorValue == OR_CE_NODE)) &&
798
+ (theGroup->bottom == NULL))
799
+ {
800
+ theGroup->logical = logical;
801
+ return(theGroup);
802
+ }
803
+
804
+ /*===========================================================*/
805
+ /* Create the top most node which connects the CEs together. */
806
+ /*===========================================================*/
807
+
808
+ theNode = GetLHSParseNode(theEnv);
809
+ theNode->logical = logical;
810
+
811
+ /*======================================================*/
812
+ /* Attach and/or/not CEs directly to the top most node. */
813
+ /*======================================================*/
814
+
815
+ if ((connectorValue == AND_CE_NODE) ||
816
+ (connectorValue == OR_CE_NODE) ||
817
+ (connectorValue == NOT_CE_NODE))
818
+ {
819
+ theNode->pnType = connectorValue;
820
+ theNode->right = theGroup;
821
+ }
822
+
823
+ /*=================================================================*/
824
+ /* Wrap two not CEs around the patterns contained in an exists CE. */
825
+ /*=================================================================*/
826
+
827
+ else if (connectorValue == EXISTS_CE_NODE)
828
+ {
829
+ theNode->pnType = NOT_CE_NODE;
830
+
831
+ theNode->right = GetLHSParseNode(theEnv);
832
+ theNode->right->pnType = NOT_CE_NODE;
833
+ theNode->right->logical = logical;
834
+
835
+ if (theGroup->bottom != NULL)
836
+ {
837
+ theNode->right->right = GetLHSParseNode(theEnv);
838
+ theNode->right->right->pnType = AND_CE_NODE;
839
+ theNode->right->right->logical = logical;
840
+ theNode->right->right->right = theGroup;
841
+ }
842
+ else
843
+ { theNode->right->right = theGroup; }
844
+ }
845
+
846
+ /*==================================================*/
847
+ /* For a forall CE, wrap a not CE around all of the */
848
+ /* CEs and a not CE around the 2nd through nth CEs. */
849
+ /*==================================================*/
850
+
851
+ else if (connectorValue == FORALL_CE_NODE)
852
+ {
853
+ theNode->pnType = NOT_CE_NODE;
854
+
855
+ tempNode = theGroup->bottom;
856
+ theGroup->bottom = NULL;
857
+
858
+ theNode->right = GetLHSParseNode(theEnv);
859
+ theNode->right->pnType = AND_CE_NODE;
860
+ theNode->right->logical = logical;
861
+ theNode->right->right = theGroup;
862
+
863
+ theGroup = tempNode;
864
+
865
+ theNode->right->right->bottom = GetLHSParseNode(theEnv);
866
+ theNode->right->right->bottom->pnType = NOT_CE_NODE;
867
+ theNode->right->right->bottom->logical = logical;
868
+
869
+ tempNode = theNode->right->right->bottom;
870
+
871
+ if (theGroup->bottom == NULL)
872
+ { tempNode->right = theGroup; }
873
+ else
874
+ {
875
+ tempNode->right = GetLHSParseNode(theEnv);
876
+ tempNode->right->pnType = AND_CE_NODE;
877
+ tempNode->right->logical = logical;
878
+ tempNode->right->right = theGroup;
879
+ }
880
+ }
881
+
882
+ /*================*/
883
+ /* Return the CE. */
884
+ /*================*/
885
+
886
+ return(theNode);
887
+ }
888
+
889
+ /***********************************************/
890
+ /* GroupPatterns: Groups a series of connected */
891
+ /* conditional elements together. */
892
+ /***********************************************/
893
+ static struct lhsParseNode *GroupPatterns(
894
+ Environment *theEnv,
895
+ const char *readSource,
896
+ TokenType terminator,
897
+ const char *terminatorString,
898
+ bool *error)
899
+ {
900
+ struct lhsParseNode *lastNode, *newNode, *theNode;
901
+
902
+ lastNode = theNode = NULL;
903
+
904
+ while (true)
905
+ {
906
+ /*==================*/
907
+ /* Get the next CE. */
908
+ /*==================*/
909
+
910
+ newNode = LHSPattern(theEnv,readSource,terminator,terminatorString,
911
+ error,false,NULL,NULL);
912
+
913
+ /*=======================================================*/
914
+ /* If an error occurred, release any LHS data structures */
915
+ /* previously allocated by this routine. */
916
+ /*=======================================================*/
917
+
918
+ if (*error)
919
+ {
920
+ ReturnLHSParseNodes(theEnv,theNode);
921
+ return NULL;
922
+ }
923
+
924
+ /*===============================================*/
925
+ /* A NULL value for the CE just parsed indicates */
926
+ /* that the terminator for the group of patterns */
927
+ /* was encountered (either a "=>" or a ")". */
928
+ /*===============================================*/
929
+
930
+ if (newNode == NULL)
931
+ {
932
+ PPBackup(theEnv);
933
+ PPBackup(theEnv);
934
+ if (terminator == RIGHT_PARENTHESIS_TOKEN)
935
+ { SavePPBuffer(theEnv,terminatorString); }
936
+ else
937
+ {
938
+ PPCRAndIndent(theEnv);
939
+ SavePPBuffer(theEnv,terminatorString);
940
+ }
941
+
942
+ return(theNode);
943
+ }
944
+
945
+ /*============================*/
946
+ /* Add the new CE to the list */
947
+ /* of CEs being grouped. */
948
+ /*============================*/
949
+
950
+ if (lastNode == NULL)
951
+ { theNode = newNode; }
952
+ else
953
+ { lastNode->bottom = newNode; }
954
+
955
+ lastNode = newNode;
956
+
957
+ /*======================================*/
958
+ /* Fix the pretty print representation. */
959
+ /*======================================*/
960
+
961
+ PPCRAndIndent(theEnv);
962
+ }
963
+ }
964
+
965
+ /**************************************************************/
966
+ /* TestPattern: Handles parsing of test conditional elements. */
967
+ /* */
968
+ /* <test-CE> ::= (test <function-call>) */
969
+ /**************************************************************/
970
+ static struct lhsParseNode *TestPattern(
971
+ Environment *theEnv,
972
+ const char *readSource,
973
+ bool *error)
974
+ {
975
+ struct lhsParseNode *theNode;
976
+ struct token theToken;
977
+ struct expr *theExpression;
978
+
979
+ /*================================================*/
980
+ /* Create the data specification for the test CE. */
981
+ /*================================================*/
982
+
983
+ SavePPBuffer(theEnv," ");
984
+ theNode = GetLHSParseNode(theEnv);
985
+ theNode->pnType = TEST_CE_NODE;
986
+ theExpression = Function0Parse(theEnv,readSource);
987
+ theNode->expression = ExpressionToLHSParseNodes(theEnv,theExpression);
988
+ ReturnExpression(theEnv,theExpression);
989
+
990
+ if (theNode->expression == NULL)
991
+ {
992
+ *error = true;
993
+ ReturnLHSParseNodes(theEnv,theNode);
994
+ return NULL;
995
+ }
996
+
997
+ /*=========================================================*/
998
+ /* Check for the closing right parenthesis of the test CE. */
999
+ /*=========================================================*/
1000
+
1001
+ GetToken(theEnv,readSource,&theToken);
1002
+ if (theToken.tknType != RIGHT_PARENTHESIS_TOKEN)
1003
+ {
1004
+ SyntaxErrorMessage(theEnv,"test conditional element");
1005
+ *error = true;
1006
+ ReturnLHSParseNodes(theEnv,theNode);
1007
+ return NULL;
1008
+ }
1009
+
1010
+ /*=====================*/
1011
+ /* Return the test CE. */
1012
+ /*=====================*/
1013
+
1014
+ return(theNode);
1015
+ }
1016
+
1017
+ /****************************************************************/
1018
+ /* AssignmentParse: Finishes the parsing of pattern conditional */
1019
+ /* elements that have been bound to a variable. */
1020
+ /* */
1021
+ /* <assigned-pattern-CE> ::= ?<variable-symbol> <- <pattern-CE> */
1022
+ /****************************************************************/
1023
+ static struct lhsParseNode *AssignmentParse(
1024
+ Environment *theEnv,
1025
+ const char *readSource,
1026
+ CLIPSLexeme *factAddress,
1027
+ bool *error)
1028
+ {
1029
+ struct lhsParseNode *theNode;
1030
+ struct token theToken;
1031
+
1032
+ /*=====================================================*/
1033
+ /* Patterns cannot be bound if they are with a not CE. */
1034
+ /*=====================================================*/
1035
+
1036
+ if (PatternData(theEnv)->WithinNotCE)
1037
+ {
1038
+ PrintErrorID(theEnv,"RULELHS",2,true);
1039
+ WriteString(theEnv,STDERR,"A pattern CE cannot be bound to a pattern-address within a not CE\n");
1040
+ *error = true;
1041
+ return NULL;
1042
+ }
1043
+
1044
+ /*===============================================*/
1045
+ /* Check for binder token, "<-", after variable. */
1046
+ /*===============================================*/
1047
+
1048
+ SavePPBuffer(theEnv," ");
1049
+
1050
+ GetToken(theEnv,readSource,&theToken);
1051
+
1052
+ if ((theToken.tknType == SYMBOL_TOKEN) ? (strcmp(theToken.lexemeValue->contents,"<-") != 0) :
1053
+ true)
1054
+ {
1055
+ SyntaxErrorMessage(theEnv,"binding patterns");
1056
+ *error = true;
1057
+ return NULL;
1058
+ }
1059
+
1060
+ SavePPBuffer(theEnv," ");
1061
+
1062
+ /*================================================*/
1063
+ /* Check for opening left parenthesis of pattern. */
1064
+ /*================================================*/
1065
+
1066
+ GetToken(theEnv,readSource,&theToken);
1067
+ if (theToken.tknType != LEFT_PARENTHESIS_TOKEN)
1068
+ {
1069
+ SyntaxErrorMessage(theEnv,"binding patterns");
1070
+ *error = true;
1071
+ return NULL;
1072
+ }
1073
+
1074
+ /*======================================================*/
1075
+ /* Parse the pattern and return the data specification. */
1076
+ /*======================================================*/
1077
+
1078
+ GetToken(theEnv,readSource,&theToken);
1079
+
1080
+ theNode = SimplePatternParse(theEnv,readSource,&theToken,error);
1081
+
1082
+ if (*error == true)
1083
+ {
1084
+ ReturnLHSParseNodes(theEnv,theNode);
1085
+ return NULL;
1086
+ }
1087
+
1088
+ /*=============================================*/
1089
+ /* Store the name of the variable to which the */
1090
+ /* pattern is bound and return the pattern. */
1091
+ /*=============================================*/
1092
+
1093
+ theNode->value = factAddress;
1094
+ return(theNode);
1095
+ }
1096
+
1097
+ /************************************************************/
1098
+ /* TagLHSLogicalNodes: Marks all *and*, *or*, and *not* CEs */
1099
+ /* contained within a logical CE as having the properties */
1100
+ /* associated with a logical CE. */
1101
+ /************************************************************/
1102
+ static void TagLHSLogicalNodes(
1103
+ struct lhsParseNode *nodePtr)
1104
+ {
1105
+ while (nodePtr != NULL)
1106
+ {
1107
+ nodePtr->logical = true;
1108
+ if ((nodePtr->pnType == AND_CE_NODE) ||
1109
+ (nodePtr->pnType == OR_CE_NODE) ||
1110
+ (nodePtr->pnType == NOT_CE_NODE))
1111
+ { TagLHSLogicalNodes(nodePtr->right); }
1112
+ nodePtr = nodePtr->bottom;
1113
+ }
1114
+ }
1115
+
1116
+ /***********************************************************/
1117
+ /* SimplePatternParse: Parses a simple pattern (an opening */
1118
+ /* parenthesis followed by one or more fields followed */
1119
+ /* by a closing parenthesis). */
1120
+ /* */
1121
+ /* <pattern-CE> ::= <ordered-pattern-CE> | */
1122
+ /* <template-pattern-CE> */
1123
+ /***********************************************************/
1124
+ static struct lhsParseNode *SimplePatternParse(
1125
+ Environment *theEnv,
1126
+ const char *readSource,
1127
+ struct token *theToken,
1128
+ bool *error)
1129
+ {
1130
+ struct lhsParseNode *theNode;
1131
+ struct patternParser *tempParser;
1132
+
1133
+ /*=================================================*/
1134
+ /* The first field of a pattern must be a symbol. */
1135
+ /* In addition, the symbols ":" and "=" can not */
1136
+ /* be used because they have special significance. */
1137
+ /*=================================================*/
1138
+
1139
+ if (theToken->tknType != SYMBOL_TOKEN)
1140
+ {
1141
+ SyntaxErrorMessage(theEnv,"the first field of a pattern");
1142
+ *error = true;
1143
+ return NULL;
1144
+ }
1145
+ else if ((strcmp(theToken->lexemeValue->contents,"=") == 0) ||
1146
+ (strcmp(theToken->lexemeValue->contents,":") == 0))
1147
+ {
1148
+ SyntaxErrorMessage(theEnv,"the field field of a pattern");
1149
+ *error = true;
1150
+ return NULL;
1151
+ }
1152
+
1153
+ /*===============================================*/
1154
+ /* Construct the topmost node of the pattern CE. */
1155
+ /*===============================================*/
1156
+
1157
+ theNode = GetLHSParseNode(theEnv);
1158
+ theNode->pnType = PATTERN_CE_NODE;
1159
+ theNode->negated = false;
1160
+ theNode->exists = false;
1161
+
1162
+ /*======================================================*/
1163
+ /* Search for a pattern parser that claims the pattern. */
1164
+ /*======================================================*/
1165
+
1166
+ for (tempParser = PatternData(theEnv)->ListOfPatternParsers;
1167
+ tempParser != NULL;
1168
+ tempParser = tempParser->next)
1169
+ {
1170
+ if ((*tempParser->recognizeFunction)(theToken->lexemeValue))
1171
+ {
1172
+ theNode->patternType = tempParser;
1173
+ theNode->right = (*tempParser->parseFunction)(theEnv,readSource,theToken);
1174
+ if (theNode->right == NULL)
1175
+ {
1176
+ *error = true;
1177
+ ReturnLHSParseNodes(theEnv,theNode);
1178
+ return NULL;
1179
+ }
1180
+
1181
+ PropagatePatternType(theNode,tempParser);
1182
+ return(theNode);
1183
+ }
1184
+ }
1185
+
1186
+ /*=================================*/
1187
+ /* If a pattern parser couldn't be */
1188
+ /* found, then signal an error. */
1189
+ /*=================================*/
1190
+
1191
+ *error = true;
1192
+ SyntaxErrorMessage(theEnv,"the field field of a pattern");
1193
+ ReturnLHSParseNodes(theEnv,theNode);
1194
+ return NULL;
1195
+ }
1196
+
1197
+ /**************************************************************/
1198
+ /* PropagatePatternType: Sets the selfPattern field for all */
1199
+ /* lhsParseNodes in a linked list of those data structures. */
1200
+ /**************************************************************/
1201
+ void PropagatePatternType(
1202
+ struct lhsParseNode *theLHS,
1203
+ struct patternParser *theParser)
1204
+ {
1205
+ while (theLHS != NULL)
1206
+ {
1207
+ theLHS->patternType = theParser;
1208
+ if (theLHS->right != NULL) PropagatePatternType(theLHS->right,theParser);
1209
+ if (theLHS->expression != NULL) PropagatePatternType(theLHS->expression,theParser);
1210
+ theLHS = theLHS->bottom;
1211
+ }
1212
+ }
1213
+
1214
+ #endif /* (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT */
1215
+
1216
+