home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / red98104.zip / RxRegExp.INF (.txt) < prev    next >
OS/2 Help File  |  1998-04-14  |  13KB  |  401 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Introduction ΓòÉΓòÉΓòÉ
  3.  
  4. Introduction 
  5.  
  6. The "RxRegExp.DLL" code allows any rexx program to make fast extensive use of 
  7. regular expression searches and replaces. 
  8.  
  9. The original regular expession "engine" (which was not modified) was written by 
  10. "Henry Spencer" (henry@zoo.toronto.edu).  There is no version number on this 
  11. source that I can find although the doco is dated "5 Sept 1996". 
  12.  
  13. I have provided a sample rexx program which should help you get started. 
  14.  
  15. The DLL was written by "Dennis Bareis" (db0@anz.com), the latest code can be 
  16. obtained from my web page at "http://www.ozemail.com.au/~dbareis". 
  17.  
  18.  
  19. ΓòÉΓòÉΓòÉ 2. Regular Expressions ΓòÉΓòÉΓòÉ
  20.  
  21. The following description is based on the documentation written by 
  22. "Henry Spencer" (henry@zoo.toronto.edu). 
  23.  
  24. Regular Expressions 
  25.  
  26. A regular expression is a sequence of characters which describes what we are 
  27. searching for. 
  28.  
  29. A regular expression is zero or more branches separated by "|".  It matches 
  30. anything that matches one of the branches. 
  31.  
  32. A branch is zero or more pieces, concatenated. It matches a match for the 
  33. first, followed by a match for the second, etc. 
  34.  
  35. A piece is an atom possibly followed by "*", "+", or "?" where: 
  36.  
  37.          An atom followed by "*" matches a sequence of 0 or more matches of 
  38.           the atom. 
  39.          An atom followed by "+" matches a sequence of 1 or more matches of 
  40.           the atom. 
  41.          An atom followed by "?" matches a match of the atom, or the null 
  42.           string. 
  43.  
  44.  An atom is: 
  45.  
  46.          A regular expression in parentheses (matching a match for the regular 
  47.           expression), a range (see below). 
  48.  
  49.          "." which matches any single character. 
  50.  
  51.          "^" which matches the empty string at the start of a line. 
  52.  
  53.          "$" which matches the empty string at the end of a line. 
  54.  
  55.          "\e" (a slash followed by a character) which matches the character. 
  56.           This is needed so search for "$" etc! 
  57.  
  58.          A single character with no other significance matches that character. 
  59.  
  60.  A range is a sequence of characters enclosed in "[]". It normally matches any 
  61.  single character from the sequence. If the sequence begins with "^", it 
  62.  matches any single character not from the rest of the sequence. If two 
  63.  characters in the sequence are separated by "-" then this is shorthand for the 
  64.  full list of ASCII characters between them (e.g. "[0-9]" matches any decimal 
  65.  digit). To include a literal "]" in the sequence, make it the first character 
  66.  (following a possible "^"). To include a literal "-", make it the first or 
  67.  last character. 
  68.  
  69.  AMBIGUITY 
  70.  
  71.  If a regular expression could match two different parts of the input string, 
  72.  it will match the one which begins earliest. If both begin in the same place 
  73.  but match different lengths, or match the same length in different ways, life 
  74.  gets messier, as follows: 
  75.  
  76.          In general, the possibilities in a list of branches are considered in 
  77.           left-to-right order, the possibilities for "*", "+", and "?" are 
  78.           considered longest-first, nested constructs are considered from the 
  79.           outermost in, and concatenated constructs are considered 
  80.           leftmost-first. The match that will be chosen is the one that uses 
  81.           the earliest possibility in the first choice that has to be made. If 
  82.           there is more than one choice, the next will be made in the same 
  83.           manner (earliest possibility) subject to the decision on the first 
  84.           choice. And so forth. 
  85.  
  86.           For example, "(ab|a)b*c" could match "abc" in one of two ways. The 
  87.           first choice is between "ab" and "a"; since "ab" is earlier, and does 
  88.           lead to a successful overall match, it is chosen. Since the "b" is 
  89.           already spoken for, the "b*" must match its last possibility (the 
  90.           empty string) since it must respect the earlier choice. 
  91.  
  92.          In the particular case where the regular expression does not use "|" 
  93.           and does not apply "*", "+", or "?" to parenthesized subexpressions, 
  94.           the net effect is that the longest possible match will be chosen. So 
  95.           "ab*", presented with "xabbbby", will match "abbbb". Note that if 
  96.           "ab*" is tried against "xabyabbbz", it will match "ab" just after 
  97.           "x", due to the begins-earliest rule. In effect, the decision on 
  98.           where to start the match is the first choice to be made, hence 
  99.           subsequent choices must respect it even if this leads them to 
  100.           less-preferred alternatives. 
  101.  
  102.  
  103. ΓòÉΓòÉΓòÉ 3. Commands ΓòÉΓòÉΓòÉ
  104.  
  105. Commands 
  106.  
  107. The following functions are available: 
  108.  
  109.          RegExpVersion 
  110.          RegExpCompile 
  111.          RegExpMatch 
  112.          RegExpReplace 
  113.  
  114.  Note that you can't trust the return codes from rexx add/query/drop functions 
  115.  so if you wish to detect (instead of dying) that the DLL is unavailable you 
  116.  should check my sample rexx program which contains a subroutine which does 
  117.  this. 
  118.  
  119.  
  120. ΓòÉΓòÉΓòÉ 3.1. RegExpVersion ΓòÉΓòÉΓòÉ
  121.  
  122. RegExpVersion 
  123.  
  124. This routine will allow you to determine the version and author information of 
  125. the DLL you are using. 
  126.  
  127. The routine takes a single parameter as follows: 
  128.  
  129.        1. Name of Variable to update with version Information. 
  130.  
  131.  The information returned (seperated by a single space): 
  132.  
  133.        1. Version Number such as "98.104". 
  134.        2. My Web page URL (where you can get a later version if available). 
  135.        3. My email Address. 
  136.        4. My Name. 
  137.  
  138.  Please see my sample rexx program for an example of this call in use. 
  139.  
  140.  Returns 
  141.  
  142.  This routine returns "OK" if the call succeeds otherwise it returns text which 
  143.  describes the reason for the failure. 
  144.  
  145.  
  146. ΓòÉΓòÉΓòÉ 3.2. RegExpCompile ΓòÉΓòÉΓòÉ
  147.  
  148. RegExpCompile 
  149.  
  150. To make use of a regular expression it must first be compiled. This routine 
  151. will either compile a regular expression or release any memory associated with 
  152. the last compiled regular expression. 
  153.  
  154. The routine takes a single parameter as follows: 
  155.  
  156.        1. The regular expression to be compiled.  There is one exception, if 
  157.           you pass exactly "ReClose" then this is taken to be a close off 
  158.           previous regular expression command. 
  159.  
  160.  The compiled express (plus some other bits) are held in memory until released. 
  161.  Rexx programs running in different sessions will not interfere with each 
  162.  other.  Not sure if there can be any problems within a session but I suspect 
  163.  not. 
  164.  
  165.  Please see my sample rexx program for an example of this call in use. 
  166.  
  167.  Returns 
  168.  
  169.  This routine returns "OK" if the call succeeds otherwise it returns text which 
  170.  describes the reason for the failure. 
  171.  
  172.  
  173. ΓòÉΓòÉΓòÉ 3.3. RegExpMatch ΓòÉΓòÉΓòÉ
  174.  
  175. RegExpMatch 
  176.  
  177. This routine will attempt to find a regular expression which was previously 
  178. compiled. 
  179.  
  180. The routine takes 2 parameters as follows: 
  181.  
  182.        1. The string to be searched. 
  183.        2. Name of Variable to update with match details.  If the variable is 
  184.           blank then there was no match otherwise a set of one or more 
  185.           "match pairs" is returned. 
  186.  
  187.  Match Pairs 
  188.  
  189.  In a set of match pairs the first describes the location of the overall 
  190.  regular expression while any others (if they exist) describe the location of 
  191.  any matches for expressions that occurred between round brackets in the 
  192.  regular expression. 
  193.  
  194.  Each match pair describes the starting position (1st byte is 1) and the length 
  195.  of the match. 
  196.  
  197.  If you used the regular expression "(A)(B)" on the string "ABCDEF" then 
  198.  "1 2 1 1 2 1" would be returned. 
  199.  
  200.  Please see my sample rexx program for an example of this call in use. 
  201.  
  202.  Returns 
  203.  
  204.  This routine returns "OK" if the call succeeds otherwise it returns text which 
  205.  describes the reason for the failure. 
  206.  
  207.  
  208. ΓòÉΓòÉΓòÉ 3.4. RegExpReplace ΓòÉΓòÉΓòÉ
  209.  
  210. RegExpReplace 
  211.  
  212. This routine will modify a string you supply based on the match information 
  213. from a previous regular expression. 
  214.  
  215. The routine takes 2 parameters as follows: 
  216.  
  217.        1. The replace specification. 
  218.        2. Name of Variable which will contain the modified string. 
  219.  
  220.  Replace Specification 
  221.  
  222.  The first thing you should understand is that we are not performing and sort 
  223.  of normal search and replace here, we are taking a specification and building 
  224.  a new string.  If you wanted to perform a search and replace type operation 
  225.  you would need to use round brackets and ensure that the before and after 
  226.  match strings were described.  Note that doing this can vary the match 
  227.  location of the string you are trying to match! 
  228.  
  229.  The replace specification is basically a string where any occurrance of "&" or 
  230.  "\0" is replaced with the overall matched characters.  "\1" to "\9" are 
  231.  replaced with the appropriate match information for each round bracketed 
  232.  expression ('\1' is first one). 
  233.  
  234.  For example you may wish to replace "SET" with "set" in which case you could 
  235.  have used the regular expression "SET" to search for the string with 
  236.  "RegExpMatch", however this would not be useful unless you manually wrote code 
  237.  to do the replacement (not hard), to use this "replace" routine you would 
  238.  search with something like "(^.*)SET(.*$)" and then your replace specification 
  239.  could be "\1set\2". 
  240.  
  241.  Please see my sample rexx program for an example of this call in use. 
  242.  
  243.  Returns 
  244.  
  245.  This routine returns "OK" if the call succeeds otherwise it returns text which 
  246.  describes the reason for the failure. 
  247.  
  248.  
  249. ΓòÉΓòÉΓòÉ 4. Rexx Example ΓòÉΓòÉΓòÉ
  250.  
  251. Rexx Example 
  252.  
  253. /* Small Test program for my REXX Regular Expression Code */
  254.  
  255. /*--- Load up functions we will use -----------------------------------------*/
  256. call RxFuncAdd   'RegExpVersion', 'RxRegExp', 'RegExpVersion';
  257. call RxFuncAdd   'RegExpCompile', 'RxRegExp', 'RegExpCompile';
  258. call RxFuncAdd   'RegExpMatch',   'RxRegExp', 'RegExpMatch';
  259. call RxFuncAdd   'RegExpReplace', 'RxRegExp', 'RegExpReplace';
  260.  
  261. /*--- Make sure Regular Expression DLL is available for use -----------------*/
  262. say 'RxRegExp.DLL';
  263. say '~~~~~~~~~~~~';
  264. if RegExpOk() = 'N' then
  265. do
  266.    say "Regular Expressions can't be used (DLL probably unavailable)!";
  267.    exit(GetLineNumber());
  268. end;
  269. say "Available";
  270.  
  271. /*--- Display Version Info --------------------------------------------------*/
  272. say '';
  273. say 'RegExpVersion';
  274. say '~~~~~~~~~~~~~';
  275. VerRc = RegExpVersion('ReVersion');
  276. if VerRc <> 'OK' then
  277. do
  278.    say '    COULD NOT GET RXREGEXP.DLL VERSION INFO'
  279.    say '    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
  280.    say '    ' || VerRc;
  281.    exit(GetLineNumber());
  282. end;
  283. parse var ReVersion DllVersion WebPage EmailAddress AuthorName;
  284. say 'Version  = ' || DllVersion;
  285. say 'Author   = ' || AuthorName;
  286. say 'Email    = ' || EmailAddress;
  287. say 'Web Page = ' || WebPage;
  288.  
  289. /*--- Define/Compile regular expression -------------------------------------*/
  290. say ''
  291. say 'RegExpCompile';
  292. say '~~~~~~~~~~~~~';
  293. Re = arg(1);
  294. if Re = '' then
  295.    Re = "1[12]";
  296. CompileRc = RegExpCompile(Re);
  297. say CompileRc;
  298. if CompileRc <> 'OK' then
  299.    exit(GetLineNumber());
  300.  
  301. /*--- Look for a match ------------------------------------------------------*/
  302. LookIn = "AAA112BBB";
  303. say ''
  304. say 'RegExpMatch';
  305. say '~~~~~~~~~~~';
  306. say 'Looking for ' || Re || ' in "' || LookIn || '"';
  307. Answer  = '?';
  308. MatchRc = RegExpMatch(LookIn, "Answer");
  309. if MatchRc <> 'OK' then
  310. do
  311.    /*--- An error occurred --------------------------------------------------*/
  312.    say '    ERROR'
  313.    say '    ~~~~~'
  314.    say '    ' || MatchRc;
  315.    exit(GetLineNumber());
  316. end
  317. else
  318. do
  319.    /*--- Did we have any matches? -------------------------------------------*/
  320.    if  Answer = '' then
  321.    do
  322.        say '   * No Matches';
  323.        exit(GetLineNumber());
  324.    end;
  325.  
  326.    /*--- List all matches and submatches ------------------------------------*/
  327.    say '   * MatchList = ' || Answer;
  328.  
  329.    /*--- Extract the overall match information ------------------------------*/
  330.    parse var Answer MatchStart MatchLength SubMatch;
  331.    say '   * Match starts at posn ' || MatchStart || ' and is ' || MatchLength || ' bytes long.';
  332.  
  333.    /*--- Extract the submatch information -----------------------------------*/
  334.    Index = 0;
  335.    do  forever
  336.        /*--- Extract info ---------------------------------------------------*/
  337.        parse var SubMatch SubMatchStart SubMatchLength SubMatch;
  338.  
  339.        /*--- Make sure we have the information ------------------------------*/
  340.        if  SubMatchLength = '' then
  341.            leave;
  342.  
  343.        /*--- Report the information -----------------------------------------*/
  344.        Index = Index + 1;
  345.        say '   * Match (' || Index || ') starts at posn ' || SubMatchStart || ' and is ' || SubMatchLength || ' bytes long.';
  346.    end;
  347. end;
  348.  
  349. /*--- Make change -----------------------------------------------------------*/
  350. say ''
  351. say 'RegExpReplace';
  352. say '~~~~~~~~~~~~~';
  353. Before = "xxx\0yyy"
  354. say 'Replacing: ' || Before
  355. Answer = '?';
  356. MatchRc = RegExpReplace(Before, "Answer");
  357. say 'ReplaceRc = ' || MatchRc;
  358. say 'Answer    = ' || Answer;
  359.  
  360. /*--- Close Regular expression ----------------------------------------------*/
  361. say '';
  362. say 'RegExpCompile(ReClose)';
  363. say '~~~~~~~~~~~~~~~~~~~~~~';
  364. say RegExpCompile("ReClose");
  365. exit(0);
  366.  
  367.  
  368. /*===========================================================================*/
  369. RegExpOk:
  370. /*                                                                           */
  371. /* None of the rexx 'Rx' functions (add/drop/query) work correctly.  The     */
  372. /* return code can't be trusted.                                             */
  373. /*                                                                           */
  374. /* This routine will return 'Y' if the DLL can be accessed.  It calls one    */
  375. /* of the known functions.  We have already registered it so if we fail then */
  376. /* the registration failed.                                                  */
  377. /*                                                                           */
  378. /* Note that as this code is within a subroutine the trap handler we set up  */
  379. /* does not override and set up in the calling code once this routine        */
  380. /* returns.                                                                  */
  381. /*===========================================================================*/
  382.    /*--- Get up trap handler and execute the command ------------------------*/
  383.    signal on SYNTAX  name RegExpNotOk;
  384.    interpret "DummyReRc = RegExpVersion('ReVersion')";
  385.  
  386.    /*--- We did not die so the function must be available -------------------*/
  387.    return('Y');
  388.  
  389.    /*--- We must have died so the function is unavailable -------------------*/
  390.    RegExpNotOk:
  391.    return('N');
  392.  
  393.  
  394.  
  395. /*===========================================================================*/
  396. GetLineNumber:
  397. /*===========================================================================*/
  398.    return( SIGL );
  399.  
  400.  
  401.