1 /* CCL find (to rpn conversion)
5 * Revision 1.13 1995/04/17 09:31:42 adam
6 * Improved handling of qualifiers. Aliases or reserved words.
8 * Revision 1.12 1995/03/20 15:27:43 adam
11 * Revision 1.11 1995/02/23 08:31:59 adam
14 * Revision 1.9 1995/02/16 13:20:06 adam
17 * Revision 1.8 1995/02/14 19:59:42 adam
18 * Removed a syntax error.
20 * Revision 1.7 1995/02/14 19:55:10 adam
21 * Header files ccl.h/cclp.h are gone! They have been merged an
22 * moved to ../include/ccl.h.
23 * Node kind(s) in ccl_rpn_node have changed names.
25 * Revision 1.6 1995/02/14 16:20:55 adam
26 * Qualifiers are read from a file now.
28 * Revision 1.5 1995/02/14 14:12:41 adam
29 * Ranges for ordered qualfiers implemented (e.g. pd=1980-1990).
31 * Revision 1.4 1995/02/14 13:16:29 adam
32 * Left and/or right truncation implemented.
34 * Revision 1.3 1995/02/14 10:25:56 adam
35 * The constructions 'qualifier rel term ...' implemented.
37 * Revision 1.2 1995/02/13 15:15:07 adam
38 * Added handling of qualifiers. Not finished yet.
40 * Revision 1.1 1995/02/13 12:35:20 adam
41 * First version of CCL. Qualifiers aren't handled yet.
52 /* current lookahead token */
53 static struct ccl_token *look_token;
55 /* holds error no if error occur */
59 static CCL_bibset bibset;
61 /* returns type of current lookahead */
62 #define KIND (look_token->kind)
64 /* move one token forward */
65 #define ADVANCE look_token = look_token->next
68 * qual_val_range: search for attribute of type with range
70 * type: Type of attribute to search for
71 * vmin: Lower bound of value to search for
72 * vmax: Upper bound of value to search for
73 * return: Return pointer to integer of attribute value found; NULL
76 static int *qual_val_range (struct ccl_rpn_attr **qa, int type,
80 struct ccl_rpn_attr *q;
84 for (i = 0; (q=qa[i]); i++)
87 if (q->type == type && q->value >= vmin && q->value <= vmax)
95 * qual_val_type: test for existance of attribute type/value pair.
97 * type: Type of attribute to search for
98 * value: Value of attribute to seach for
99 * return: 1 if found; 0 otherwise.
101 static int qual_val_type (struct ccl_rpn_attr **qa, int type, int value)
104 struct ccl_rpn_attr *q;
108 for (i = 0; (q=qa[i]); i++)
111 if (q->type == type && q->value == value)
119 * strxcat: concatenate strings.
120 * n: Null-terminated Destination string
121 * src: Source string to be appended (not null-terminated)
122 * len: Length of source string.
124 static void strxcat (char *n, const char *src, int len)
134 * copy_token_name: Return copy of CCL token name
135 * tp: Pointer to token info.
136 * return: malloc(3) allocated copy of token name.
138 static char *copy_token_name (struct ccl_token *tp)
140 char *str = malloc (tp->len + 1);
142 memcpy (str, tp->name, tp->len);
148 * mk_node: Create RPN node.
149 * kind: Type of node.
150 * return: pointer to allocated node.
152 static struct ccl_rpn_node *mk_node (enum rpn_node_kind kind)
154 struct ccl_rpn_node *p;
155 p = malloc (sizeof(*p));
162 * ccl_rpn_delete: Delete RPN tree.
163 * rpn: Pointer to tree.
165 void ccl_rpn_delete (struct ccl_rpn_node *rpn)
167 struct ccl_rpn_attr *attr, *attr1;
175 ccl_rpn_delete (rpn->u.p[0]);
176 ccl_rpn_delete (rpn->u.p[1]);
179 free (rpn->u.t.term);
180 for (attr = rpn->u.t.attr_list; attr; attr = attr1)
187 free (rpn->u.setname);
190 ccl_rpn_delete (rpn->u.p[0]);
191 ccl_rpn_delete (rpn->u.p[1]);
197 static struct ccl_rpn_node *find_spec (struct ccl_rpn_attr **qa);
198 static struct ccl_rpn_node *search_terms (struct ccl_rpn_attr **qa);
201 * add_attr: Add attribute (type/value) to RPN term node.
202 * p: RPN node of type term.
203 * type: Type of attribute
204 * value: Value of attribute
206 static void add_attr (struct ccl_rpn_node *p, int type, int value)
208 struct ccl_rpn_attr *n;
210 n = malloc (sizeof(*n));
214 n->next = p->u.t.attr_list;
215 p->u.t.attr_list = n;
219 * search_term: Parse CCL search term.
220 * qa: Qualifier attributes already applied.
221 * return: pointer to node(s); NULL on error.
223 static struct ccl_rpn_node *search_term (struct ccl_rpn_attr **qa)
225 struct ccl_rpn_node *p;
226 struct ccl_token *lookahead = look_token;
232 int relation_value = -1;
233 int position_value = -1;
234 int structure_value = -1;
235 int truncation_value = -1;
236 int completeness_value = -1;
238 if (KIND != CCL_TOK_TERM)
240 ccl_error = CCL_ERR_TERM_EXPECTED;
243 /* create the term node, but wait a moment before adding the term */
244 p = mk_node (CCL_RPN_TERM);
245 p->u.t.attr_list = NULL;
250 /* no qualifier(s) applied. Use 'term' if it is defined */
252 qa = malloc (2*sizeof(*qa));
254 qa[0] = ccl_qual_search (bibset, "term", 4);
258 /* go through all attributes and add them to the attribute list */
259 for (i=0; qa && qa[i]; i++)
261 struct ccl_rpn_attr *attr;
263 for (attr = qa[i]; attr; attr = attr->next)
265 { /* deal only with REAL attributes (positive) */
269 if (relation_value != -1)
271 relation_value = attr->value;
274 if (position_value != -1)
276 position_value = attr->value;
279 if (structure_value != -1)
281 structure_value = attr->value;
284 if (truncation_value != -1)
286 truncation_value = attr->value;
289 if (completeness_value != -1)
291 completeness_value = attr->value;
294 add_attr (p, attr->type, attr->value);
297 /* go through each TERM token. If no truncation attribute is yet
298 met, then look for left/right truncation markers (?) and
299 set left_trunc/right_trunc/mid_trunc accordingly */
300 for (no = 0; lookahead->kind == CCL_TOK_TERM; no++)
302 for (i = 0; i<lookahead->len; i++)
303 if (truncation_value == -1 && lookahead->name[i] == '?')
305 if (no == 0 && i == 0 && lookahead->len >= 1)
307 else if (lookahead->next->kind != CCL_TOK_TERM &&
308 i == lookahead->len-1 && i >= 1)
313 len += 1+lookahead->len;
314 lookahead = lookahead->next;
316 /* len now holds the number of characters in the RPN term */
317 /* no holds the number of CCL tokens (1 or more) */
319 if (structure_value == -1 &&
320 qual_val_type (qa, CCL_BIB1_STR, CCL_BIB1_STR_WP))
321 { /* no structure attribute met. Apply either structure attribute
322 WORD or PHRASE depending on number of CCL tokens */
324 add_attr (p, CCL_BIB1_STR, 2);
326 add_attr (p, CCL_BIB1_STR, 1);
329 /* make the RPN token */
330 p->u.t.term = malloc (len);
331 assert (p->u.t.term);
332 p->u.t.term[0] = '\0';
333 for (i = 0; i<no; i++)
335 const char *src_str = look_token->name;
336 int src_len = look_token->len;
338 if (i == 0 && left_trunc)
343 else if (i == no-1 && right_trunc)
346 strcat (p->u.t.term, " ");
347 strxcat (p->u.t.term, src_str, src_len);
350 if (left_trunc && right_trunc)
352 if (!qual_val_type (qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_BOTH))
354 ccl_error = CCL_ERR_TRUNC_NOT_BOTH;
359 add_attr (p, CCL_BIB1_TRU, 3);
361 else if (right_trunc)
363 if (!qual_val_type (qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_RIGHT))
365 ccl_error = CCL_ERR_TRUNC_NOT_RIGHT;
370 add_attr (p, CCL_BIB1_TRU, 1);
374 if (!qual_val_type (qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_LEFT))
376 ccl_error = CCL_ERR_TRUNC_NOT_LEFT;
381 add_attr (p, CCL_BIB1_TRU, 2);
385 if (qual_val_type (qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_NONE))
386 add_attr (p, CCL_BIB1_TRU, 100);
392 * qualifiers: Parse CCL qualifiers and search terms.
393 * la: Token pointer to RELATION token.
394 * qa: Qualifier attributes already applied.
395 * return: pointer to node(s); NULL on error.
397 static struct ccl_rpn_node *qualifiers (struct ccl_token *la,
398 struct ccl_rpn_attr **qa)
400 struct ccl_token *lookahead = look_token;
401 struct ccl_rpn_attr **ap;
407 ccl_error = CCL_ERR_DOUBLE_QUAL;
411 for (lookahead = look_token; lookahead != la; lookahead=lookahead->next)
414 for (i=0; qa[i]; i++)
416 ap = malloc ((no+1) * sizeof(*ap));
418 for (i = 0; look_token != la; i++)
420 ap[i] = ccl_qual_search (bibset, look_token->name, look_token->len);
423 ccl_error = CCL_ERR_UNKNOWN_QUAL;
428 if (KIND == CCL_TOK_COMMA)
435 if (!qual_val_type (ap, CCL_BIB1_REL, CCL_BIB1_REL_ORDER))
437 /* unordered relation */
438 struct ccl_rpn_node *p;
439 if (KIND != CCL_TOK_EQ)
441 ccl_error = CCL_ERR_EQ_EXPECTED;
446 if (KIND == CCL_TOK_LP)
449 if (!(p = find_spec (ap)))
454 if (KIND != CCL_TOK_RP)
456 ccl_error = CCL_ERR_RP_EXPECTED;
464 p = search_terms (ap);
469 if (look_token->len == 1)
471 if (look_token->name[0] == '<')
473 else if (look_token->name[0] == '=')
475 else if (look_token->name[0] == '>')
478 else if (look_token->len == 2)
480 if (!memcmp (look_token->name, "<=", 2))
482 else if (!memcmp (look_token->name, ">=", 2))
484 else if (!memcmp (look_token->name, "<>", 2))
488 ccl_error = CCL_ERR_BAD_RELATION;
491 struct ccl_rpn_node *p;
493 ADVANCE; /* skip relation */
494 if (KIND == CCL_TOK_TERM && look_token->next->kind == CCL_TOK_MINUS)
496 struct ccl_rpn_node *p1;
497 if (!(p1 = search_term (ap)))
502 ADVANCE; /* skip '-' */
503 if (KIND == CCL_TOK_TERM) /* = term - term ? */
505 struct ccl_rpn_node *p2;
507 if (!(p2 = search_term (ap)))
513 p = mk_node (CCL_RPN_AND);
515 add_attr (p1, CCL_BIB1_REL, 4);
517 add_attr (p2, CCL_BIB1_REL, 2);
523 add_attr (p1, CCL_BIB1_REL, 4);
528 else if (KIND == CCL_TOK_MINUS) /* = - term ? */
531 if (!(p = search_term (ap)))
536 add_attr (p, CCL_BIB1_REL, 2);
540 else if (KIND == CCL_TOK_LP)
543 if (!(p = find_spec (ap)))
548 if (KIND != CCL_TOK_RP)
550 ccl_error = CCL_ERR_RP_EXPECTED;
561 if (!(p = search_terms (ap)))
566 add_attr (p, CCL_BIB1_REL, rel);
570 ccl_error = CCL_ERR_TERM_EXPECTED;
577 * search_terms: Parse CCL search terms - including proximity.
578 * qa: Qualifier attributes already applied.
579 * return: pointer to node(s); NULL on error.
581 static struct ccl_rpn_node *search_terms (struct ccl_rpn_attr **qa)
583 struct ccl_rpn_node *p1, *p2, *pn;
584 p1 = search_term (qa);
589 if (KIND == CCL_TOK_PROX)
592 p2 = search_term (qa);
598 pn = mk_node (CCL_RPN_PROX);
603 else if (KIND == CCL_TOK_TERM)
605 p2 = search_term (qa);
611 pn = mk_node (CCL_RPN_PROX);
623 * search_elements: Parse CCL search elements
624 * qa: Qualifier attributes already applied.
625 * return: pointer to node(s); NULL on error.
627 static struct ccl_rpn_node *search_elements (struct ccl_rpn_attr **qa)
629 struct ccl_rpn_node *p1;
630 struct ccl_token *lookahead;
631 if (KIND == CCL_TOK_LP)
637 if (KIND != CCL_TOK_RP)
639 ccl_error = CCL_ERR_RP_EXPECTED;
646 else if (KIND == CCL_TOK_SET)
649 if (KIND == CCL_TOK_EQ)
651 if (KIND != CCL_TOK_TERM)
653 ccl_error = CCL_ERR_SETNAME_EXPECTED;
656 p1 = mk_node (CCL_RPN_SET);
657 p1->u.setname = copy_token_name (look_token);
661 lookahead = look_token;
663 while (lookahead->kind==CCL_TOK_TERM || lookahead->kind==CCL_TOK_COMMA)
664 lookahead = lookahead->next;
665 if (lookahead->kind == CCL_TOK_REL || lookahead->kind == CCL_TOK_EQ)
666 return qualifiers (lookahead, qa);
667 return search_terms (qa);
671 * find_spec: Parse CCL find specification
672 * qa: Qualifier attributes already applied.
673 * return: pointer to node(s); NULL on error.
675 static struct ccl_rpn_node *find_spec (struct ccl_rpn_attr **qa)
677 struct ccl_rpn_node *p1, *p2, *pn;
678 if (!(p1 = search_elements (qa)))
686 p2 = search_elements (qa);
692 pn = mk_node (CCL_RPN_AND);
699 p2 = search_elements (qa);
705 pn = mk_node (CCL_RPN_OR);
712 p2 = search_elements (qa);
718 pn = mk_node (CCL_RPN_NOT);
730 * ccl_find: Parse CCL find - token representation
731 * abibset: Bibset to be used for the parsing
732 * list: List of tokens
733 * error: Pointer to integer. Holds error no. on completion.
734 * pos: Pointer to char position. Holds approximate error position.
735 * return: RPN tree on successful completion; NULL otherwise.
737 struct ccl_rpn_node *ccl_find (CCL_bibset abibset, struct ccl_token *list,
738 int *error, const char **pos)
740 struct ccl_rpn_node *p;
744 p = find_spec (NULL);
745 if (p && KIND != CCL_TOK_EOL)
747 if (KIND == CCL_TOK_RP)
748 ccl_error = CCL_ERR_BAD_RP;
750 ccl_error = CCL_ERR_OP_EXPECTED;
754 *pos = look_token->name;
763 * ccl_find_str: Parse CCL find - string representation
764 * bibset: Bibset to be used for the parsing
765 * str: String to be parsed
766 * error: Pointer to integer. Holds error no. on completion.
767 * pos: Pointer to char position. Holds approximate error position.
768 * return: RPN tree on successful completion; NULL otherwise.
770 struct ccl_rpn_node *ccl_find_str (CCL_bibset bibset, const char *str,
771 int *error, int *pos)
773 struct ccl_token *list;
774 struct ccl_rpn_node *rpn;
775 const char *char_pos;
777 list = ccl_tokenize (str);
778 rpn = ccl_find (bibset, list, error, &char_pos);
780 *pos = char_pos - str;