X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fcclfind.c;h=6db1d84875c9e54051b509b0ce7cde8609fe79ab;hb=5c3d2d2ab097e4bb59ba5718a396b020a2d302c0;hp=82dd726bf828443f142b191b1dd39af535ac68b5;hpb=5c3254b421ce3cc5f3d8c4f294a48f233a6cf3f7;p=yaz-moved-to-github.git diff --git a/src/cclfind.c b/src/cclfind.c index 82dd726..6db1d84 100644 --- a/src/cclfind.c +++ b/src/cclfind.c @@ -41,10 +41,22 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. * */ + +/** + * \file cclfind.c + * \brief Implements parsing of a CCL FIND query. + * + * This source file implements parsing of a CCL Query (ISO8777). + * The parser uses predictive parsing, but it does several tokens + * of lookahead in the handling of relational operations.. So + * it's not really pure. + */ + + /* CCL find (to rpn conversion) * Europagate, 1995 * - * $Id: cclfind.c,v 1.3 2004-08-11 20:13:36 adam Exp $ + * $Id: cclfind.c,v 1.6 2004-10-15 00:18:59 adam Exp $ * * Old Europagate log: * @@ -109,7 +121,7 @@ /* move one token forward */ #define ADVANCE cclp->look_token = cclp->look_token->next -/* +/** * qual_val_type: test for existance of attribute type/value pair. * qa: Attribute array * type: Type of attribute to search for @@ -139,7 +151,7 @@ static int qual_val_type (struct ccl_rpn_attr **qa, int type, int value, return 0; } -/* +/** * strxcat: concatenate strings. * n: Null-terminated Destination string * src: Source string to be appended (not null-terminated) @@ -154,7 +166,7 @@ static void strxcat (char *n, const char *src, int len) *n = '\0'; } -/* +/** * copy_token_name: Return copy of CCL token name * tp: Pointer to token info. * return: malloc(3) allocated copy of token name. @@ -168,7 +180,7 @@ static char *copy_token_name (struct ccl_token *tp) return str; } -/* +/** * mk_node: Create RPN node. * kind: Type of node. * return: pointer to allocated node. @@ -182,7 +194,7 @@ static struct ccl_rpn_node *mk_node (int kind) return p; } -/* +/** * ccl_rpn_delete: Delete RPN tree. * rpn: Pointer to tree. */ @@ -217,6 +229,7 @@ void ccl_rpn_delete (struct ccl_rpn_node *rpn) case CCL_RPN_PROX: ccl_rpn_delete (rpn->u.p[0]); ccl_rpn_delete (rpn->u.p[1]); + ccl_rpn_delete (rpn->u.p[2]); break; } xfree (rpn); @@ -259,7 +272,7 @@ static struct ccl_rpn_attr *add_attr_node (struct ccl_rpn_node *p, return n; } -/* +/** * add_attr_numeric: Add attribute (type/value) to RPN term node. * p: RPN node of type term. * type: Type of attribute @@ -287,7 +300,7 @@ static void add_attr_string (struct ccl_rpn_node *p, const char *set, } -/* +/** * search_term: Parse CCL search term. * cclp: CCL Parser * qa: Qualifier attributes already applied. @@ -535,43 +548,13 @@ static struct ccl_rpn_node *search_term (CCL_parser cclp, return search_term_x(cclp, qa, list, 0); } -static struct ccl_rpn_node *qualifiers2 (CCL_parser cclp, - struct ccl_rpn_attr **ap) +static +struct ccl_rpn_node *qualifiers_order (CCL_parser cclp, + struct ccl_rpn_attr **ap, char *attset) { - char *attset; - int rel; + int rel = 0; + struct ccl_rpn_node *p; - if (!qual_val_type(ap, CCL_BIB1_REL, CCL_BIB1_REL_ORDER, &attset)) - { - /* unordered relation */ - struct ccl_rpn_node *p; - if (KIND != CCL_TOK_EQ) - { - cclp->error_code = CCL_ERR_EQ_EXPECTED; - return NULL; - } - ADVANCE; - if (KIND == CCL_TOK_LP) - { - ADVANCE; - if (!(p = find_spec (cclp, ap))) - { - return NULL; - } - if (KIND != CCL_TOK_RP) - { - cclp->error_code = CCL_ERR_RP_EXPECTED; - ccl_rpn_delete (p); - return NULL; - } - ADVANCE; - } - else - p = search_terms (cclp, ap); - return p; - } - /* ordered relation ... */ - rel = 0; if (cclp->look_token->len == 1) { if (cclp->look_token->name[0] == '<') @@ -591,78 +574,185 @@ static struct ccl_rpn_node *qualifiers2 (CCL_parser cclp, rel = 6; } if (!rel) + { cclp->error_code = CCL_ERR_BAD_RELATION; - else + return NULL; + } + ADVANCE; /* skip relation */ + if (rel == 3 && + qual_val_type(ap, CCL_BIB1_REL, CCL_BIB1_REL_PORDER, 0)) { - struct ccl_rpn_node *p; + /* allow - inside term and treat it as range _always_ */ + /* relation is =. Extract "embedded" - to separate terms */ + if (KIND == CCL_TOK_TERM) + { + size_t i; + for (i = 0; ilook_token->len; i++) + { + if (cclp->look_token->name[i] == '-') + break; + } + + if (cclp->look_token->len > 1 && i == 0) + { /* -xx*/ + struct ccl_token *ntoken = ccl_token_add (cclp->look_token); + + ntoken->kind = CCL_TOK_TERM; + ntoken->name = cclp->look_token->name + 1; + ntoken->len = cclp->look_token->len - 1; + + cclp->look_token->len = 1; + cclp->look_token->name = "-"; + } + else if (cclp->look_token->len > 1 && i == cclp->look_token->len-1) + { /* xx- */ + struct ccl_token *ntoken = ccl_token_add (cclp->look_token); + + ntoken->kind = CCL_TOK_TERM; + ntoken->name = "-"; + ntoken->len = 1; + + (cclp->look_token->len)--; + } + else if (cclp->look_token->len > 2 && i < cclp->look_token->len) + { /* xx-yy */ + struct ccl_token *ntoken1 = ccl_token_add (cclp->look_token); + struct ccl_token *ntoken2 = ccl_token_add (ntoken1); + + ntoken1->kind = CCL_TOK_TERM; /* generate - */ + ntoken1->name = "-"; + ntoken1->len = 1; + + ntoken2->kind = CCL_TOK_TERM; /* generate yy */ + ntoken2->name = cclp->look_token->name + (i+1); + ntoken2->len = cclp->look_token->len - (i+1); + + cclp->look_token->len = i; /* adjust xx */ + } + else if (i == cclp->look_token->len && + cclp->look_token->next && + cclp->look_token->next->kind == CCL_TOK_TERM && + cclp->look_token->next->len > 1 && + cclp->look_token->next->name[0] == '-') + + { /* xx -yy */ + /* we _know_ that xx does not have - in it */ + struct ccl_token *ntoken = ccl_token_add (cclp->look_token); + + ntoken->kind = CCL_TOK_TERM; /* generate - */ + ntoken->name = "-"; + ntoken->len = 1; + + (ntoken->next->name)++; /* adjust yy */ + (ntoken->next->len)--; + } + } + } - ADVANCE; /* skip relation */ - if (KIND == CCL_TOK_TERM && - cclp->look_token->next && cclp->look_token->next->len == 1 && - cclp->look_token->next->name[0] == '-') - { - struct ccl_rpn_node *p1; - if (!(p1 = search_term (cclp, ap))) - return NULL; - ADVANCE; /* skip '-' */ - if (KIND == CCL_TOK_TERM) /* = term - term ? */ - { - struct ccl_rpn_node *p2; - - if (!(p2 = search_term (cclp, ap))) - { - ccl_rpn_delete (p1); - return NULL; - } - p = mk_node (CCL_RPN_AND); - p->u.p[0] = p1; - add_attr_numeric (p1, attset, CCL_BIB1_REL, 4); - p->u.p[1] = p2; - add_attr_numeric (p2, attset, CCL_BIB1_REL, 2); - return p; - } - else /* = term - */ - { - add_attr_numeric (p1, attset, CCL_BIB1_REL, 4); - return p1; - } - } - else if (cclp->look_token->len == 1 && - cclp->look_token->name[0] == '-') /* = - term ? */ - { - ADVANCE; - if (!(p = search_term (cclp, ap))) - return NULL; - add_attr_numeric (p, attset, CCL_BIB1_REL, 2); - return p; - } - else if (KIND == CCL_TOK_LP) - { - ADVANCE; - if (!(p = find_spec (cclp, ap))) - return NULL; - if (KIND != CCL_TOK_RP) - { - cclp->error_code = CCL_ERR_RP_EXPECTED; - ccl_rpn_delete (p); - return NULL; - } - ADVANCE; - return p; - } - else - { - if (!(p = search_terms (cclp, ap))) - return NULL; - add_attr_numeric (p, attset, CCL_BIB1_REL, rel); - return p; - } - cclp->error_code = CCL_ERR_TERM_EXPECTED; + if (rel == 3 && + KIND == CCL_TOK_TERM && + cclp->look_token->next && cclp->look_token->next->len == 1 && + cclp->look_token->next->name[0] == '-') + { + struct ccl_rpn_node *p1; + if (!(p1 = search_term (cclp, ap))) + return NULL; + ADVANCE; /* skip '-' */ + if (KIND == CCL_TOK_TERM) /* = term - term ? */ + { + struct ccl_rpn_node *p2; + + if (!(p2 = search_term (cclp, ap))) + { + ccl_rpn_delete (p1); + return NULL; + } + p = mk_node (CCL_RPN_AND); + p->u.p[0] = p1; + add_attr_numeric (p1, attset, CCL_BIB1_REL, 4); + p->u.p[1] = p2; + add_attr_numeric (p2, attset, CCL_BIB1_REL, 2); + return p; + } + else /* = term - */ + { + add_attr_numeric (p1, attset, CCL_BIB1_REL, 4); + return p1; + } } + else if (rel == 3 && + cclp->look_token->len == 1 && + cclp->look_token->name[0] == '-') /* = - term ? */ + { + ADVANCE; + if (!(p = search_term (cclp, ap))) + return NULL; + add_attr_numeric (p, attset, CCL_BIB1_REL, 2); + return p; + } + else if (KIND == CCL_TOK_LP) + { + ADVANCE; + if (!(p = find_spec (cclp, ap))) + return NULL; + if (KIND != CCL_TOK_RP) + { + cclp->error_code = CCL_ERR_RP_EXPECTED; + ccl_rpn_delete (p); + return NULL; + } + ADVANCE; + return p; + } + else + { + if (!(p = search_terms (cclp, ap))) + return NULL; + add_attr_numeric (p, attset, CCL_BIB1_REL, rel); + return p; + } + cclp->error_code = CCL_ERR_TERM_EXPECTED; return NULL; } -/* +static +struct ccl_rpn_node *qualifiers2 (CCL_parser cclp, struct ccl_rpn_attr **ap) +{ + char *attset; + struct ccl_rpn_node *p; + + if (qual_val_type(ap, CCL_BIB1_REL, CCL_BIB1_REL_ORDER, &attset) + || qual_val_type(ap, CCL_BIB1_REL, CCL_BIB1_REL_PORDER, &attset)) + return qualifiers_order(cclp, ap, attset); + + /* unordered relation */ + if (KIND != CCL_TOK_EQ) + { + cclp->error_code = CCL_ERR_EQ_EXPECTED; + return NULL; + } + ADVANCE; + if (KIND == CCL_TOK_LP) + { + ADVANCE; + if (!(p = find_spec (cclp, ap))) + { + return NULL; + } + if (KIND != CCL_TOK_RP) + { + cclp->error_code = CCL_ERR_RP_EXPECTED; + ccl_rpn_delete (p); + return NULL; + } + ADVANCE; + } + else + p = search_terms (cclp, ap); + return p; +} + +/** * qualifiers1: Parse CCL qualifiers and search terms. * cclp: CCL Parser * la: Token pointer to RELATION token. @@ -814,7 +904,7 @@ static struct ccl_rpn_node *qualifiers1 (CCL_parser cclp, struct ccl_token *la, } -/* +/** * search_terms: Parse CCL search terms - including proximity. * cclp: CCL Parser * qa: Qualifier attributes already applied. @@ -876,7 +966,7 @@ static struct ccl_rpn_node *search_terms (CCL_parser cclp, return p1; } -/* +/** * search_elements: Parse CCL search elements * cclp: CCL Parser * qa: Qualifier attributes already applied. @@ -970,7 +1060,7 @@ static struct ccl_rpn_node *search_elements (CCL_parser cclp, } } -/* +/** * find_spec: Parse CCL find specification * cclp: CCL Parser * qa: Qualifier attributes already applied. @@ -1038,8 +1128,6 @@ struct ccl_rpn_node *ccl_parser_find (CCL_parser cclp, struct ccl_token *list) { struct ccl_rpn_node *p; - - cclp->look_token = list; p = find_spec (cclp, NULL); if (p && KIND != CCL_TOK_EOL) @@ -1059,7 +1147,7 @@ struct ccl_rpn_node *ccl_parser_find (CCL_parser cclp, struct ccl_token *list) return p; } -/* +/** * ccl_find: Parse CCL find - token representation * bibset: Bibset to be used for the parsing * list: List of tokens @@ -1085,7 +1173,7 @@ struct ccl_rpn_node *ccl_find (CCL_bibset bibset, struct ccl_token *list, return p; } -/* +/** * ccl_find_str: Parse CCL find - string representation * bibset: Bibset to be used for the parsing * str: String to be parsed