1 /*******************************************************/
2 /* "C" Language Integrated Production System */
3 /* */
4 /* CLIPS Version 6.30 08/16/14 */
5 /* */
6 /* PARSING FUNCTIONS MODULE */
7 /*******************************************************/
8
9 /*************************************************************/
10 /* Purpose: Contains the code for several parsing related */
11 /* functions including... */
12 /* */
13 /* Principal Programmer(s): */
14 /* Gary D. Riley */
15 /* */
16 /* Contributing Programmer(s): */
17 /* */
18 /* Revision History: */
19 /* */
20 /* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
21 /* */
22 /* 6.24: Corrected code to remove run-time program */
23 /* compiler warnings. */
24 /* */
25 /* 6.30: Changed integer type/precision. */
26 /* */
27 /* Removed conditional code for unsupported */
28 /* compilers/operating systems (IBM_MCW, */
29 /* MAC_MCW, and IBM_TBC). */
30 /* */
31 /* Added const qualifiers to remove C++ */
32 /* deprecation warnings. */
33 /* */
34 /* Fixed function declaration issue when */
35 /* BLOAD_ONLY compiler flag is set to 1. */
36 /* */
37 /*************************************************************/
38
39 #define _PARSEFUN_SOURCE_
40
41 #include "setup.h"
42
43 #include <string.h>
44
45 #include "argacces.h"
46 #include "cstrcpsr.h"
47 #include "envrnmnt.h"
48 #include "exprnpsr.h"
49 #include "extnfunc.h"
50 #include "memalloc.h"
51 #include "multifld.h"
52 #include "prcdrpsr.h"
53 #include "router.h"
54 #include "strngrtr.h"
55 #include "utility.h"
56
57 #include "parsefun.h"
58
59 #define PARSEFUN_DATA 11
60
61 struct parseFunctionData
62 {
63 char *ErrorString;
64 size_t ErrorCurrentPosition;
65 size_t ErrorMaximumPosition;
66 char *WarningString;
67 size_t WarningCurrentPosition;
68 size_t WarningMaximumPosition;
69 };
70
71 #define ParseFunctionData(theEnv) ((struct parseFunctionData *) GetEnvironmentData(theEnv,PARSEFUN_DATA))
72
73 /***************************************/
74 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
75 /***************************************/
76
77 #if (! RUN_TIME) && (! BLOAD_ONLY)
78 static int FindErrorCapture(void *,const char *);
79 static int PrintErrorCapture(void *,const char *,const char *);
80 static void DeactivateErrorCapture(void *);
81 static void SetErrorCaptureValues(void *,DATA_OBJECT_PTR);
82 #endif
83
84 /*****************************************/
85 /* ParseFunctionDefinitions: Initializes */
86 /* the parsing related functions. */
87 /*****************************************/
ParseFunctionDefinitions(void * theEnv)88 globle void ParseFunctionDefinitions(
89 void *theEnv)
90 {
91 AllocateEnvironmentData(theEnv,PARSEFUN_DATA,sizeof(struct parseFunctionData),NULL);
92
93 #if ! RUN_TIME
94 EnvDefineFunction2(theEnv,"check-syntax",'u',PTIEF CheckSyntaxFunction,"CheckSyntaxFunction","11s");
95 #endif
96 }
97
98 #if (! RUN_TIME) && (! BLOAD_ONLY)
99 /*******************************************/
100 /* CheckSyntaxFunction: H/L access routine */
101 /* for the check-syntax function. */
102 /*******************************************/
CheckSyntaxFunction(void * theEnv,DATA_OBJECT * returnValue)103 globle void CheckSyntaxFunction(
104 void *theEnv,
105 DATA_OBJECT *returnValue)
106 {
107 DATA_OBJECT theArg;
108
109 /*===============================*/
110 /* Set up a default return value */
111 /* (TRUE for problems found). */
112 /*===============================*/
113
114 SetpType(returnValue,SYMBOL);
115 SetpValue(returnValue,EnvTrueSymbol(theEnv));
116
117 /*=====================================================*/
118 /* Function check-syntax expects exactly one argument. */
119 /*=====================================================*/
120
121 if (EnvArgCountCheck(theEnv,"check-syntax",EXACTLY,1) == -1) return;
122
123 /*========================================*/
124 /* The argument should be of type STRING. */
125 /*========================================*/
126
127 if (EnvArgTypeCheck(theEnv,"check-syntax",1,STRING,&theArg) == FALSE)
128 { return; }
129
130 /*===================*/
131 /* Check the syntax. */
132 /*===================*/
133
134 CheckSyntax(theEnv,DOToString(theArg),returnValue);
135 }
136
137 /*********************************/
138 /* CheckSyntax: C access routine */
139 /* for the build function. */
140 /*********************************/
CheckSyntax(void * theEnv,const char * theString,DATA_OBJECT_PTR returnValue)141 globle int CheckSyntax(
142 void *theEnv,
143 const char *theString,
144 DATA_OBJECT_PTR returnValue)
145 {
146 const char *name;
147 struct token theToken;
148 struct expr *top;
149 short rv;
150
151 /*==============================*/
152 /* Set the default return value */
153 /* (TRUE for problems found). */
154 /*==============================*/
155
156 SetpType(returnValue,SYMBOL);
157 SetpValue(returnValue,EnvTrueSymbol(theEnv));
158
159 /*===========================================*/
160 /* Create a string source router so that the */
161 /* string can be used as an input source. */
162 /*===========================================*/
163
164 if (OpenStringSource(theEnv,"check-syntax",theString,0) == 0)
165 { return(TRUE); }
166
167 /*=================================*/
168 /* Only expressions and constructs */
169 /* can have their syntax checked. */
170 /*=================================*/
171
172 GetToken(theEnv,"check-syntax",&theToken);
173
174 if (theToken.type != LPAREN)
175 {
176 CloseStringSource(theEnv,"check-syntax");
177 SetpValue(returnValue,EnvAddSymbol(theEnv,"MISSING-LEFT-PARENTHESIS"));
178 return(TRUE);
179 }
180
181 /*========================================*/
182 /* The next token should be the construct */
183 /* type or function name. */
184 /*========================================*/
185
186 GetToken(theEnv,"check-syntax",&theToken);
187 if (theToken.type != SYMBOL)
188 {
189 CloseStringSource(theEnv,"check-syntax");
190 SetpValue(returnValue,EnvAddSymbol(theEnv,"EXPECTED-SYMBOL-AFTER-LEFT-PARENTHESIS"));
191 return(TRUE);
192 }
193
194 name = ValueToString(theToken.value);
195
196 /*==============================================*/
197 /* Set up a router to capture the error output. */
198 /*==============================================*/
199
200 EnvAddRouter(theEnv,"error-capture",40,
201 FindErrorCapture, PrintErrorCapture,
202 NULL, NULL, NULL);
203
204 /*================================*/
205 /* Determine if it's a construct. */
206 /*================================*/
207
208 if (FindConstruct(theEnv,name))
209 {
210 ConstructData(theEnv)->CheckSyntaxMode = TRUE;
211 rv = (short) ParseConstruct(theEnv,name,"check-syntax");
212 GetToken(theEnv,"check-syntax",&theToken);
213 ConstructData(theEnv)->CheckSyntaxMode = FALSE;
214
215 if (rv)
216 {
217 EnvPrintRouter(theEnv,WERROR,"\nERROR:\n");
218 PrintInChunks(theEnv,WERROR,GetPPBuffer(theEnv));
219 EnvPrintRouter(theEnv,WERROR,"\n");
220 }
221
222 DestroyPPBuffer(theEnv);
223
224 CloseStringSource(theEnv,"check-syntax");
225
226 if ((rv != FALSE) || (ParseFunctionData(theEnv)->WarningString != NULL))
227 {
228 SetErrorCaptureValues(theEnv,returnValue);
229 DeactivateErrorCapture(theEnv);
230 return(TRUE);
231 }
232
233 if (theToken.type != STOP)
234 {
235 SetpValue(returnValue,EnvAddSymbol(theEnv,"EXTRANEOUS-INPUT-AFTER-LAST-PARENTHESIS"));
236 DeactivateErrorCapture(theEnv);
237 return(TRUE);
238 }
239
240 SetpType(returnValue,SYMBOL);
241 SetpValue(returnValue,EnvFalseSymbol(theEnv));
242 DeactivateErrorCapture(theEnv);
243 return(FALSE);
244 }
245
246 /*=======================*/
247 /* Parse the expression. */
248 /*=======================*/
249
250 top = Function2Parse(theEnv,"check-syntax",name);
251 GetToken(theEnv,"check-syntax",&theToken);
252 ClearParsedBindNames(theEnv);
253 CloseStringSource(theEnv,"check-syntax");
254
255 if (top == NULL)
256 {
257 SetErrorCaptureValues(theEnv,returnValue);
258 DeactivateErrorCapture(theEnv);
259 return(TRUE);
260 }
261
262 if (theToken.type != STOP)
263 {
264 SetpValue(returnValue,EnvAddSymbol(theEnv,"EXTRANEOUS-INPUT-AFTER-LAST-PARENTHESIS"));
265 DeactivateErrorCapture(theEnv);
266 ReturnExpression(theEnv,top);
267 return(TRUE);
268 }
269
270 DeactivateErrorCapture(theEnv);
271
272 ReturnExpression(theEnv,top);
273 SetpType(returnValue,SYMBOL);
274 SetpValue(returnValue,EnvFalseSymbol(theEnv));
275 return(FALSE);
276 }
277
278 /**************************************************/
279 /* DeactivateErrorCapture: Deactivates the error */
280 /* capture router and the strings used to store */
281 /* the captured information. */
282 /**************************************************/
DeactivateErrorCapture(void * theEnv)283 static void DeactivateErrorCapture(
284 void *theEnv)
285 {
286 if (ParseFunctionData(theEnv)->ErrorString != NULL)
287 {
288 rm(theEnv,ParseFunctionData(theEnv)->ErrorString,ParseFunctionData(theEnv)->ErrorMaximumPosition);
289 ParseFunctionData(theEnv)->ErrorString = NULL;
290 }
291
292 if (ParseFunctionData(theEnv)->WarningString != NULL)
293 {
294 rm(theEnv,ParseFunctionData(theEnv)->WarningString,ParseFunctionData(theEnv)->WarningMaximumPosition);
295 ParseFunctionData(theEnv)->WarningString = NULL;
296 }
297
298 ParseFunctionData(theEnv)->ErrorCurrentPosition = 0;
299 ParseFunctionData(theEnv)->ErrorMaximumPosition = 0;
300 ParseFunctionData(theEnv)->WarningCurrentPosition = 0;
301 ParseFunctionData(theEnv)->WarningMaximumPosition = 0;
302
303 EnvDeleteRouter(theEnv,"error-capture");
304 }
305
306 /******************************************************************/
307 /* SetErrorCaptureValues: Stores the error/warnings captured when */
308 /* parsing an expression or construct into a multifield value. */
309 /* The first field contains the output sent to the WERROR */
310 /* logical name and the second field contains the output sent */
311 /* to the WWARNING logical name. FALSE is stored in either */
312 /* position if no output was sent to those logical names. */
313 /******************************************************************/
SetErrorCaptureValues(void * theEnv,DATA_OBJECT_PTR returnValue)314 static void SetErrorCaptureValues(
315 void *theEnv,
316 DATA_OBJECT_PTR returnValue)
317 {
318 struct multifield *theMultifield;
319
320 theMultifield = (struct multifield *) EnvCreateMultifield(theEnv,2L);
321
322 if (ParseFunctionData(theEnv)->ErrorString != NULL)
323 {
324 SetMFType(theMultifield,1,STRING);
325 SetMFValue(theMultifield,1,EnvAddSymbol(theEnv,ParseFunctionData(theEnv)->ErrorString));
326 }
327 else
328 {
329 SetMFType(theMultifield,1,SYMBOL);
330 SetMFValue(theMultifield,1,EnvFalseSymbol(theEnv));
331 }
332
333 if (ParseFunctionData(theEnv)->WarningString != NULL)
334 {
335 SetMFType(theMultifield,2,STRING);
336 SetMFValue(theMultifield,2,EnvAddSymbol(theEnv,ParseFunctionData(theEnv)->WarningString));
337 }
338 else
339 {
340 SetMFType(theMultifield,2,SYMBOL);
341 SetMFValue(theMultifield,2,EnvFalseSymbol(theEnv));
342 }
343
344 SetpType(returnValue,MULTIFIELD);
345 SetpDOBegin(returnValue,1);
346 SetpDOEnd(returnValue,2);
347 SetpValue(returnValue,(void *) theMultifield);
348 }
349
350 /**********************************/
351 /* FindErrorCapture: Find routine */
352 /* for the check-syntax router. */
353 /**********************************/
FindErrorCapture(void * theEnv,const char * logicalName)354 static int FindErrorCapture(
355 void *theEnv,
356 const char *logicalName)
357 {
358 #if MAC_XCD
359 #pragma unused(theEnv)
360 #endif
361
362 if ((strcmp(logicalName,WERROR) == 0) ||
363 (strcmp(logicalName,WWARNING) == 0))
364 { return(TRUE); }
365
366 return(FALSE);
367 }
368
369 /************************************/
370 /* PrintErrorCapture: Print routine */
371 /* for the check-syntax router. */
372 /************************************/
PrintErrorCapture(void * theEnv,const char * logicalName,const char * str)373 static int PrintErrorCapture(
374 void *theEnv,
375 const char *logicalName,
376 const char *str)
377 {
378 if (strcmp(logicalName,WERROR) == 0)
379 {
380 ParseFunctionData(theEnv)->ErrorString = AppendToString(theEnv,str,ParseFunctionData(theEnv)->ErrorString,
381 &ParseFunctionData(theEnv)->ErrorCurrentPosition,
382 &ParseFunctionData(theEnv)->ErrorMaximumPosition);
383 }
384 else if (strcmp(logicalName,WWARNING) == 0)
385 {
386 ParseFunctionData(theEnv)->WarningString = AppendToString(theEnv,str,ParseFunctionData(theEnv)->WarningString,
387 &ParseFunctionData(theEnv)->WarningCurrentPosition,
388 &ParseFunctionData(theEnv)->WarningMaximumPosition);
389 }
390
391 return(1);
392 }
393
394 #else
395 /****************************************************/
396 /* CheckSyntaxFunction: This is the non-functional */
397 /* stub provided for use with a run-time version. */
398 /****************************************************/
CheckSyntaxFunction(void * theEnv,DATA_OBJECT * returnValue)399 globle void CheckSyntaxFunction(
400 void *theEnv,
401 DATA_OBJECT *returnValue)
402 {
403 PrintErrorID(theEnv,"PARSEFUN",1,FALSE);
404 EnvPrintRouter(theEnv,WERROR,"Function check-syntax does not work in run time modules.\n");
405 SetpType(returnValue,SYMBOL);
406 SetpValue(returnValue,EnvTrueSymbol(theEnv));
407 }
408
409 /************************************************/
410 /* CheckSyntax: This is the non-functional stub */
411 /* provided for use with a run-time version. */
412 /************************************************/
CheckSyntax(void * theEnv,const char * theString,DATA_OBJECT_PTR returnValue)413 globle int CheckSyntax(
414 void *theEnv,
415 const char *theString,
416 DATA_OBJECT_PTR returnValue)
417 {
418 PrintErrorID(theEnv,"PARSEFUN",1,FALSE);
419 EnvPrintRouter(theEnv,WERROR,"Function check-syntax does not work in run time modules.\n");
420 SetpType(returnValue,SYMBOL);
421 SetpValue(returnValue,EnvTrueSymbol(theEnv));
422 return(TRUE);
423 }
424
425 #endif /* (! RUN_TIME) && (! BLOAD_ONLY) */
426
427
428