# include "Slip.h" /** * @brief gSlip equivalent to N:YMATCH function in MAD-Slip * * Pattern matching is done by comparing the input rule against * a list. For the nonce, the list does not contain any sublist. * This interpretation seems consistent with the example given * in MAD_SLIPManual.pdf, in that the example and definition do * not separately specify any mechanicism which can recognize * and process a sublist. * * The comparison is done in a linear fashion, starting at the * first cell in the rule and the input list. The code logic * seems to be: * 1. If the spec cell is an integer * a. If the spec is zero, create a sublist containing * all input list cells from the current cell to the * last cell in the input list. Append this sublist * to the result and advance the input list 'pointer' * and the rule 'pointer' to the ends of their respective * lists. * b. If the spec is a number > 0, then create a sublist * containing that number of cells from the input list * and append this list to the result. Advance the * input list 'pointer' to the number of cells copied * and the rule list by 1. * c. If the spec is a number > 0 and there are less than * number of cells left in the input list, then we fail. * d. If the number < 0, we fail. * 2. If the spec cell is a literal (as defined in MAD_Slip * a literal is a string) then: * a. If there is no match to the current input cell, then * continue searching. This logic can be changed. * b. If there is a match to the currect input cell, then * create a sublist and append it to the result. Advance * the input list 'pointer' by 1 and the rule list 'pointer' * by 1. * 3. If the rule list is a sublist, then advance over it (ignore * all sublists). * 4. If the input list is a sublist, then advance over it * (ignore all sublists). * 5. Terminate processing when either the rule list is empty * or the input list is empty. Note 'empty' means that the * list 'pointer' points to the list header. It does not * mean that the original list contains no elements. * * Some Notes: * 1. The algorithm is non-destructive. The input list parameters * are unchanged. * 2. The algorithm is primed by advancing over the input list * parameters to the first cell in the list. If the list is * empty, then the first cell in the list is the list header * and this terminates processing. * 3. The list 'pointer' is never seen by the application. The * application only sees the current list cell being proessed. * 4. Step 1.a. implies that an input spec of zero (0) must be * the last spec in the input rules. * 5. Step 1.c. this condition is not specified in MAD_SLIPManual. * It is assumed to be the intent of the writer. An alternative * would be to declare this an error and take fixup, but there * is no way to report an error back to the caller. * 6. Rule comparison is linear. It goes from left to right (start * to finish) without backup. Once a comparison is made and is * successful, the rule advances. * 7. Step 2 is the nub of the argument. This specifies the exact * mechanism for comparing rule to the input list. Part of this * is that a failure comparison between a rule literal and the * input list cell causes the input list to advance but the * rule list to stay where it is. * 8. No mechanism is specified in MAD_SLIPManual to treat sublists. * It is assumed that sublists are not entered but that if the * input spec is a number, then sublists are copied. * 9. There is an assumption that the output result is an empty * list on entry. * 10. On error, the output result is not emptied. * * @param[IN] rule rename L1 * @param[IN] list rename L2 * @param[OUT] result rename L3 */ int YMATCH(SlipHeader rule, SlipHeader list, SlipHeader result ) { SlipCell cell = input.advanceLER(); //!< advance to first slip cell SlipCell spec = rule.advanceLER(); //!< advnace to first rule //!< advance in the rule for (; !cell.isHeader() && !spec.isHeadaer(); spec.advanceLWR() ) { if (spec.isSublist()) continue; //!< sublists in the rule are excluded if (cell.isSublist()) continue; //!< sublists in the input list are excluded if (spec.isNumber()) { if (spec < 0) continue; SlipHeader* head = new SlipHeader(); if (spec == 0) { for (; !cell.isHeader(); cell.advanceLWR()) { head.enqueue(cell); } } else { int i; for (i = 0; (i < spec) && !cell.isHeader(); cell.advanceLWR()) { head.enqueue(cell); } if (i != spec) return 1; } cell.advanceLWL(); // we went too far result.enqueue(head); // put a sublist into the result // The assumption is that we search until a string // match is found. If the requirement is that the // next string in the input list must be the literal // in the spec, then the for loop is replaced by a // conditional. } else if (spec.isString() { // spec must be a literal // replace if 'if' as required for (; !cell.isHeader() && cell != spec; cell.advanceLWR()); if (cell.isHeader()) cell.advanceLWL(); // did not find, fixup list pointer if (cell != spec) return 1; // a string match was not found SlipHeader* head = new SlipHeader(); head.enqueue(cell); result.enqueue(head); } else { // action unspecified } } return (int)result.isEmpty(); } // int YMATCH()