1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- G N A T . S P I T B O L . P A T T E R N S --
9 -- Copyright (C) 1998-2016, AdaCore --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- Note: the data structures and general approach used in this implementation
33 -- are derived from the original MINIMAL sources for SPITBOL. The code is not
34 -- a direct translation, but the approach is followed closely. In particular,
35 -- we use the one stack approach developed in the SPITBOL implementation.
37 with Ada
.Strings
.Unbounded
.Aux
; use Ada
.Strings
.Unbounded
.Aux
;
39 with GNAT
.Debug_Utilities
; use GNAT
.Debug_Utilities
;
41 with System
; use System
;
43 with Ada
.Unchecked_Conversion
;
44 with Ada
.Unchecked_Deallocation
;
46 package body GNAT
.Spitbol
.Patterns
is
48 ------------------------
49 -- Internal Debugging --
50 ------------------------
52 Internal_Debug
: constant Boolean := False;
53 -- Set this flag to True to activate some built-in debugging traceback
54 -- These are all lines output with PutD and Put_LineD.
57 pragma Inline
(New_LineD
);
58 -- Output new blank line with New_Line if Internal_Debug is True
60 procedure PutD
(Str
: String);
62 -- Output string with Put if Internal_Debug is True
64 procedure Put_LineD
(Str
: String);
65 pragma Inline
(Put_LineD
);
66 -- Output string with Put_Line if Internal_Debug is True
68 -----------------------------
69 -- Local Type Declarations --
70 -----------------------------
72 subtype String_Ptr
is Ada
.Strings
.Unbounded
.String_Access
;
73 subtype File_Ptr
is Ada
.Text_IO
.File_Access
;
75 function To_Address
is new Ada
.Unchecked_Conversion
(PE_Ptr
, Address
);
76 -- Used only for debugging output purposes
78 subtype AFC
is Ada
.Finalization
.Controlled
;
80 N
: constant PE_Ptr
:= null;
81 -- Shorthand used to initialize Copy fields to null
83 type Natural_Ptr
is access all Natural;
84 type Pattern_Ptr
is access all Pattern
;
86 --------------------------------------------------
87 -- Description of Algorithm and Data Structures --
88 --------------------------------------------------
90 -- A pattern structure is represented as a linked graph of nodes
91 -- with the following structure:
93 -- +------------------------------------+
95 -- +------------------------------------+
97 -- +------------------------------------+
99 -- +------------------------------------+
101 -- +------------------------------------+
103 -- Pcode is a code value indicating the type of the pattern node. This
104 -- code is used both as the discriminant value for the record, and as
105 -- the case index in the main match routine that branches to the proper
106 -- match code for the given element.
108 -- Index is a serial index number. The use of these serial index
109 -- numbers is described in a separate section.
111 -- Pthen is a pointer to the successor node, i.e the node to be matched
112 -- if the attempt to match the node succeeds. If this is the last node
113 -- of the pattern to be matched, then Pthen points to a dummy node
114 -- of kind PC_EOP (end of pattern), which initializes pattern exit.
116 -- The parameter or parameters are present for certain node types,
117 -- and the type varies with the pattern code.
119 type Pattern_Code
is (
212 type IndexT
is range 0 .. +(2 **15 - 1);
214 type PE
(Pcode
: Pattern_Code
) is record
217 -- Serial index number of pattern element within pattern
220 -- Successor element, to be matched after this one
277 Str2
: String (1 .. 2);
280 Str3
: String (1 .. 3);
283 Str4
: String (1 .. 4);
286 Str5
: String (1 .. 5);
289 Str6
: String (1 .. 6);
350 subtype PC_Has_Alt
is Pattern_Code
range PC_Alt
.. PC_Arbno_X
;
351 -- Range of pattern codes that has an Alt field. This is used in the
352 -- recursive traversals, since these links must be followed.
354 EOP_Element
: aliased constant PE
:= (PC_EOP
, 0, N
);
355 -- This is the end of pattern element, and is thus the representation of
356 -- a null pattern. It has a zero index element since it is never placed
357 -- inside a pattern. Furthermore it does not need a successor, since it
358 -- marks the end of the pattern, so that no more successors are needed.
360 EOP
: constant PE_Ptr
:= EOP_Element
'Unrestricted_Access;
361 -- This is the end of pattern pointer, that is used in the Pthen pointer
362 -- of other nodes to signal end of pattern.
364 -- The following array is used to determine if a pattern used as an
365 -- argument for Arbno is eligible for treatment using the simple Arbno
366 -- structure (i.e. it is a pattern that is guaranteed to match at least
367 -- one character on success, and not to make any entries on the stack.
369 OK_For_Simple_Arbno
: constant array (Pattern_Code
) of Boolean :=
392 -------------------------------
393 -- The Pattern History Stack --
394 -------------------------------
396 -- The pattern history stack is used for controlling backtracking when
397 -- a match fails. The idea is to stack entries that give a cursor value
398 -- to be restored, and a node to be reestablished as the current node to
399 -- attempt an appropriate rematch operation. The processing for a pattern
400 -- element that has rematch alternatives pushes an appropriate entry or
401 -- entry on to the stack, and the proceeds. If a match fails at any point,
402 -- the top element of the stack is popped off, resetting the cursor and
403 -- the match continues by accessing the node stored with this entry.
405 type Stack_Entry
is record
408 -- Saved cursor value that is restored when this entry is popped
409 -- from the stack if a match attempt fails. Occasionally, this
410 -- field is used to store a history stack pointer instead of a
411 -- cursor. Such cases are noted in the documentation and the value
412 -- stored is negative since stack pointer values are always negative.
415 -- This pattern element reference is reestablished as the current
416 -- Node to be matched (which will attempt an appropriate rematch).
420 subtype Stack_Range
is Integer range -Stack_Size
.. -1;
422 type Stack_Type
is array (Stack_Range
) of Stack_Entry
;
423 -- The type used for a history stack. The actual instance of the stack
424 -- is declared as a local variable in the Match routine, to properly
425 -- handle recursive calls to Match. All stack pointer values are negative
426 -- to distinguish them from normal cursor values.
428 -- Note: the pattern matching stack is used only to handle backtracking.
429 -- If no backtracking occurs, its entries are never accessed, and never
430 -- popped off, and in particular it is normal for a successful match
431 -- to terminate with entries on the stack that are simply discarded.
433 -- Note: in subsequent diagrams of the stack, we always place element
434 -- zero (the deepest element) at the top of the page, then build the
435 -- stack down on the page with the most recent (top of stack) element
436 -- being the bottom-most entry on the page.
438 -- Stack checking is handled by labeling every pattern with the maximum
439 -- number of stack entries that are required, so a single check at the
440 -- start of matching the pattern suffices. There are two exceptions.
442 -- First, the count does not include entries for recursive pattern
443 -- references. Such recursions must therefore perform a specific
444 -- stack check with respect to the number of stack entries required
445 -- by the recursive pattern that is accessed and the amount of stack
446 -- that remains unused.
448 -- Second, the count includes only one iteration of an Arbno pattern,
449 -- so a specific check must be made on subsequent iterations that there
450 -- is still enough stack space left. The Arbno node has a field that
451 -- records the number of stack entries required by its argument for
454 ---------------------------------------------------
455 -- Use of Serial Index Field in Pattern Elements --
456 ---------------------------------------------------
458 -- The serial index numbers for the pattern elements are assigned as
459 -- a pattern is constructed from its constituent elements. Note that there
460 -- is never any sharing of pattern elements between patterns (copies are
461 -- always made), so the serial index numbers are unique to a particular
462 -- pattern as referenced from the P field of a value of type Pattern.
464 -- The index numbers meet three separate invariants, which are used for
465 -- various purposes as described in this section.
467 -- First, the numbers uniquely identify the pattern elements within a
468 -- pattern. If Num is the number of elements in a given pattern, then
469 -- the serial index numbers for the elements of this pattern will range
470 -- from 1 .. Num, so that each element has a separate value.
472 -- The purpose of this assignment is to provide a convenient auxiliary
473 -- data structure mechanism during operations which must traverse a
474 -- pattern (e.g. copy and finalization processing). Once constructed
475 -- patterns are strictly read only. This is necessary to allow sharing
476 -- of patterns between tasks. This means that we cannot go marking the
477 -- pattern (e.g. with a visited bit). Instead we construct a separate
478 -- vector that contains the necessary information indexed by the Index
479 -- values in the pattern elements. For this purpose the only requirement
480 -- is that they be uniquely assigned.
482 -- Second, the pattern element referenced directly, i.e. the leading
483 -- pattern element, is always the maximum numbered element and therefore
484 -- indicates the total number of elements in the pattern. More precisely,
485 -- the element referenced by the P field of a pattern value, or the
486 -- element returned by any of the internal pattern construction routines
487 -- in the body (that return a value of type PE_Ptr) always is this
490 -- The purpose of this requirement is to allow an immediate determination
491 -- of the number of pattern elements within a pattern. This is used to
492 -- properly size the vectors used to contain auxiliary information for
493 -- traversal as described above.
495 -- Third, as compound pattern structures are constructed, the way in which
496 -- constituent parts of the pattern are constructed is stylized. This is
497 -- an automatic consequence of the way that these compound structures
498 -- are constructed, and basically what we are doing is simply documenting
499 -- and specifying the natural result of the pattern construction. The
500 -- section describing compound pattern structures gives details of the
501 -- numbering of each compound pattern structure.
503 -- The purpose of specifying the stylized numbering structures for the
504 -- compound patterns is to help simplify the processing in the Image
505 -- function, since it eases the task of retrieving the original recursive
506 -- structure of the pattern from the flat graph structure of elements.
507 -- This use in the Image function is the only point at which the code
508 -- makes use of the stylized structures.
510 type Ref_Array
is array (IndexT
range <>) of PE_Ptr
;
511 -- This type is used to build an array whose N'th entry references the
512 -- element in a pattern whose Index value is N. See Build_Ref_Array.
514 procedure Build_Ref_Array
(E
: PE_Ptr
; RA
: out Ref_Array
);
515 -- Given a pattern element which is the leading element of a pattern
516 -- structure, and a Ref_Array with bounds 1 .. E.Index, fills in the
517 -- Ref_Array so that its N'th entry references the element of the
518 -- referenced pattern whose Index value is N.
520 -------------------------------
521 -- Recursive Pattern Matches --
522 -------------------------------
524 -- The pattern primitive (+P) where P is a Pattern_Ptr or Pattern_Func
525 -- causes a recursive pattern match. This cannot be handled by an actual
526 -- recursive call to the outer level Match routine, since this would not
527 -- allow for possible backtracking into the region matched by the inner
528 -- pattern. Indeed this is the classical clash between recursion and
529 -- backtracking, and a simple recursive stack structure does not suffice.
531 -- This section describes how this recursion and the possible associated
532 -- backtracking is handled. We still use a single stack, but we establish
533 -- the concept of nested regions on this stack, each of which has a stack
534 -- base value pointing to the deepest stack entry of the region. The base
535 -- value for the outer level is zero.
537 -- When a recursive match is established, two special stack entries are
538 -- made. The first entry is used to save the original node that starts
539 -- the recursive match. This is saved so that the successor field of
540 -- this node is accessible at the end of the match, but it is never
541 -- popped and executed.
543 -- The second entry corresponds to a standard new region action. A
544 -- PC_R_Remove node is stacked, whose cursor field is used to store
545 -- the outer stack base, and the stack base is reset to point to
546 -- this PC_R_Remove node. Then the recursive pattern is matched and
547 -- it can make history stack entries in the normal matter, so now
548 -- the stack looks like:
550 -- (stack entries made by outer level)
552 -- (Special entry, node is (+P) successor
553 -- cursor entry is not used)
555 -- (PC_R_Remove entry, "cursor" value is (negative) <-- Stack base
556 -- saved base value for the enclosing region)
558 -- (stack entries made by inner level)
560 -- If a subsequent failure occurs and pops the PC_R_Remove node, it
561 -- removes itself and the special entry immediately underneath it,
562 -- restores the stack base value for the enclosing region, and then
563 -- again signals failure to look for alternatives that were stacked
564 -- before the recursion was initiated.
566 -- Now we need to consider what happens if the inner pattern succeeds, as
567 -- signalled by accessing the special PC_EOP pattern primitive. First we
568 -- recognize the nested case by looking at the Base value. If this Base
569 -- value is Stack'First, then the entire match has succeeded, but if the
570 -- base value is greater than Stack'First, then we have successfully
571 -- matched an inner pattern, and processing continues at the outer level.
573 -- There are two cases. The simple case is when the inner pattern has made
574 -- no stack entries, as recognized by the fact that the current stack
575 -- pointer is equal to the current base value. In this case it is fine to
576 -- remove all trace of the recursion by restoring the outer base value and
577 -- using the special entry to find the appropriate successor node.
579 -- The more complex case arises when the inner match does make stack
580 -- entries. In this case, the PC_EOP processing stacks a special entry
581 -- whose cursor value saves the saved inner base value (the one that
582 -- references the corresponding PC_R_Remove value), and whose node
583 -- pointer references a PC_R_Restore node, so the stack looks like:
585 -- (stack entries made by outer level)
587 -- (Special entry, node is (+P) successor,
588 -- cursor entry is not used)
590 -- (PC_R_Remove entry, "cursor" value is (negative)
591 -- saved base value for the enclosing region)
593 -- (stack entries made by inner level)
595 -- (PC_Region_Replace entry, "cursor" value is (negative)
596 -- stack pointer value referencing the PC_R_Remove entry).
598 -- If the entire match succeeds, then these stack entries are, as usual,
599 -- ignored and abandoned. If on the other hand a subsequent failure
600 -- causes the PC_Region_Replace entry to be popped, it restores the
601 -- inner base value from its saved "cursor" value and then fails again.
602 -- Note that it is OK that the cursor is temporarily clobbered by this
603 -- pop, since the second failure will reestablish a proper cursor value.
605 ---------------------------------
606 -- Compound Pattern Structures --
607 ---------------------------------
609 -- This section discusses the compound structures used to represent
610 -- constructed patterns. It shows the graph structures of pattern
611 -- elements that are constructed, and in the case of patterns that
612 -- provide backtracking possibilities, describes how the history
613 -- stack is used to control the backtracking. Finally, it notes the
614 -- way in which the Index numbers are assigned to the structure.
616 -- In all diagrams, solid lines (built with minus signs or vertical
617 -- bars, represent successor pointers (Pthen fields) with > or V used
618 -- to indicate the direction of the pointer. The initial node of the
619 -- structure is in the upper left of the diagram. A dotted line is an
620 -- alternative pointer from the element above it to the element below
621 -- it. See individual sections for details on how alternatives are used.
627 -- In the pattern structures listed in this section, a line that looks
628 -- like ----> with nothing to the right indicates an end of pattern
629 -- (EOP) pointer that represents the end of the match.
631 -- When a pattern concatenation (L & R) occurs, the resulting structure
632 -- is obtained by finding all such EOP pointers in L, and replacing
633 -- them to point to R. This is the most important flattening that
634 -- occurs in constructing a pattern, and it means that the pattern
635 -- matching circuitry does not have to keep track of the structure
636 -- of a pattern with respect to concatenation, since the appropriate
637 -- successor is always at hand.
639 -- Concatenation itself generates no additional possibilities for
640 -- backtracking, but the constituent patterns of the concatenated
641 -- structure will make stack entries as usual. The maximum amount
642 -- of stack required by the structure is thus simply the sum of the
643 -- maximums required by L and R.
645 -- The index numbering of a concatenation structure works by leaving
646 -- the numbering of the right hand pattern, R, unchanged and adjusting
647 -- the numbers in the left hand pattern, L up by the count of elements
648 -- in R. This ensures that the maximum numbered element is the leading
649 -- element as required (given that it was the leading element in L).
655 -- A pattern (L or R) constructs the structure:
658 -- | A |---->| L |---->
666 -- The A element here is a PC_Alt node, and the dotted line represents
667 -- the contents of the Alt field. When the PC_Alt element is matched,
668 -- it stacks a pointer to the leading element of R on the history stack
669 -- so that on subsequent failure, a match of R is attempted.
671 -- The A node is the highest numbered element in the pattern. The
672 -- original index numbers of R are unchanged, but the index numbers
673 -- of the L pattern are adjusted up by the count of elements in R.
675 -- Note that the difference between the index of the L leading element
676 -- the index of the R leading element (after building the alt structure)
677 -- indicates the number of nodes in L, and this is true even after the
678 -- structure is incorporated into some larger structure. For example,
679 -- if the A node has index 16, and L has index 15 and R has index
680 -- 5, then we know that L has 10 (15-5) elements in it.
682 -- Suppose that we now concatenate this structure to another pattern
683 -- with 9 elements in it. We will now have the A node with an index
684 -- of 25, L with an index of 24 and R with an index of 14. We still
685 -- know that L has 10 (24-14) elements in it, numbered 15-24, and
686 -- consequently the successor of the alternation structure has an
687 -- index with a value less than 15. This is used in Image to figure
688 -- out the original recursive structure of a pattern.
690 -- To clarify the interaction of the alternation and concatenation
691 -- structures, here is a more complex example of the structure built
694 -- (V or W or X) (Y or Z)
696 -- where A,B,C,D,E are all single element patterns:
698 -- +---+ +---+ +---+ +---+
699 -- I A I---->I V I---+-->I A I---->I Y I---->
700 -- +---+ +---+ I +---+ +---+
703 -- +---+ +---+ I +---+
704 -- I A I---->I W I-->I I Z I---->
705 -- +---+ +---+ I +---+
709 -- I X I------------>+
712 -- The numbering of the nodes would be as follows:
714 -- +---+ +---+ +---+ +---+
715 -- I 8 I---->I 7 I---+-->I 3 I---->I 2 I---->
716 -- +---+ +---+ I +---+ +---+
719 -- +---+ +---+ I +---+
720 -- I 6 I---->I 5 I-->I I 1 I---->
721 -- +---+ +---+ I +---+
725 -- I 4 I------------>+
728 -- Note: The above structure actually corresponds to
730 -- (A or (B or C)) (D or E)
734 -- ((A or B) or C) (D or E)
736 -- which is the more natural interpretation, but in fact alternation
737 -- is associative, and the construction of an alternative changes the
738 -- left grouped pattern to the right grouped pattern in any case, so
739 -- that the Image function produces a more natural looking output.
745 -- An Arb pattern builds the structure
756 -- The X node is a PC_Arb_X node, which matches null, and stacks a
757 -- pointer to Y node, which is the PC_Arb_Y node that matches one
758 -- extra character and restacks itself.
760 -- The PC_Arb_X node is numbered 2, and the PC_Arb_Y node is 1
762 -------------------------
763 -- Arbno (simple case) --
764 -------------------------
766 -- The simple form of Arbno can be used where the pattern always
767 -- matches at least one character if it succeeds, and it is known
768 -- not to make any history stack entries. In this case, Arbno (P)
769 -- can construct the following structure:
783 -- The S (PC_Arbno_S) node matches null stacking a pointer to the
784 -- pattern P. If a subsequent failure causes P to be matched and
785 -- this match succeeds, then node A gets restacked to try another
786 -- instance if needed by a subsequent failure.
788 -- The node numbering of the constituent pattern P is not affected.
789 -- The S node has a node number of P.Index + 1.
791 --------------------------
792 -- Arbno (complex case) --
793 --------------------------
795 -- A call to Arbno (P), where P can match null (or at least is not
796 -- known to require a non-null string) and/or P requires pattern stack
797 -- entries, constructs the following structure:
799 -- +--------------------------+
807 -- +---+ +---+ +---+ |
808 -- | E |---->| P |---->| Y |--->+
811 -- The node X (PC_Arbno_X) matches null, stacking a pointer to the
812 -- E-P-X structure used to match one Arbno instance.
814 -- Here E is the PC_R_Enter node which matches null and creates two
815 -- stack entries. The first is a special entry whose node field is
816 -- not used at all, and whose cursor field has the initial cursor.
818 -- The second entry corresponds to a standard new region action. A
819 -- PC_R_Remove node is stacked, whose cursor field is used to store
820 -- the outer stack base, and the stack base is reset to point to
821 -- this PC_R_Remove node. Then the pattern P is matched, and it can
822 -- make history stack entries in the normal manner, so now the stack
825 -- (stack entries made before assign pattern)
827 -- (Special entry, node field not used,
828 -- used only to save initial cursor)
830 -- (PC_R_Remove entry, "cursor" value is (negative) <-- Stack Base
831 -- saved base value for the enclosing region)
833 -- (stack entries made by matching P)
835 -- If the match of P fails, then the PC_R_Remove entry is popped and
836 -- it removes both itself and the special entry underneath it,
837 -- restores the outer stack base, and signals failure.
839 -- If the match of P succeeds, then node Y, the PC_Arbno_Y node, pops
840 -- the inner region. There are two possibilities. If matching P left
841 -- no stack entries, then all traces of the inner region can be removed.
842 -- If there are stack entries, then we push an PC_Region_Replace stack
843 -- entry whose "cursor" value is the inner stack base value, and then
844 -- restore the outer stack base value, so the stack looks like:
846 -- (stack entries made before assign pattern)
848 -- (Special entry, node field not used,
849 -- used only to save initial cursor)
851 -- (PC_R_Remove entry, "cursor" value is (negative)
852 -- saved base value for the enclosing region)
854 -- (stack entries made by matching P)
856 -- (PC_Region_Replace entry, "cursor" value is (negative)
857 -- stack pointer value referencing the PC_R_Remove entry).
859 -- Now that we have matched another instance of the Arbno pattern,
860 -- we need to move to the successor. There are two cases. If the
861 -- Arbno pattern matched null, then there is no point in seeking
862 -- alternatives, since we would just match a whole bunch of nulls.
863 -- In this case we look through the alternative node, and move
864 -- directly to its successor (i.e. the successor of the Arbno
865 -- pattern). If on the other hand a non-null string was matched,
866 -- we simply follow the successor to the alternative node, which
867 -- sets up for another possible match of the Arbno pattern.
869 -- As noted in the section on stack checking, the stack count (and
870 -- hence the stack check) for a pattern includes only one iteration
871 -- of the Arbno pattern. To make sure that multiple iterations do not
872 -- overflow the stack, the Arbno node saves the stack count required
873 -- by a single iteration, and the Concat function increments this to
874 -- include stack entries required by any successor. The PC_Arbno_Y
875 -- node uses this count to ensure that sufficient stack remains
876 -- before proceeding after matching each new instance.
878 -- The node numbering of the constituent pattern P is not affected.
879 -- Where N is the number of nodes in P, the Y node is numbered N + 1,
880 -- the E node is N + 2, and the X node is N + 3.
882 ----------------------
883 -- Assign Immediate --
884 ----------------------
886 -- Immediate assignment (P * V) constructs the following structure
889 -- | E |---->| P |---->| A |---->
892 -- Here E is the PC_R_Enter node which matches null and creates two
893 -- stack entries. The first is a special entry whose node field is
894 -- not used at all, and whose cursor field has the initial cursor.
896 -- The second entry corresponds to a standard new region action. A
897 -- PC_R_Remove node is stacked, whose cursor field is used to store
898 -- the outer stack base, and the stack base is reset to point to
899 -- this PC_R_Remove node. Then the pattern P is matched, and it can
900 -- make history stack entries in the normal manner, so now the stack
903 -- (stack entries made before assign pattern)
905 -- (Special entry, node field not used,
906 -- used only to save initial cursor)
908 -- (PC_R_Remove entry, "cursor" value is (negative) <-- Stack Base
909 -- saved base value for the enclosing region)
911 -- (stack entries made by matching P)
913 -- If the match of P fails, then the PC_R_Remove entry is popped
914 -- and it removes both itself and the special entry underneath it,
915 -- restores the outer stack base, and signals failure.
917 -- If the match of P succeeds, then node A, which is the actual
918 -- PC_Assign_Imm node, executes the assignment (using the stack
919 -- base to locate the entry with the saved starting cursor value),
920 -- and the pops the inner region. There are two possibilities, if
921 -- matching P left no stack entries, then all traces of the inner
922 -- region can be removed. If there are stack entries, then we push
923 -- an PC_Region_Replace stack entry whose "cursor" value is the
924 -- inner stack base value, and then restore the outer stack base
925 -- value, so the stack looks like:
927 -- (stack entries made before assign pattern)
929 -- (Special entry, node field not used,
930 -- used only to save initial cursor)
932 -- (PC_R_Remove entry, "cursor" value is (negative)
933 -- saved base value for the enclosing region)
935 -- (stack entries made by matching P)
937 -- (PC_Region_Replace entry, "cursor" value is the (negative)
938 -- stack pointer value referencing the PC_R_Remove entry).
940 -- If a subsequent failure occurs, the PC_Region_Replace node restores
941 -- the inner stack base value and signals failure to explore rematches
944 -- The node numbering of the constituent pattern P is not affected.
945 -- Where N is the number of nodes in P, the A node is numbered N + 1,
946 -- and the E node is N + 2.
948 ---------------------
949 -- Assign On Match --
950 ---------------------
952 -- The assign on match (**) pattern is quite similar to the assign
953 -- immediate pattern, except that the actual assignment has to be
954 -- delayed. The following structure is constructed:
957 -- | E |---->| P |---->| A |---->
960 -- The operation of this pattern is identical to that described above
961 -- for deferred assignment, up to the point where P has been matched.
963 -- The A node, which is the PC_Assign_OnM node first pushes a
964 -- PC_Assign node onto the history stack. This node saves the ending
965 -- cursor and acts as a flag for the final assignment, as further
968 -- It then stores a pointer to itself in the special entry node field.
969 -- This was otherwise unused, and is now used to retrieve the address
970 -- of the variable to be assigned at the end of the pattern.
972 -- After that the inner region is terminated in the usual manner,
973 -- by stacking a PC_R_Restore entry as described for the assign
974 -- immediate case. Note that the optimization of completely
975 -- removing the inner region does not happen in this case, since
976 -- we have at least one stack entry (the PC_Assign one we just made).
977 -- The stack now looks like:
979 -- (stack entries made before assign pattern)
981 -- (Special entry, node points to copy of
982 -- the PC_Assign_OnM node, and the
983 -- cursor field saves the initial cursor).
985 -- (PC_R_Remove entry, "cursor" value is (negative)
986 -- saved base value for the enclosing region)
988 -- (stack entries made by matching P)
990 -- (PC_Assign entry, saves final cursor)
992 -- (PC_Region_Replace entry, "cursor" value is (negative)
993 -- stack pointer value referencing the PC_R_Remove entry).
995 -- If a subsequent failure causes the PC_Assign node to execute it
996 -- simply removes itself and propagates the failure.
998 -- If the match succeeds, then the history stack is scanned for
999 -- PC_Assign nodes, and the assignments are executed (examination
1000 -- of the above diagram will show that all the necessary data is
1001 -- at hand for the assignment).
1003 -- To optimize the common case where no assign-on-match operations
1004 -- are present, a global flag Assign_OnM is maintained which is
1005 -- initialize to False, and gets set True as part of the execution
1006 -- of the PC_Assign_OnM node. The scan of the history stack for
1007 -- PC_Assign entries is done only if this flag is set.
1009 -- The node numbering of the constituent pattern P is not affected.
1010 -- Where N is the number of nodes in P, the A node is numbered N + 1,
1011 -- and the E node is N + 2.
1017 -- Bal builds a single node:
1023 -- The node B is the PC_Bal node which matches a parentheses balanced
1024 -- string, starting at the current cursor position. It then updates
1025 -- the cursor past this matched string, and stacks a pointer to itself
1026 -- with this updated cursor value on the history stack, to extend the
1027 -- matched string on a subsequent failure.
1029 -- Since this is a single node it is numbered 1 (the reason we include
1030 -- it in the compound patterns section is that it backtracks).
1036 -- BreakX builds the structure
1039 -- | B |---->| A |---->
1047 -- Here the B node is the BreakX_xx node that performs a normal Break
1048 -- function. The A node is an alternative (PC_Alt) node that matches
1049 -- null, but stacks a pointer to node X (the PC_BreakX_X node) which
1050 -- extends the match one character (to eat up the previously detected
1051 -- break character), and then rematches the break.
1053 -- The B node is numbered 3, the alternative node is 1, and the X
1060 -- Fence builds a single node:
1066 -- The element F, PC_Fence, matches null, and stacks a pointer to a
1067 -- PC_Cancel element which will abort the match on a subsequent failure.
1069 -- Since this is a single element it is numbered 1 (the reason we
1070 -- include it in the compound patterns section is that it backtracks).
1072 --------------------
1073 -- Fence Function --
1074 --------------------
1076 -- A call to the Fence function builds the structure:
1078 -- +---+ +---+ +---+
1079 -- | E |---->| P |---->| X |---->
1080 -- +---+ +---+ +---+
1082 -- Here E is the PC_R_Enter node which matches null and creates two
1083 -- stack entries. The first is a special entry which is not used at
1084 -- all in the fence case (it is present merely for uniformity with
1085 -- other cases of region enter operations).
1087 -- The second entry corresponds to a standard new region action. A
1088 -- PC_R_Remove node is stacked, whose cursor field is used to store
1089 -- the outer stack base, and the stack base is reset to point to
1090 -- this PC_R_Remove node. Then the pattern P is matched, and it can
1091 -- make history stack entries in the normal manner, so now the stack
1094 -- (stack entries made before fence pattern)
1096 -- (Special entry, not used at all)
1098 -- (PC_R_Remove entry, "cursor" value is (negative) <-- Stack Base
1099 -- saved base value for the enclosing region)
1101 -- (stack entries made by matching P)
1103 -- If the match of P fails, then the PC_R_Remove entry is popped
1104 -- and it removes both itself and the special entry underneath it,
1105 -- restores the outer stack base, and signals failure.
1107 -- If the match of P succeeds, then node X, the PC_Fence_X node, gets
1108 -- control. One might be tempted to think that at this point, the
1109 -- history stack entries made by matching P can just be removed since
1110 -- they certainly are not going to be used for rematching (that is
1111 -- whole point of Fence after all). However, this is wrong, because
1112 -- it would result in the loss of possible assign-on-match entries
1113 -- for deferred pattern assignments.
1115 -- Instead what we do is to make a special entry whose node references
1116 -- PC_Fence_Y, and whose cursor saves the inner stack base value, i.e.
1117 -- the pointer to the PC_R_Remove entry. Then the outer stack base
1118 -- pointer is restored, so the stack looks like:
1120 -- (stack entries made before assign pattern)
1122 -- (Special entry, not used at all)
1124 -- (PC_R_Remove entry, "cursor" value is (negative)
1125 -- saved base value for the enclosing region)
1127 -- (stack entries made by matching P)
1129 -- (PC_Fence_Y entry, "cursor" value is (negative) stack
1130 -- pointer value referencing the PC_R_Remove entry).
1132 -- If a subsequent failure occurs, then the PC_Fence_Y entry removes
1133 -- the entire inner region, including all entries made by matching P,
1134 -- and alternatives prior to the Fence pattern are sought.
1136 -- The node numbering of the constituent pattern P is not affected.
1137 -- Where N is the number of nodes in P, the X node is numbered N + 1,
1138 -- and the E node is N + 2.
1144 -- Succeed builds a single node:
1150 -- The node S is the PC_Succeed node which matches null, and stacks
1151 -- a pointer to itself on the history stack, so that a subsequent
1152 -- failure repeats the same match.
1154 -- Since this is a single node it is numbered 1 (the reason we include
1155 -- it in the compound patterns section is that it backtracks).
1157 ---------------------
1158 -- Write Immediate --
1159 ---------------------
1161 -- The structure built for a write immediate operation (P * F, where
1162 -- F is a file access value) is:
1164 -- +---+ +---+ +---+
1165 -- | E |---->| P |---->| W |---->
1166 -- +---+ +---+ +---+
1168 -- Here E is the PC_R_Enter node and W is the PC_Write_Imm node. The
1169 -- handling is identical to that described above for Assign Immediate,
1170 -- except that at the point where a successful match occurs, the matched
1171 -- substring is written to the referenced file.
1173 -- The node numbering of the constituent pattern P is not affected.
1174 -- Where N is the number of nodes in P, the W node is numbered N + 1,
1175 -- and the E node is N + 2.
1177 --------------------
1178 -- Write On Match --
1179 --------------------
1181 -- The structure built for a write on match operation (P ** F, where
1182 -- F is a file access value) is:
1184 -- +---+ +---+ +---+
1185 -- | E |---->| P |---->| W |---->
1186 -- +---+ +---+ +---+
1188 -- Here E is the PC_R_Enter node and W is the PC_Write_OnM node. The
1189 -- handling is identical to that described above for Assign On Match,
1190 -- except that at the point where a successful match has completed,
1191 -- the matched substring is written to the referenced file.
1193 -- The node numbering of the constituent pattern P is not affected.
1194 -- Where N is the number of nodes in P, the W node is numbered N + 1,
1195 -- and the E node is N + 2.
1196 -----------------------
1197 -- Constant Patterns --
1198 -----------------------
1200 -- The following pattern elements are referenced only from the pattern
1201 -- history stack. In each case the processing for the pattern element
1202 -- results in pattern match abort, or further failure, so there is no
1203 -- need for a successor and no need for a node number
1205 CP_Assign
: aliased PE
:= (PC_Assign
, 0, N
);
1206 CP_Cancel
: aliased PE
:= (PC_Cancel
, 0, N
);
1207 CP_Fence_Y
: aliased PE
:= (PC_Fence_Y
, 0, N
);
1208 CP_R_Remove
: aliased PE
:= (PC_R_Remove
, 0, N
);
1209 CP_R_Restore
: aliased PE
:= (PC_R_Restore
, 0, N
);
1211 -----------------------
1212 -- Local Subprograms --
1213 -----------------------
1215 function Alternate
(L
, R
: PE_Ptr
) return PE_Ptr
;
1216 function "or" (L
, R
: PE_Ptr
) return PE_Ptr
renames Alternate
;
1217 -- Build pattern structure corresponding to the alternation of L, R.
1218 -- (i.e. try to match L, and if that fails, try to match R).
1220 function Arbno_Simple
(P
: PE_Ptr
) return PE_Ptr
;
1221 -- Build simple Arbno pattern, P is a pattern that is guaranteed to
1222 -- match at least one character if it succeeds and to require no
1223 -- stack entries under all circumstances. The result returned is
1224 -- a simple Arbno structure as previously described.
1226 function Bracket
(E
, P
, A
: PE_Ptr
) return PE_Ptr
;
1227 -- Given two single node pattern elements E and A, and a (possible
1228 -- complex) pattern P, construct the concatenation E-->P-->A and
1229 -- return a pointer to E. The concatenation does not affect the
1230 -- node numbering in P. A has a number one higher than the maximum
1231 -- number in P, and E has a number two higher than the maximum
1232 -- number in P (see for example the Assign_Immediate structure to
1233 -- understand a typical use of this function).
1235 function BreakX_Make
(B
: PE_Ptr
) return Pattern
;
1236 -- Given a pattern element for a Break pattern, returns the
1237 -- corresponding BreakX compound pattern structure.
1239 function Concat
(L
, R
: PE_Ptr
; Incr
: Natural) return PE_Ptr
;
1240 -- Creates a pattern element that represents a concatenation of the
1241 -- two given pattern elements (i.e. the pattern L followed by R).
1242 -- The result returned is always the same as L, but the pattern
1243 -- referenced by L is modified to have R as a successor. This
1244 -- procedure does not copy L or R, so if a copy is required, it
1245 -- is the responsibility of the caller. The Incr parameter is an
1246 -- amount to be added to the Nat field of any P_Arbno_Y node that is
1247 -- in the left operand, it represents the additional stack space
1248 -- required by the right operand.
1250 function C_To_PE
(C
: PChar
) return PE_Ptr
;
1251 -- Given a character, constructs a pattern element that matches
1252 -- the single character.
1254 function Copy
(P
: PE_Ptr
) return PE_Ptr
;
1255 -- Creates a copy of the pattern element referenced by the given
1256 -- pattern element reference. This is a deep copy, which means that
1257 -- it follows the Next and Alt pointers.
1259 function Image
(P
: PE_Ptr
) return String;
1260 -- Returns the image of the address of the referenced pattern element.
1261 -- This is equivalent to Image (To_Address (P));
1263 function Is_In
(C
: Character; Str
: String) return Boolean;
1264 pragma Inline
(Is_In
);
1265 -- Determines if the character C is in string Str
1267 procedure Logic_Error
;
1268 -- Called to raise Program_Error with an appropriate message if an
1269 -- internal logic error is detected.
1271 function Str_BF
(A
: Boolean_Func
) return String;
1272 function Str_FP
(A
: File_Ptr
) return String;
1273 function Str_NF
(A
: Natural_Func
) return String;
1274 function Str_NP
(A
: Natural_Ptr
) return String;
1275 function Str_PP
(A
: Pattern_Ptr
) return String;
1276 function Str_VF
(A
: VString_Func
) return String;
1277 function Str_VP
(A
: VString_Ptr
) return String;
1278 -- These are debugging routines, which return a representation of the
1279 -- given access value (they are called only by Image and Dump)
1281 procedure Set_Successor
(Pat
: PE_Ptr
; Succ
: PE_Ptr
);
1282 -- Adjusts all EOP pointers in Pat to point to Succ. No other changes
1283 -- are made. In particular, Succ is unchanged, and no index numbers
1284 -- are modified. Note that Pat may not be equal to EOP on entry.
1286 function S_To_PE
(Str
: PString
) return PE_Ptr
;
1287 -- Given a string, constructs a pattern element that matches the string
1289 procedure Uninitialized_Pattern
;
1290 pragma No_Return
(Uninitialized_Pattern
);
1291 -- Called to raise Program_Error with an appropriate error message if
1292 -- an uninitialized pattern is used in any pattern construction or
1293 -- pattern matching operation.
1299 Start
: out Natural;
1300 Stop
: out Natural);
1301 -- This is the common pattern match routine. It is passed a string and
1302 -- a pattern, and it indicates success or failure, and on success the
1303 -- section of the string matched. It does not perform any assignments
1304 -- to the subject string, so pattern replacement is for the caller.
1306 -- Subject The subject string. The lower bound is always one. In the
1307 -- Match procedures, it is fine to use strings whose lower bound
1308 -- is not one, but we perform a one time conversion before the
1309 -- call to XMatch, so that XMatch does not have to be bothered
1310 -- with strange lower bounds.
1312 -- Pat_P Points to initial pattern element of pattern to be matched
1314 -- Pat_S Maximum required stack entries for pattern to be matched
1316 -- Start If match is successful, starting index of matched section.
1317 -- This value is always non-zero. A value of zero is used to
1318 -- indicate a failed match.
1320 -- Stop If match is successful, ending index of matched section.
1321 -- This can be zero if we match the null string at the start,
1322 -- in which case Start is set to zero, and Stop to one. If the
1323 -- Match fails, then the contents of Stop is undefined.
1329 Start
: out Natural;
1330 Stop
: out Natural);
1331 -- Identical in all respects to XMatch, except that trace information is
1332 -- output on Standard_Output during execution of the match. This is the
1333 -- version that is called if the original Match call has Debug => True.
1339 function "&" (L
: PString
; R
: Pattern
) return Pattern
is
1341 return (AFC
with R
.Stk
, Concat
(S_To_PE
(L
), Copy
(R
.P
), R
.Stk
));
1344 function "&" (L
: Pattern
; R
: PString
) return Pattern
is
1346 return (AFC
with L
.Stk
, Concat
(Copy
(L
.P
), S_To_PE
(R
), 0));
1349 function "&" (L
: PChar
; R
: Pattern
) return Pattern
is
1351 return (AFC
with R
.Stk
, Concat
(C_To_PE
(L
), Copy
(R
.P
), R
.Stk
));
1354 function "&" (L
: Pattern
; R
: PChar
) return Pattern
is
1356 return (AFC
with L
.Stk
, Concat
(Copy
(L
.P
), C_To_PE
(R
), 0));
1359 function "&" (L
: Pattern
; R
: Pattern
) return Pattern
is
1361 return (AFC
with L
.Stk
+ R
.Stk
, Concat
(Copy
(L
.P
), Copy
(R
.P
), R
.Stk
));
1370 -- +---+ +---+ +---+
1371 -- | E |---->| P |---->| A |---->
1372 -- +---+ +---+ +---+
1374 -- The node numbering of the constituent pattern P is not affected.
1375 -- Where N is the number of nodes in P, the A node is numbered N + 1,
1376 -- and the E node is N + 2.
1378 function "*" (P
: Pattern
; Var
: VString_Var
) return Pattern
is
1379 Pat
: constant PE_Ptr
:= Copy
(P
.P
);
1380 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1381 A : constant PE_Ptr :=
1382 new PE'(PC_Assign_Imm
, 0, EOP
, Var
'Unrestricted_Access);
1384 return (AFC
with P
.Stk
+ 3, Bracket
(E
, Pat
, A
));
1387 function "*" (P
: PString
; Var
: VString_Var
) return Pattern
is
1388 Pat
: constant PE_Ptr
:= S_To_PE
(P
);
1389 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1390 A : constant PE_Ptr :=
1391 new PE'(PC_Assign_Imm
, 0, EOP
, Var
'Unrestricted_Access);
1393 return (AFC
with 3, Bracket
(E
, Pat
, A
));
1396 function "*" (P
: PChar
; Var
: VString_Var
) return Pattern
is
1397 Pat
: constant PE_Ptr
:= C_To_PE
(P
);
1398 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1399 A : constant PE_Ptr :=
1400 new PE'(PC_Assign_Imm
, 0, EOP
, Var
'Unrestricted_Access);
1402 return (AFC
with 3, Bracket
(E
, Pat
, A
));
1407 -- +---+ +---+ +---+
1408 -- | E |---->| P |---->| W |---->
1409 -- +---+ +---+ +---+
1411 -- The node numbering of the constituent pattern P is not affected.
1412 -- Where N is the number of nodes in P, the W node is numbered N + 1,
1413 -- and the E node is N + 2.
1415 function "*" (P
: Pattern
; Fil
: File_Access
) return Pattern
is
1416 Pat
: constant PE_Ptr
:= Copy
(P
.P
);
1417 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1418 W : constant PE_Ptr := new PE'(PC_Write_Imm
, 0, EOP
, Fil
);
1420 return (AFC
with 3, Bracket
(E
, Pat
, W
));
1423 function "*" (P
: PString
; Fil
: File_Access
) return Pattern
is
1424 Pat
: constant PE_Ptr
:= S_To_PE
(P
);
1425 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1426 W : constant PE_Ptr := new PE'(PC_Write_Imm
, 0, EOP
, Fil
);
1428 return (AFC
with 3, Bracket
(E
, Pat
, W
));
1431 function "*" (P
: PChar
; Fil
: File_Access
) return Pattern
is
1432 Pat
: constant PE_Ptr
:= C_To_PE
(P
);
1433 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1434 W : constant PE_Ptr := new PE'(PC_Write_Imm
, 0, EOP
, Fil
);
1436 return (AFC
with 3, Bracket
(E
, Pat
, W
));
1445 -- +---+ +---+ +---+
1446 -- | E |---->| P |---->| A |---->
1447 -- +---+ +---+ +---+
1449 -- The node numbering of the constituent pattern P is not affected.
1450 -- Where N is the number of nodes in P, the A node is numbered N + 1,
1451 -- and the E node is N + 2.
1453 function "**" (P
: Pattern
; Var
: VString_Var
) return Pattern
is
1454 Pat
: constant PE_Ptr
:= Copy
(P
.P
);
1455 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1456 A : constant PE_Ptr :=
1457 new PE'(PC_Assign_OnM
, 0, EOP
, Var
'Unrestricted_Access);
1459 return (AFC
with P
.Stk
+ 3, Bracket
(E
, Pat
, A
));
1462 function "**" (P
: PString
; Var
: VString_Var
) return Pattern
is
1463 Pat
: constant PE_Ptr
:= S_To_PE
(P
);
1464 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1465 A : constant PE_Ptr :=
1466 new PE'(PC_Assign_OnM
, 0, EOP
, Var
'Unrestricted_Access);
1468 return (AFC
with 3, Bracket
(E
, Pat
, A
));
1471 function "**" (P
: PChar
; Var
: VString_Var
) return Pattern
is
1472 Pat
: constant PE_Ptr
:= C_To_PE
(P
);
1473 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1474 A : constant PE_Ptr :=
1475 new PE'(PC_Assign_OnM
, 0, EOP
, Var
'Unrestricted_Access);
1477 return (AFC
with 3, Bracket
(E
, Pat
, A
));
1482 -- +---+ +---+ +---+
1483 -- | E |---->| P |---->| W |---->
1484 -- +---+ +---+ +---+
1486 -- The node numbering of the constituent pattern P is not affected.
1487 -- Where N is the number of nodes in P, the W node is numbered N + 1,
1488 -- and the E node is N + 2.
1490 function "**" (P
: Pattern
; Fil
: File_Access
) return Pattern
is
1491 Pat
: constant PE_Ptr
:= Copy
(P
.P
);
1492 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1493 W : constant PE_Ptr := new PE'(PC_Write_OnM
, 0, EOP
, Fil
);
1495 return (AFC
with P
.Stk
+ 3, Bracket
(E
, Pat
, W
));
1498 function "**" (P
: PString
; Fil
: File_Access
) return Pattern
is
1499 Pat
: constant PE_Ptr
:= S_To_PE
(P
);
1500 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1501 W : constant PE_Ptr := new PE'(PC_Write_OnM
, 0, EOP
, Fil
);
1503 return (AFC
with 3, Bracket
(E
, Pat
, W
));
1506 function "**" (P
: PChar
; Fil
: File_Access
) return Pattern
is
1507 Pat
: constant PE_Ptr
:= C_To_PE
(P
);
1508 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
1509 W : constant PE_Ptr := new PE'(PC_Write_OnM
, 0, EOP
, Fil
);
1511 return (AFC
with 3, Bracket
(E
, Pat
, W
));
1518 function "+" (Str
: VString_Var
) return Pattern
is
1522 new PE
'(PC_String_VP, 1, EOP, Str'Unrestricted_Access));
1525 function "+" (Str : VString_Func) return Pattern is
1527 return (AFC with 0, new PE'(PC_String_VF
, 1, EOP
, Str
));
1530 function "+" (P
: Pattern_Var
) return Pattern
is
1534 new PE
'(PC_Rpat, 1, EOP, P'Unrestricted_Access));
1537 function "+" (P : Boolean_Func) return Pattern is
1539 return (AFC with 3, new PE'(PC_Pred_Func
, 1, EOP
, P
));
1546 function "or" (L
: PString
; R
: Pattern
) return Pattern
is
1548 return (AFC
with R
.Stk
+ 1, S_To_PE
(L
) or Copy
(R
.P
));
1551 function "or" (L
: Pattern
; R
: PString
) return Pattern
is
1553 return (AFC
with L
.Stk
+ 1, Copy
(L
.P
) or S_To_PE
(R
));
1556 function "or" (L
: PString
; R
: PString
) return Pattern
is
1558 return (AFC
with 1, S_To_PE
(L
) or S_To_PE
(R
));
1561 function "or" (L
: Pattern
; R
: Pattern
) return Pattern
is
1564 Natural'Max (L
.Stk
, R
.Stk
) + 1, Copy
(L
.P
) or Copy
(R
.P
));
1567 function "or" (L
: PChar
; R
: Pattern
) return Pattern
is
1569 return (AFC
with 1, C_To_PE
(L
) or Copy
(R
.P
));
1572 function "or" (L
: Pattern
; R
: PChar
) return Pattern
is
1574 return (AFC
with 1, Copy
(L
.P
) or C_To_PE
(R
));
1577 function "or" (L
: PChar
; R
: PChar
) return Pattern
is
1579 return (AFC
with 1, C_To_PE
(L
) or C_To_PE
(R
));
1582 function "or" (L
: PString
; R
: PChar
) return Pattern
is
1584 return (AFC
with 1, S_To_PE
(L
) or C_To_PE
(R
));
1587 function "or" (L
: PChar
; R
: PString
) return Pattern
is
1589 return (AFC
with 1, C_To_PE
(L
) or S_To_PE
(R
));
1596 -- No two patterns share the same pattern elements, so the adjust
1597 -- procedure for a Pattern assignment must do a deep copy of the
1598 -- pattern element structure.
1600 procedure Adjust
(Object
: in out Pattern
) is
1602 Object
.P
:= Copy
(Object
.P
);
1609 function Alternate
(L
, R
: PE_Ptr
) return PE_Ptr
is
1611 -- If the left pattern is null, then we just add the alternation
1612 -- node with an index one greater than the right hand pattern.
1615 return new PE
'(PC_Alt, R.Index + 1, EOP, R);
1617 -- If the left pattern is non-null, then build a reference vector
1618 -- for its elements, and adjust their index values to accommodate
1619 -- the right hand elements. Then add the alternation node.
1623 Refs : Ref_Array (1 .. L.Index);
1626 Build_Ref_Array (L, Refs);
1628 for J in Refs'Range loop
1629 Refs (J).Index := Refs (J).Index + R.Index;
1633 return new PE'(PC_Alt
, L
.Index
+ 1, L
, R
);
1641 function Any
(Str
: String) return Pattern
is
1643 return (AFC
with 0, new PE
'(PC_Any_CS, 1, EOP, To_Set (Str)));
1646 function Any (Str : VString) return Pattern is
1648 return Any (S (Str));
1651 function Any (Str : Character) return Pattern is
1653 return (AFC with 0, new PE'(PC_Any_CH
, 1, EOP
, Str
));
1656 function Any
(Str
: Character_Set
) return Pattern
is
1658 return (AFC
with 0, new PE
'(PC_Any_CS, 1, EOP, Str));
1661 function Any (Str : not null access VString) return Pattern is
1663 return (AFC with 0, new PE'(PC_Any_VP
, 1, EOP
, VString_Ptr
(Str
)));
1666 function Any
(Str
: VString_Func
) return Pattern
is
1668 return (AFC
with 0, new PE
'(PC_Any_VF, 1, EOP, Str));
1684 -- The PC_Arb_X element is numbered 2, and the PC_Arb_Y element is 1
1686 function Arb return Pattern is
1687 Y : constant PE_Ptr := new PE'(PC_Arb_Y
, 1, EOP
);
1688 X
: constant PE_Ptr
:= new PE
'(PC_Arb_X, 2, EOP, Y);
1690 return (AFC with 1, X);
1697 function Arbno (P : PString) return Pattern is
1699 if P'Length = 0 then
1700 return (AFC with 0, EOP);
1702 return (AFC with 0, Arbno_Simple (S_To_PE (P)));
1706 function Arbno (P : PChar) return Pattern is
1708 return (AFC with 0, Arbno_Simple (C_To_PE (P)));
1711 function Arbno (P : Pattern) return Pattern is
1712 Pat : constant PE_Ptr := Copy (P.P);
1716 and then OK_For_Simple_Arbno (Pat.Pcode)
1718 return (AFC with 0, Arbno_Simple (Pat));
1721 -- This is the complex case, either the pattern makes stack entries
1722 -- or it is possible for the pattern to match the null string (more
1723 -- accurately, we don't know that this is not the case).
1725 -- +--------------------------+
1733 -- +---+ +---+ +---+ |
1734 -- | E |---->| P |---->| Y |--->+
1735 -- +---+ +---+ +---+
1737 -- The node numbering of the constituent pattern P is not affected.
1738 -- Where N is the number of nodes in P, the Y node is numbered N + 1,
1739 -- the E node is N + 2, and the X node is N + 3.
1742 E : constant PE_Ptr := new PE'(PC_R_Enter
, 0, EOP
);
1743 X
: constant PE_Ptr
:= new PE
'(PC_Arbno_X, 0, EOP, E);
1744 Y : constant PE_Ptr := new PE'(PC_Arbno_Y
, 0, X
, P
.Stk
+ 3);
1745 EPY
: constant PE_Ptr
:= Bracket
(E
, Pat
, Y
);
1748 X
.Index
:= EPY
.Index
+ 1;
1749 return (AFC
with P
.Stk
+ 3, X
);
1766 -- | P |---------->+
1769 -- The node numbering of the constituent pattern P is not affected.
1770 -- The S node has a node number of P.Index + 1.
1772 -- Note that we know that P cannot be EOP, because a null pattern
1773 -- does not meet the requirements for simple Arbno.
1775 function Arbno_Simple
(P
: PE_Ptr
) return PE_Ptr
is
1776 S
: constant PE_Ptr
:= new PE
'(PC_Arbno_S, P.Index + 1, EOP, P);
1778 Set_Successor (P, S);
1786 function Bal return Pattern is
1788 return (AFC with 1, new PE'(PC_Bal
, 1, EOP
));
1795 function Bracket
(E
, P
, A
: PE_Ptr
) return PE_Ptr
is
1804 Set_Successor
(P
, A
);
1805 E
.Index
:= P
.Index
+ 2;
1806 A
.Index
:= P
.Index
+ 1;
1816 function Break
(Str
: String) return Pattern
is
1818 return (AFC
with 0, new PE
'(PC_Break_CS, 1, EOP, To_Set (Str)));
1821 function Break (Str : VString) return Pattern is
1823 return Break (S (Str));
1826 function Break (Str : Character) return Pattern is
1828 return (AFC with 0, new PE'(PC_Break_CH
, 1, EOP
, Str
));
1831 function Break
(Str
: Character_Set
) return Pattern
is
1833 return (AFC
with 0, new PE
'(PC_Break_CS, 1, EOP, Str));
1836 function Break (Str : not null access VString) return Pattern is
1839 new PE'(PC_Break_VP
, 1, EOP
, Str
.all'Unchecked_Access));
1842 function Break
(Str
: VString_Func
) return Pattern
is
1844 return (AFC
with 0, new PE
'(PC_Break_VF, 1, EOP, Str));
1851 function BreakX (Str : String) return Pattern is
1853 return BreakX_Make (new PE'(PC_BreakX_CS
, 3, N
, To_Set
(Str
)));
1856 function BreakX
(Str
: VString
) return Pattern
is
1858 return BreakX
(S
(Str
));
1861 function BreakX
(Str
: Character) return Pattern
is
1863 return BreakX_Make
(new PE
'(PC_BreakX_CH, 3, N, Str));
1866 function BreakX (Str : Character_Set) return Pattern is
1868 return BreakX_Make (new PE'(PC_BreakX_CS
, 3, N
, Str
));
1871 function BreakX
(Str
: not null access VString
) return Pattern
is
1873 return BreakX_Make
(new PE
'(PC_BreakX_VP, 3, N, VString_Ptr (Str)));
1876 function BreakX (Str : VString_Func) return Pattern is
1878 return BreakX_Make (new PE'(PC_BreakX_VF
, 3, N
, Str
));
1886 -- | B |---->| A |---->
1894 -- The B node is numbered 3, the alternative node is 1, and the X
1897 function BreakX_Make
(B
: PE_Ptr
) return Pattern
is
1898 X
: constant PE_Ptr
:= new PE
'(PC_BreakX_X, 2, B);
1899 A : constant PE_Ptr := new PE'(PC_Alt
, 1, EOP
, X
);
1902 return (AFC
with 2, B
);
1905 ---------------------
1906 -- Build_Ref_Array --
1907 ---------------------
1909 procedure Build_Ref_Array
(E
: PE_Ptr
; RA
: out Ref_Array
) is
1911 procedure Record_PE
(E
: PE_Ptr
);
1912 -- Record given pattern element if not already recorded in RA,
1913 -- and also record any referenced pattern elements recursively.
1919 procedure Record_PE
(E
: PE_Ptr
) is
1921 PutD
(" Record_PE called with PE_Ptr = " & Image
(E
));
1923 if E
= EOP
or else RA
(E
.Index
) /= null then
1924 Put_LineD
(", nothing to do");
1928 Put_LineD
(", recording" & IndexT
'Image (E
.Index
));
1930 Record_PE
(E
.Pthen
);
1932 if E
.Pcode
in PC_Has_Alt
then
1938 -- Start of processing for Build_Ref_Array
1942 Put_LineD
("Entering Build_Ref_Array");
1945 end Build_Ref_Array
;
1951 function C_To_PE
(C
: PChar
) return PE_Ptr
is
1953 return new PE
'(PC_Char, 1, EOP, C);
1960 function Cancel return Pattern is
1962 return (AFC with 0, new PE'(PC_Cancel
, 1, EOP
));
1969 -- Concat needs to traverse the left operand performing the following
1972 -- a) Any successor pointers (Pthen fields) that are set to EOP are
1973 -- reset to point to the second operand.
1975 -- b) Any PC_Arbno_Y node has its stack count field incremented
1976 -- by the parameter Incr provided for this purpose.
1978 -- d) Num fields of all pattern elements in the left operand are
1979 -- adjusted to include the elements of the right operand.
1981 -- Note: we do not use Set_Successor in the processing for Concat, since
1982 -- there is no point in doing two traversals, we may as well do everything
1983 -- at the same time.
1985 function Concat
(L
, R
: PE_Ptr
; Incr
: Natural) return PE_Ptr
is
1995 Refs
: Ref_Array
(1 .. L
.Index
);
1996 -- We build a reference array for L whose N'th element points to
1997 -- the pattern element of L whose original Index value is N.
2002 Build_Ref_Array
(L
, Refs
);
2004 for J
in Refs
'Range loop
2007 P
.Index
:= P
.Index
+ R
.Index
;
2009 if P
.Pcode
= PC_Arbno_Y
then
2010 P
.Nat
:= P
.Nat
+ Incr
;
2013 if P
.Pthen
= EOP
then
2017 if P
.Pcode
in PC_Has_Alt
and then P
.Alt
= EOP
then
2031 function Copy
(P
: PE_Ptr
) return PE_Ptr
is
2034 Uninitialized_Pattern
;
2038 Refs
: Ref_Array
(1 .. P
.Index
);
2039 -- References to elements in P, indexed by Index field
2041 Copy
: Ref_Array
(1 .. P
.Index
);
2042 -- Holds copies of elements of P, indexed by Index field
2047 Build_Ref_Array
(P
, Refs
);
2049 -- Now copy all nodes
2051 for J
in Refs
'Range loop
2052 Copy
(J
) := new PE
'(Refs (J).all);
2055 -- Adjust all internal references
2057 for J in Copy'Range loop
2060 -- Adjust successor pointer to point to copy
2062 if E.Pthen /= EOP then
2063 E.Pthen := Copy (E.Pthen.Index);
2066 -- Adjust Alt pointer if there is one to point to copy
2068 if E.Pcode in PC_Has_Alt and then E.Alt /= EOP then
2069 E.Alt := Copy (E.Alt.Index);
2072 -- Copy referenced string
2074 if E.Pcode = PC_String then
2075 E.Str := new String'(E
.Str
.all);
2079 return Copy
(P
.Index
);
2088 procedure Dump
(P
: Pattern
) is
2090 subtype Count
is Ada
.Text_IO
.Count
;
2092 -- Used to keep track of column in dump output
2094 Refs
: Ref_Array
(1 .. P
.P
.Index
);
2095 -- We build a reference array whose N'th element points to the
2096 -- pattern element whose Index value is N.
2098 Cols
: Natural := 2;
2099 -- Number of columns used for pattern numbers, minimum is 2
2103 procedure Write_Node_Id
(E
: PE_Ptr
);
2104 -- Writes out a string identifying the given pattern element
2110 procedure Write_Node_Id
(E
: PE_Ptr
) is
2115 for J
in 4 .. Cols
loop
2121 Str
: String (1 .. Cols
);
2122 N
: Natural := Natural (E
.Index
);
2127 for J
in reverse Str
'Range loop
2128 Str
(J
) := Character'Val (48 + N
mod 10);
2137 -- Start of processing for Dump
2141 Put
("Pattern Dump Output (pattern at " &
2143 ", S = " & Natural'Image (P
.Stk
) & ')');
2148 while Col
< Scol
loop
2154 -- If uninitialized pattern, dump line and we are done
2157 Put_Line
("Uninitialized pattern value");
2161 -- If null pattern, just dump it and we are all done
2164 Put_Line
("EOP (null pattern)");
2168 Build_Ref_Array
(P
.P
, Refs
);
2170 -- Set number of columns required for node numbers
2172 while 10 ** Cols
- 1 < Integer (P
.P
.Index
) loop
2176 -- Now dump the nodes in reverse sequence. We output them in reverse
2177 -- sequence since this corresponds to the natural order used to
2178 -- construct the patterns.
2180 for J
in reverse Refs
'Range loop
2183 Set_Col
(Count
(Cols
) + 4);
2186 Put
(Pattern_Code
'Image (E
.Pcode
));
2188 Set_Col
(21 + Count
(Cols
) + Address_Image_Length
);
2189 Write_Node_Id
(E
.Pthen
);
2190 Set_Col
(24 + 2 * Count
(Cols
) + Address_Image_Length
);
2198 Write_Node_Id
(E
.Alt
);
2201 Put
(Str_PP
(E
.PP
));
2203 when PC_Pred_Func
=>
2204 Put
(Str_BF
(E
.BF
));
2216 Put
(Str_VP
(E
.VP
));
2221 Put
(Str_FP
(E
.FP
));
2224 Put
(Image
(E
.Str
.all));
2227 Put
(Image
(E
.Str2
));
2230 Put
(Image
(E
.Str3
));
2233 Put
(Image
(E
.Str4
));
2236 Put
(Image
(E
.Str5
));
2239 Put
(Image
(E
.Str6
));
2242 Put
(Str_NP
(E
.Var
));
2252 Put
(''' & E
.Char
& ''');
2261 Put
('"' & To_Sequence
(E
.CS
) & '"');
2278 Put
(Str_NF
(E
.NF
));
2286 Put
(Str_NP
(E
.NP
));
2296 Put
(Str_VF
(E
.VF
));
2312 function Fail
return Pattern
is
2314 return (AFC
with 0, new PE
'(PC_Fail, 1, EOP));
2323 function Fence return Pattern is
2325 return (AFC with 1, new PE'(PC_Fence
, 1, EOP
));
2330 -- +---+ +---+ +---+
2331 -- | E |---->| P |---->| X |---->
2332 -- +---+ +---+ +---+
2334 -- The node numbering of the constituent pattern P is not affected.
2335 -- Where N is the number of nodes in P, the X node is numbered N + 1,
2336 -- and the E node is N + 2.
2338 function Fence
(P
: Pattern
) return Pattern
is
2339 Pat
: constant PE_Ptr
:= Copy
(P
.P
);
2340 E
: constant PE_Ptr
:= new PE
'(PC_R_Enter, 0, EOP);
2341 X : constant PE_Ptr := new PE'(PC_Fence_X
, 0, EOP
);
2343 return (AFC
with P
.Stk
+ 1, Bracket
(E
, Pat
, X
));
2350 procedure Finalize
(Object
: in out Pattern
) is
2352 procedure Free
is new Ada
.Unchecked_Deallocation
(PE
, PE_Ptr
);
2353 procedure Free
is new Ada
.Unchecked_Deallocation
(String, String_Ptr
);
2356 -- Nothing to do if already freed
2358 if Object
.P
= null then
2361 -- Otherwise we must free all elements
2365 Refs
: Ref_Array
(1 .. Object
.P
.Index
);
2366 -- References to elements in pattern to be finalized
2369 Build_Ref_Array
(Object
.P
, Refs
);
2371 for J
in Refs
'Range loop
2372 if Refs
(J
).Pcode
= PC_String
then
2373 Free
(Refs
(J
).Str
);
2388 function Image
(P
: PE_Ptr
) return String is
2390 return Image
(To_Address
(P
));
2393 function Image
(P
: Pattern
) return String is
2395 return S
(Image
(P
));
2398 function Image
(P
: Pattern
) return VString
is
2400 Kill_Ampersand
: Boolean := False;
2401 -- Set True to delete next & to be output to Result
2403 Result
: VString
:= Nul
;
2404 -- The result is accumulated here, using Append
2406 Refs
: Ref_Array
(1 .. P
.P
.Index
);
2407 -- We build a reference array whose N'th element points to the
2408 -- pattern element whose Index value is N.
2410 procedure Delete_Ampersand
;
2411 -- Deletes the ampersand at the end of Result
2413 procedure Image_Seq
(E
: PE_Ptr
; Succ
: PE_Ptr
; Paren
: Boolean);
2414 -- E refers to a pattern structure whose successor is given by Succ.
2415 -- This procedure appends to Result a representation of this pattern.
2416 -- The Paren parameter indicates whether parentheses are required if
2417 -- the output is more than one element.
2419 procedure Image_One
(E
: in out PE_Ptr
);
2420 -- E refers to a pattern structure. This procedure appends to Result
2421 -- a representation of the single simple or compound pattern structure
2422 -- at the start of E and updates E to point to its successor.
2424 ----------------------
2425 -- Delete_Ampersand --
2426 ----------------------
2428 procedure Delete_Ampersand
is
2429 L
: constant Natural := Length
(Result
);
2432 Delete
(Result
, L
- 1, L
);
2434 end Delete_Ampersand
;
2440 procedure Image_One
(E
: in out PE_Ptr
) is
2442 ER
: PE_Ptr
:= E
.Pthen
;
2443 -- Successor set as result in E unless reset
2448 Append
(Result
, "Cancel");
2450 when PC_Alt
=> Alt
: declare
2452 Elmts_In_L
: constant IndexT
:= E
.Pthen
.Index
- E
.Alt
.Index
;
2453 -- Number of elements in left pattern of alternation
2455 Lowest_In_L
: constant IndexT
:= E
.Index
- Elmts_In_L
;
2456 -- Number of lowest index in elements of left pattern
2461 -- The successor of the alternation node must have a lower
2462 -- index than any node that is in the left pattern or a
2463 -- higher index than the alternation node itself.
2466 and then ER
.Index
>= Lowest_In_L
2467 and then ER
.Index
< E
.Index
2472 Append
(Result
, '(');
2476 Image_Seq
(E1
.Pthen
, ER
, False);
2477 Append
(Result
, " or ");
2479 exit when E1
.Pcode
/= PC_Alt
;
2482 Image_Seq
(E1
, ER
, False);
2483 Append
(Result
, ')');
2487 Append
(Result
, "Any (" & Image
(To_Sequence
(E
.CS
)) & ')');
2490 Append
(Result
, "Any (" & Str_VF
(E
.VF
) & ')');
2493 Append
(Result
, "Any (" & Str_VP
(E
.VP
) & ')');
2496 Append
(Result
, "Arb");
2499 Append
(Result
, "Arbno (");
2500 Image_Seq
(E
.Alt
, E
, False);
2501 Append
(Result
, ')');
2504 Append
(Result
, "Arbno (");
2505 Image_Seq
(E
.Alt
.Pthen
, Refs
(E
.Index
- 2), False);
2506 Append
(Result
, ')');
2508 when PC_Assign_Imm
=>
2510 Append
(Result
, "* " & Str_VP
(Refs
(E
.Index
).VP
));
2512 when PC_Assign_OnM
=>
2514 Append
(Result
, "** " & Str_VP
(Refs
(E
.Index
).VP
));
2517 Append
(Result
, "Any ('" & E
.Char
& "')");
2520 Append
(Result
, "Bal");
2523 Append
(Result
, "Break ('" & E
.Char
& "')");
2526 Append
(Result
, "Break (" & Image
(To_Sequence
(E
.CS
)) & ')');
2529 Append
(Result
, "Break (" & Str_VF
(E
.VF
) & ')');
2532 Append
(Result
, "Break (" & Str_VP
(E
.VP
) & ')');
2534 when PC_BreakX_CH
=>
2535 Append
(Result
, "BreakX ('" & E
.Char
& "')");
2538 when PC_BreakX_CS
=>
2539 Append
(Result
, "BreakX (" & Image
(To_Sequence
(E
.CS
)) & ')');
2542 when PC_BreakX_VF
=>
2543 Append
(Result
, "BreakX (" & Str_VF
(E
.VF
) & ')');
2546 when PC_BreakX_VP
=>
2547 Append
(Result
, "BreakX (" & Str_VP
(E
.VP
) & ')');
2551 Append
(Result
, ''' & E
.Char
& ''');
2554 Append
(Result
, "Fail");
2557 Append
(Result
, "Fence");
2560 Append
(Result
, "Fence (");
2561 Image_Seq
(E
.Pthen
, Refs
(E
.Index
- 1), False);
2562 Append
(Result
, ")");
2563 ER
:= Refs
(E
.Index
- 1).Pthen
;
2566 Append
(Result
, "Len (" & E
.Nat
& ')');
2569 Append
(Result
, "Len (" & Str_NF
(E
.NF
) & ')');
2572 Append
(Result
, "Len (" & Str_NP
(E
.NP
) & ')');
2574 when PC_NotAny_CH
=>
2575 Append
(Result
, "NotAny ('" & E
.Char
& "')");
2577 when PC_NotAny_CS
=>
2578 Append
(Result
, "NotAny (" & Image
(To_Sequence
(E
.CS
)) & ')');
2580 when PC_NotAny_VF
=>
2581 Append
(Result
, "NotAny (" & Str_VF
(E
.VF
) & ')');
2583 when PC_NotAny_VP
=>
2584 Append
(Result
, "NotAny (" & Str_VP
(E
.VP
) & ')');
2587 Append
(Result
, "NSpan ('" & E
.Char
& "')");
2590 Append
(Result
, "NSpan (" & Image
(To_Sequence
(E
.CS
)) & ')');
2593 Append
(Result
, "NSpan (" & Str_VF
(E
.VF
) & ')');
2596 Append
(Result
, "NSpan (" & Str_VP
(E
.VP
) & ')');
2599 Append
(Result
, """""");
2602 Append
(Result
, "Pos (" & E
.Nat
& ')');
2605 Append
(Result
, "Pos (" & Str_NF
(E
.NF
) & ')');
2608 Append
(Result
, "Pos (" & Str_NP
(E
.NP
) & ')');
2611 Kill_Ampersand
:= True;
2614 Append
(Result
, "Rest");
2617 Append
(Result
, "(+ " & Str_PP
(E
.PP
) & ')');
2619 when PC_Pred_Func
=>
2620 Append
(Result
, "(+ " & Str_BF
(E
.BF
) & ')');
2623 Append
(Result
, "RPos (" & E
.Nat
& ')');
2626 Append
(Result
, "RPos (" & Str_NF
(E
.NF
) & ')');
2629 Append
(Result
, "RPos (" & Str_NP
(E
.NP
) & ')');
2632 Append
(Result
, "RTab (" & E
.Nat
& ')');
2635 Append
(Result
, "RTab (" & Str_NF
(E
.NF
) & ')');
2638 Append
(Result
, "RTab (" & Str_NP
(E
.NP
) & ')');
2641 Append
(Result
, "Setcur (" & Str_NP
(E
.Var
) & ')');
2644 Append
(Result
, "Span ('" & E
.Char
& "')");
2647 Append
(Result
, "Span (" & Image
(To_Sequence
(E
.CS
)) & ')');
2650 Append
(Result
, "Span (" & Str_VF
(E
.VF
) & ')');
2653 Append
(Result
, "Span (" & Str_VP
(E
.VP
) & ')');
2656 Append
(Result
, Image
(E
.Str
.all));
2659 Append
(Result
, Image
(E
.Str2
));
2662 Append
(Result
, Image
(E
.Str3
));
2665 Append
(Result
, Image
(E
.Str4
));
2668 Append
(Result
, Image
(E
.Str5
));
2671 Append
(Result
, Image
(E
.Str6
));
2673 when PC_String_VF
=>
2674 Append
(Result
, "(+" & Str_VF
(E
.VF
) & ')');
2676 when PC_String_VP
=>
2677 Append
(Result
, "(+" & Str_VP
(E
.VP
) & ')');
2680 Append
(Result
, "Succeed");
2683 Append
(Result
, "Tab (" & E
.Nat
& ')');
2686 Append
(Result
, "Tab (" & Str_NF
(E
.NF
) & ')');
2689 Append
(Result
, "Tab (" & Str_NP
(E
.NP
) & ')');
2691 when PC_Write_Imm
=>
2692 Append
(Result
, '(');
2693 Image_Seq
(E
, Refs
(E
.Index
- 1), True);
2694 Append
(Result
, " * " & Str_FP
(Refs
(E
.Index
- 1).FP
));
2695 ER
:= Refs
(E
.Index
- 1).Pthen
;
2697 when PC_Write_OnM
=>
2698 Append
(Result
, '(');
2699 Image_Seq
(E
.Pthen
, Refs
(E
.Index
- 1), True);
2700 Append
(Result
, " ** " & Str_FP
(Refs
(E
.Index
- 1).FP
));
2701 ER
:= Refs
(E
.Index
- 1).Pthen
;
2703 -- Other pattern codes should not appear as leading elements
2715 Append
(Result
, "???");
2725 procedure Image_Seq
(E
: PE_Ptr
; Succ
: PE_Ptr
; Paren
: Boolean) is
2726 Indx
: constant Natural := Length
(Result
);
2728 Mult
: Boolean := False;
2731 -- The image of EOP is "" (the null string)
2734 Append
(Result
, """""");
2736 -- Else generate appropriate concatenation sequence
2741 exit when E1
= Succ
;
2745 if Kill_Ampersand
then
2746 Kill_Ampersand
:= False;
2748 Append
(Result
, " & ");
2753 if Mult
and Paren
then
2754 Insert
(Result
, Indx
+ 1, "(");
2755 Append
(Result
, ")");
2759 -- Start of processing for Image
2762 Build_Ref_Array
(P
.P
, Refs
);
2763 Image_Seq
(P
.P
, EOP
, False);
2771 function Is_In
(C
: Character; Str
: String) return Boolean is
2773 for J
in Str
'Range loop
2786 function Len
(Count
: Natural) return Pattern
is
2788 -- Note, the following is not just an optimization, it is needed
2789 -- to ensure that Arbno (Len (0)) does not generate an infinite
2790 -- matching loop (since PC_Len_Nat is OK_For_Simple_Arbno).
2793 return (AFC
with 0, new PE
'(PC_Null, 1, EOP));
2796 return (AFC with 0, new PE'(PC_Len_Nat
, 1, EOP
, Count
));
2800 function Len
(Count
: Natural_Func
) return Pattern
is
2802 return (AFC
with 0, new PE
'(PC_Len_NF, 1, EOP, Count));
2805 function Len (Count : not null access Natural) return Pattern is
2807 return (AFC with 0, new PE'(PC_Len_NP
, 1, EOP
, Natural_Ptr
(Count
)));
2814 procedure Logic_Error
is
2816 raise Program_Error
with
2817 "Internal logic error in GNAT.Spitbol.Patterns";
2826 Pat
: Pattern
) return Boolean
2828 S
: Big_String_Access
;
2832 pragma Unreferenced
(Stop
);
2835 Get_String
(Subject
, S
, L
);
2838 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2840 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2848 Pat
: Pattern
) return Boolean
2850 Start
, Stop
: Natural;
2851 pragma Unreferenced
(Stop
);
2853 subtype String1
is String (1 .. Subject
'Length);
2857 XMatchD
(String1
(Subject
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2859 XMatch
(String1
(Subject
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2866 (Subject
: VString_Var
;
2868 Replace
: VString
) return Boolean
2872 S
: Big_String_Access
;
2876 Get_String
(Subject
, S
, L
);
2879 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2881 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2887 Get_String
(Replace
, S
, L
);
2889 (Subject
'Unrestricted_Access.all, Start
, Stop
, S
(1 .. L
));
2895 (Subject
: VString_Var
;
2897 Replace
: String) return Boolean
2901 S
: Big_String_Access
;
2905 Get_String
(Subject
, S
, L
);
2908 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2910 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2917 (Subject
'Unrestricted_Access.all, Start
, Stop
, Replace
);
2926 S
: Big_String_Access
;
2931 pragma Unreferenced
(Start
, Stop
);
2934 Get_String
(Subject
, S
, L
);
2937 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2939 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2947 Start
, Stop
: Natural;
2948 pragma Unreferenced
(Start
, Stop
);
2950 subtype String1
is String (1 .. Subject
'Length);
2954 XMatchD
(String1
(Subject
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2956 XMatch
(String1
(Subject
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2961 (Subject
: in out VString
;
2967 S
: Big_String_Access
;
2971 Get_String
(Subject
, S
, L
);
2974 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2976 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
2980 Get_String
(Replace
, S
, L
);
2981 Replace_Slice
(Subject
, Start
, Stop
, S
(1 .. L
));
2986 (Subject
: in out VString
;
2992 S
: Big_String_Access
;
2996 Get_String
(Subject
, S
, L
);
2999 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
3001 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
3005 Replace_Slice
(Subject
, Start
, Stop
, Replace
);
3011 Pat
: PString
) return Boolean
3013 Pat_Len
: constant Natural := Pat
'Length;
3014 S
: Big_String_Access
;
3018 Get_String
(Subject
, S
, L
);
3020 if Anchored_Mode
then
3024 return Pat
= S
(1 .. Pat_Len
);
3028 for J
in 1 .. L
- Pat_Len
+ 1 loop
3029 if Pat
= S
(J
.. J
+ (Pat_Len
- 1)) then
3040 Pat
: PString
) return Boolean
3042 Pat_Len
: constant Natural := Pat
'Length;
3043 Sub_Len
: constant Natural := Subject
'Length;
3044 SFirst
: constant Natural := Subject
'First;
3047 if Anchored_Mode
then
3048 if Pat_Len
> Sub_Len
then
3051 return Pat
= Subject
(SFirst
.. SFirst
+ Pat_Len
- 1);
3055 for J
in SFirst
.. SFirst
+ Sub_Len
- Pat_Len
loop
3056 if Pat
= Subject
(J
.. J
+ (Pat_Len
- 1)) then
3066 (Subject
: VString_Var
;
3068 Replace
: VString
) return Boolean
3072 S
: Big_String_Access
;
3076 Get_String
(Subject
, S
, L
);
3079 XMatchD
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3081 XMatch
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3087 Get_String
(Replace
, S
, L
);
3089 (Subject
'Unrestricted_Access.all, Start
, Stop
, S
(1 .. L
));
3095 (Subject
: VString_Var
;
3097 Replace
: String) return Boolean
3101 S
: Big_String_Access
;
3105 Get_String
(Subject
, S
, L
);
3108 XMatchD
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3110 XMatch
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3117 (Subject
'Unrestricted_Access.all, Start
, Stop
, Replace
);
3126 S
: Big_String_Access
;
3131 pragma Unreferenced
(Start
, Stop
);
3134 Get_String
(Subject
, S
, L
);
3137 XMatchD
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3139 XMatch
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3147 Start
, Stop
: Natural;
3148 pragma Unreferenced
(Start
, Stop
);
3150 subtype String1
is String (1 .. Subject
'Length);
3154 XMatchD
(String1
(Subject
), S_To_PE
(Pat
), 0, Start
, Stop
);
3156 XMatch
(String1
(Subject
), S_To_PE
(Pat
), 0, Start
, Stop
);
3161 (Subject
: in out VString
;
3167 S
: Big_String_Access
;
3171 Get_String
(Subject
, S
, L
);
3174 XMatchD
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3176 XMatch
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3180 Get_String
(Replace
, S
, L
);
3181 Replace_Slice
(Subject
, Start
, Stop
, S
(1 .. L
));
3186 (Subject
: in out VString
;
3192 S
: Big_String_Access
;
3196 Get_String
(Subject
, S
, L
);
3199 XMatchD
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3201 XMatch
(S
(1 .. L
), S_To_PE
(Pat
), 0, Start
, Stop
);
3205 Replace_Slice
(Subject
, Start
, Stop
, Replace
);
3210 (Subject
: VString_Var
;
3212 Result
: Match_Result_Var
) return Boolean
3216 S
: Big_String_Access
;
3220 Get_String
(Subject
, S
, L
);
3223 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
3225 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
3229 Result
'Unrestricted_Access.all.Var
:= null;
3233 Result
'Unrestricted_Access.all.Var
:= Subject
'Unrestricted_Access;
3234 Result
'Unrestricted_Access.all.Start
:= Start
;
3235 Result
'Unrestricted_Access.all.Stop
:= Stop
;
3241 (Subject
: in out VString
;
3243 Result
: out Match_Result
)
3247 S
: Big_String_Access
;
3251 Get_String
(Subject
, S
, L
);
3254 XMatchD
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
3256 XMatch
(S
(1 .. L
), Pat
.P
, Pat
.Stk
, Start
, Stop
);
3262 Result
.Var
:= Subject
'Unrestricted_Access;
3263 Result
.Start
:= Start
;
3264 Result
.Stop
:= Stop
;
3272 procedure New_LineD
is
3274 if Internal_Debug
then
3283 function NotAny
(Str
: String) return Pattern
is
3285 return (AFC
with 0, new PE
'(PC_NotAny_CS, 1, EOP, To_Set (Str)));
3288 function NotAny (Str : VString) return Pattern is
3290 return NotAny (S (Str));
3293 function NotAny (Str : Character) return Pattern is
3295 return (AFC with 0, new PE'(PC_NotAny_CH
, 1, EOP
, Str
));
3298 function NotAny
(Str
: Character_Set
) return Pattern
is
3300 return (AFC
with 0, new PE
'(PC_NotAny_CS, 1, EOP, Str));
3303 function NotAny (Str : not null access VString) return Pattern is
3305 return (AFC with 0, new PE'(PC_NotAny_VP
, 1, EOP
, VString_Ptr
(Str
)));
3308 function NotAny
(Str
: VString_Func
) return Pattern
is
3310 return (AFC
with 0, new PE
'(PC_NotAny_VF, 1, EOP, Str));
3317 function NSpan (Str : String) return Pattern is
3319 return (AFC with 0, new PE'(PC_NSpan_CS
, 1, EOP
, To_Set
(Str
)));
3322 function NSpan
(Str
: VString
) return Pattern
is
3324 return NSpan
(S
(Str
));
3327 function NSpan
(Str
: Character) return Pattern
is
3329 return (AFC
with 0, new PE
'(PC_NSpan_CH, 1, EOP, Str));
3332 function NSpan (Str : Character_Set) return Pattern is
3334 return (AFC with 0, new PE'(PC_NSpan_CS
, 1, EOP
, Str
));
3337 function NSpan
(Str
: not null access VString
) return Pattern
is
3339 return (AFC
with 0, new PE
'(PC_NSpan_VP, 1, EOP, VString_Ptr (Str)));
3342 function NSpan (Str : VString_Func) return Pattern is
3344 return (AFC with 0, new PE'(PC_NSpan_VF
, 1, EOP
, Str
));
3351 function Pos
(Count
: Natural) return Pattern
is
3353 return (AFC
with 0, new PE
'(PC_Pos_Nat, 1, EOP, Count));
3356 function Pos (Count : Natural_Func) return Pattern is
3358 return (AFC with 0, new PE'(PC_Pos_NF
, 1, EOP
, Count
));
3361 function Pos
(Count
: not null access Natural) return Pattern
is
3363 return (AFC
with 0, new PE
'(PC_Pos_NP, 1, EOP, Natural_Ptr (Count)));
3370 procedure PutD (Str : String) is
3372 if Internal_Debug then
3381 procedure Put_LineD (Str : String) is
3383 if Internal_Debug then
3393 (Result : in out Match_Result;
3396 S : Big_String_Access;
3400 Get_String (Replace, S, L);
3402 if Result.Var /= null then
3403 Replace_Slice (Result.Var.all, Result.Start, Result.Stop, S (1 .. L));
3412 function Rest return Pattern is
3414 return (AFC with 0, new PE'(PC_Rest
, 1, EOP
));
3421 function Rpos
(Count
: Natural) return Pattern
is
3423 return (AFC
with 0, new PE
'(PC_RPos_Nat, 1, EOP, Count));
3426 function Rpos (Count : Natural_Func) return Pattern is
3428 return (AFC with 0, new PE'(PC_RPos_NF
, 1, EOP
, Count
));
3431 function Rpos
(Count
: not null access Natural) return Pattern
is
3433 return (AFC
with 0, new PE
'(PC_RPos_NP, 1, EOP, Natural_Ptr (Count)));
3440 function Rtab (Count : Natural) return Pattern is
3442 return (AFC with 0, new PE'(PC_RTab_Nat
, 1, EOP
, Count
));
3445 function Rtab
(Count
: Natural_Func
) return Pattern
is
3447 return (AFC
with 0, new PE
'(PC_RTab_NF, 1, EOP, Count));
3450 function Rtab (Count : not null access Natural) return Pattern is
3452 return (AFC with 0, new PE'(PC_RTab_NP
, 1, EOP
, Natural_Ptr
(Count
)));
3459 function S_To_PE
(Str
: PString
) return PE_Ptr
is
3460 Len
: constant Natural := Str
'Length;
3465 return new PE
'(PC_Null, 1, EOP);
3468 return new PE'(PC_Char
, 1, EOP
, Str
(Str
'First));
3471 return new PE
'(PC_String_2, 1, EOP, Str);
3474 return new PE'(PC_String_3
, 1, EOP
, Str
);
3477 return new PE
'(PC_String_4, 1, EOP, Str);
3480 return new PE'(PC_String_5
, 1, EOP
, Str
);
3483 return new PE
'(PC_String_6, 1, EOP, Str);
3486 return new PE'(PC_String
, 1, EOP
, new String'(Str));
3494 -- Note: this procedure is not used by the normal concatenation circuit,
3495 -- since other fixups are required on the left operand in this case, and
3496 -- they might as well be done all together.
3498 procedure Set_Successor (Pat : PE_Ptr; Succ : PE_Ptr) is
3501 Uninitialized_Pattern;
3503 elsif Pat = EOP then
3508 Refs : Ref_Array (1 .. Pat.Index);
3509 -- We build a reference array for L whose N'th element points to
3510 -- the pattern element of L whose original Index value is N.
3515 Build_Ref_Array (Pat, Refs);
3517 for J in Refs'Range loop
3520 if P.Pthen = EOP then
3524 if P.Pcode in PC_Has_Alt and then P.Alt = EOP then
3536 function Setcur (Var : not null access Natural) return Pattern is
3538 return (AFC with 0, new PE'(PC_Setcur
, 1, EOP
, Natural_Ptr
(Var
)));
3545 function Span
(Str
: String) return Pattern
is
3547 return (AFC
with 0, new PE
'(PC_Span_CS, 1, EOP, To_Set (Str)));
3550 function Span (Str : VString) return Pattern is
3552 return Span (S (Str));
3555 function Span (Str : Character) return Pattern is
3557 return (AFC with 0, new PE'(PC_Span_CH
, 1, EOP
, Str
));
3560 function Span
(Str
: Character_Set
) return Pattern
is
3562 return (AFC
with 0, new PE
'(PC_Span_CS, 1, EOP, Str));
3565 function Span (Str : not null access VString) return Pattern is
3567 return (AFC with 0, new PE'(PC_Span_VP
, 1, EOP
, VString_Ptr
(Str
)));
3570 function Span
(Str
: VString_Func
) return Pattern
is
3572 return (AFC
with 0, new PE
'(PC_Span_VF, 1, EOP, Str));
3579 function Str_BF (A : Boolean_Func) return String is
3580 function To_A is new Ada.Unchecked_Conversion (Boolean_Func, Address);
3582 return "BF(" & Image (To_A (A)) & ')';
3589 function Str_FP (A : File_Ptr) return String is
3591 return "FP(" & Image (A.all'Address) & ')';
3598 function Str_NF (A : Natural_Func) return String is
3599 function To_A is new Ada.Unchecked_Conversion (Natural_Func, Address);
3601 return "NF(" & Image (To_A (A)) & ')';
3608 function Str_NP (A : Natural_Ptr) return String is
3610 return "NP(" & Image (A.all'Address) & ')';
3617 function Str_PP (A : Pattern_Ptr) return String is
3619 return "PP(" & Image (A.all'Address) & ')';
3626 function Str_VF (A : VString_Func) return String is
3627 function To_A is new Ada.Unchecked_Conversion (VString_Func, Address);
3629 return "VF(" & Image (To_A (A)) & ')';
3636 function Str_VP (A : VString_Ptr) return String is
3638 return "VP(" & Image (A.all'Address) & ')';
3645 function Succeed return Pattern is
3647 return (AFC with 1, new PE'(PC_Succeed
, 1, EOP
));
3654 function Tab
(Count
: Natural) return Pattern
is
3656 return (AFC
with 0, new PE
'(PC_Tab_Nat, 1, EOP, Count));
3659 function Tab (Count : Natural_Func) return Pattern is
3661 return (AFC with 0, new PE'(PC_Tab_NF
, 1, EOP
, Count
));
3664 function Tab
(Count
: not null access Natural) return Pattern
is
3666 return (AFC
with 0, new PE
'(PC_Tab_NP, 1, EOP, Natural_Ptr (Count)));
3669 ---------------------------
3670 -- Uninitialized_Pattern --
3671 ---------------------------
3673 procedure Uninitialized_Pattern is
3675 raise Program_Error with
3676 "uninitialized value of type GNAT.Spitbol.Patterns.Pattern";
3677 end Uninitialized_Pattern;
3687 Start : out Natural;
3691 -- Pointer to current pattern node. Initialized from Pat_P, and then
3692 -- updated as the match proceeds through its constituent elements.
3694 Length : constant Natural := Subject'Length;
3695 -- Length of string (= Subject'Last, since Subject'First is always 1)
3697 Cursor : Integer := 0;
3698 -- If the value is non-negative, then this value is the index showing
3699 -- the current position of the match in the subject string. The next
3700 -- character to be matched is at Subject (Cursor + 1). Note that since
3701 -- our view of the subject string in XMatch always has a lower bound
3702 -- of one, regardless of original bounds, that this definition exactly
3703 -- corresponds to the cursor value as referenced by functions like Pos.
3705 -- If the value is negative, then this is a saved stack pointer,
3706 -- typically a base pointer of an inner or outer region. Cursor
3707 -- temporarily holds such a value when it is popped from the stack
3708 -- by Fail. In all cases, Cursor is reset to a proper non-negative
3709 -- cursor value before the match proceeds (e.g. by propagating the
3710 -- failure and popping a "real" cursor value from the stack.
3712 PE_Unanchored : aliased PE := (PC_Unanchored, 0, Pat_P);
3713 -- Dummy pattern element used in the unanchored case
3716 -- The pattern matching failure stack for this call to Match
3718 Stack_Ptr : Stack_Range;
3719 -- Current stack pointer. This points to the top element of the stack
3720 -- that is currently in use. At the outer level this is the special
3721 -- entry placed on the stack according to the anchor mode.
3723 Stack_Init : constant Stack_Range := Stack'First + 1;
3724 -- This is the initial value of the Stack_Ptr and Stack_Base. The
3725 -- initial (Stack'First) element of the stack is not used so that
3726 -- when we pop the last element off, Stack_Ptr is still in range.
3728 Stack_Base : Stack_Range;
3729 -- This value is the stack base value, i.e. the stack pointer for the
3730 -- first history stack entry in the current stack region. See separate
3731 -- section on handling of recursive pattern matches.
3733 Assign_OnM : Boolean := False;
3734 -- Set True if assign-on-match or write-on-match operations may be
3735 -- present in the history stack, which must then be scanned on a
3736 -- successful match.
3738 procedure Pop_Region;
3739 pragma Inline (Pop_Region);
3740 -- Used at the end of processing of an inner region. If the inner
3741 -- region left no stack entries, then all trace of it is removed.
3742 -- Otherwise a PC_Restore_Region entry is pushed to ensure proper
3743 -- handling of alternatives in the inner region.
3745 procedure Push (Node : PE_Ptr);
3746 pragma Inline (Push);
3747 -- Make entry in pattern matching stack with current cursor value
3749 procedure Push_Region;
3750 pragma Inline (Push_Region);
3751 -- This procedure makes a new region on the history stack. The
3752 -- caller first establishes the special entry on the stack, but
3753 -- does not push the stack pointer. Then this call stacks a
3754 -- PC_Remove_Region node, on top of this entry, using the cursor
3755 -- field of the PC_Remove_Region entry to save the outer level
3756 -- stack base value, and resets the stack base to point to this
3757 -- PC_Remove_Region node.
3763 procedure Pop_Region is
3765 -- If nothing was pushed in the inner region, we can just get
3766 -- rid of it entirely, leaving no traces that it was ever there
3768 if Stack_Ptr = Stack_Base then
3769 Stack_Ptr := Stack_Base - 2;
3770 Stack_Base := Stack (Stack_Ptr + 2).Cursor;
3772 -- If stuff was pushed in the inner region, then we have to
3773 -- push a PC_R_Restore node so that we properly handle possible
3774 -- rematches within the region.
3777 Stack_Ptr := Stack_Ptr + 1;
3778 Stack (Stack_Ptr).Cursor := Stack_Base;
3779 Stack (Stack_Ptr).Node := CP_R_Restore'Access;
3780 Stack_Base := Stack (Stack_Base).Cursor;
3788 procedure Push (Node : PE_Ptr) is
3790 Stack_Ptr := Stack_Ptr + 1;
3791 Stack (Stack_Ptr).Cursor := Cursor;
3792 Stack (Stack_Ptr).Node := Node;
3799 procedure Push_Region is
3801 Stack_Ptr := Stack_Ptr + 2;
3802 Stack (Stack_Ptr).Cursor := Stack_Base;
3803 Stack (Stack_Ptr).Node := CP_R_Remove'Access;
3804 Stack_Base := Stack_Ptr;
3807 -- Start of processing for XMatch
3810 if Pat_P = null then
3811 Uninitialized_Pattern;
3814 -- Check we have enough stack for this pattern. This check deals with
3815 -- every possibility except a match of a recursive pattern, where we
3816 -- make a check at each recursion level.
3818 if Pat_S >= Stack_Size - 1 then
3819 raise Pattern_Stack_Overflow;
3822 -- In anchored mode, the bottom entry on the stack is an abort entry
3824 if Anchored_Mode then
3825 Stack (Stack_Init).Node := CP_Cancel'Access;
3826 Stack (Stack_Init).Cursor := 0;
3828 -- In unanchored more, the bottom entry on the stack references
3829 -- the special pattern element PE_Unanchored, whose Pthen field
3830 -- points to the initial pattern element. The cursor value in this
3831 -- entry is the number of anchor moves so far.
3834 Stack (Stack_Init).Node := PE_Unanchored'Unchecked_Access;
3835 Stack (Stack_Init).Cursor := 0;
3838 Stack_Ptr := Stack_Init;
3839 Stack_Base := Stack_Ptr;
3844 -----------------------------------------
3845 -- Main Pattern Matching State Control --
3846 -----------------------------------------
3848 -- This is a state machine which uses gotos to change state. The
3849 -- initial state is Match, to initiate the matching of the first
3850 -- element, so the goto Match above starts the match. In the
3851 -- following descriptions, we indicate the global values that
3852 -- are relevant for the state transition.
3854 -- Come here if entire match fails
3861 -- Come here if entire match succeeds
3863 -- Cursor current position in subject string
3866 Start := Stack (Stack_Init).Cursor + 1;
3869 -- Scan history stack for deferred assignments or writes
3872 for S in Stack_Init .. Stack_Ptr loop
3873 if Stack (S).Node = CP_Assign'Access then
3875 Inner_Base : constant Stack_Range :=
3876 Stack (S + 1).Cursor;
3877 Special_Entry : constant Stack_Range :=
3879 Node_OnM : constant PE_Ptr :=
3880 Stack (Special_Entry).Node;
3881 Start : constant Natural :=
3882 Stack (Special_Entry).Cursor + 1;
3883 Stop : constant Natural := Stack (S).Cursor;
3886 if Node_OnM.Pcode = PC_Assign_OnM then
3887 Set_Unbounded_String
3888 (Node_OnM.VP.all, Subject (Start .. Stop));
3890 elsif Node_OnM.Pcode = PC_Write_OnM then
3891 Put_Line (Node_OnM.FP.all, Subject (Start .. Stop));
3903 -- Come here if attempt to match current element fails
3905 -- Stack_Base current stack base
3906 -- Stack_Ptr current stack pointer
3909 Cursor := Stack (Stack_Ptr).Cursor;
3910 Node := Stack (Stack_Ptr).Node;
3911 Stack_Ptr := Stack_Ptr - 1;
3914 -- Come here if attempt to match current element succeeds
3916 -- Cursor current position in subject string
3917 -- Node pointer to node successfully matched
3918 -- Stack_Base current stack base
3919 -- Stack_Ptr current stack pointer
3924 -- Come here to match the next pattern element
3926 -- Cursor current position in subject string
3927 -- Node pointer to node to be matched
3928 -- Stack_Base current stack base
3929 -- Stack_Ptr current stack pointer
3933 --------------------------------------------------
3934 -- Main Pattern Match Element Matching Routines --
3935 --------------------------------------------------
3937 -- Here is the case statement that processes the current node. The
3938 -- processing for each element does one of five things:
3940 -- goto Succeed to move to the successor
3941 -- goto Match_Succeed if the entire match succeeds
3942 -- goto Match_Fail if the entire match fails
3943 -- goto Fail to signal failure of current match
3945 -- Processing is NOT allowed to fall through
3961 -- Any (one character case)
3965 and then Subject (Cursor + 1) = Node.Char
3967 Cursor := Cursor + 1;
3973 -- Any (character set case)
3977 and then Is_In (Subject (Cursor + 1), Node.CS)
3979 Cursor := Cursor + 1;
3985 -- Any (string function case)
3987 when PC_Any_VF => declare
3988 U : constant VString := Node.VF.all;
3989 S : Big_String_Access;
3993 Get_String (U, S, L);
3996 and then Is_In (Subject (Cursor + 1), S (1 .. L))
3998 Cursor := Cursor + 1;
4005 -- Any (string pointer case)
4007 when PC_Any_VP => declare
4008 U : constant VString := Node.VP.all;
4009 S : Big_String_Access;
4013 Get_String (U, S, L);
4016 and then Is_In (Subject (Cursor + 1), S (1 .. L))
4018 Cursor := Cursor + 1;
4025 -- Arb (initial match)
4035 if Cursor < Length then
4036 Cursor := Cursor + 1;
4043 -- Arbno_S (simple Arbno initialize). This is the node that
4044 -- initiates the match of a simple Arbno structure.
4051 -- Arbno_X (Arbno initialize). This is the node that initiates
4052 -- the match of a complex Arbno structure.
4059 -- Arbno_Y (Arbno rematch). This is the node that is executed
4060 -- following successful matching of one instance of a complex
4063 when PC_Arbno_Y => declare
4064 Null_Match : constant Boolean :=
4065 Cursor = Stack (Stack_Base - 1).Cursor;
4070 -- If arbno extension matched null, then immediately fail
4076 -- Here we must do a stack check to make sure enough stack
4077 -- is left. This check will happen once for each instance of
4078 -- the Arbno pattern that is matched. The Nat field of a
4079 -- PC_Arbno pattern contains the maximum stack entries needed
4080 -- for the Arbno with one instance and the successor pattern
4082 if Stack_Ptr + Node.Nat >= Stack'Last then
4083 raise Pattern_Stack_Overflow;
4089 -- Assign. If this node is executed, it means the assign-on-match
4090 -- or write-on-match operation will not happen after all, so we
4091 -- is propagate the failure, removing the PC_Assign node.
4096 -- Assign immediate. This node performs the actual assignment
4098 when PC_Assign_Imm =>
4099 Set_Unbounded_String
4101 Subject (Stack (Stack_Base - 1).Cursor + 1 .. Cursor));
4105 -- Assign on match. This node sets up for the eventual assignment
4107 when PC_Assign_OnM =>
4108 Stack (Stack_Base - 1).Node := Node;
4109 Push (CP_Assign'Access);
4117 if Cursor >= Length or else Subject (Cursor + 1) = ')' then
4120 elsif Subject (Cursor + 1) = '(' then
4122 Paren_Count : Natural := 1;
4126 Cursor := Cursor + 1;
4128 if Cursor >= Length then
4131 elsif Subject (Cursor + 1) = '(' then
4132 Paren_Count := Paren_Count + 1;
4134 elsif Subject (Cursor + 1) = ')' then
4135 Paren_Count := Paren_Count - 1;
4136 exit when Paren_Count = 0;
4142 Cursor := Cursor + 1;
4146 -- Break (one character case)
4149 while Cursor < Length loop
4150 if Subject (Cursor + 1) = Node.Char then
4153 Cursor := Cursor + 1;
4159 -- Break (character set case)
4162 while Cursor < Length loop
4163 if Is_In (Subject (Cursor + 1), Node.CS) then
4166 Cursor := Cursor + 1;
4172 -- Break (string function case)
4174 when PC_Break_VF => declare
4175 U : constant VString := Node.VF.all;
4176 S : Big_String_Access;
4180 Get_String (U, S, L);
4182 while Cursor < Length loop
4183 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
4186 Cursor := Cursor + 1;
4193 -- Break (string pointer case)
4195 when PC_Break_VP => declare
4196 U : constant VString := Node.VP.all;
4197 S : Big_String_Access;
4201 Get_String (U, S, L);
4203 while Cursor < Length loop
4204 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
4207 Cursor := Cursor + 1;
4214 -- BreakX (one character case)
4216 when PC_BreakX_CH =>
4217 while Cursor < Length loop
4218 if Subject (Cursor + 1) = Node.Char then
4221 Cursor := Cursor + 1;
4227 -- BreakX (character set case)
4229 when PC_BreakX_CS =>
4230 while Cursor < Length loop
4231 if Is_In (Subject (Cursor + 1), Node.CS) then
4234 Cursor := Cursor + 1;
4240 -- BreakX (string function case)
4242 when PC_BreakX_VF => declare
4243 U : constant VString := Node.VF.all;
4244 S : Big_String_Access;
4248 Get_String (U, S, L);
4250 while Cursor < Length loop
4251 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
4254 Cursor := Cursor + 1;
4261 -- BreakX (string pointer case)
4263 when PC_BreakX_VP => declare
4264 U : constant VString := Node.VP.all;
4265 S : Big_String_Access;
4269 Get_String (U, S, L);
4271 while Cursor < Length loop
4272 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
4275 Cursor := Cursor + 1;
4282 -- BreakX_X (BreakX extension). See section on "Compound Pattern
4283 -- Structures". This node is the alternative that is stacked to
4284 -- skip past the break character and extend the break.
4287 Cursor := Cursor + 1;
4290 -- Character (one character string)
4294 and then Subject (Cursor + 1) = Node.Char
4296 Cursor := Cursor + 1;
4305 if Stack_Base = Stack_Init then
4308 -- End of recursive inner match. See separate section on
4309 -- handing of recursive pattern matches for details.
4312 Node := Stack (Stack_Base - 1).Node;
4322 -- Fence (built in pattern)
4325 Push (CP_Cancel'Access);
4328 -- Fence function node X. This is the node that gets control
4329 -- after a successful match of the fenced pattern.
4332 Stack_Ptr := Stack_Ptr + 1;
4333 Stack (Stack_Ptr).Cursor := Stack_Base;
4334 Stack (Stack_Ptr).Node := CP_Fence_Y'Access;
4335 Stack_Base := Stack (Stack_Base).Cursor;
4338 -- Fence function node Y. This is the node that gets control on
4339 -- a failure that occurs after the fenced pattern has matched.
4341 -- Note: the Cursor at this stage is actually the inner stack
4342 -- base value. We don't reset this, but we do use it to strip
4343 -- off all the entries made by the fenced pattern.
4346 Stack_Ptr := Cursor - 2;
4349 -- Len (integer case)
4352 if Cursor + Node.Nat > Length then
4355 Cursor := Cursor + Node.Nat;
4359 -- Len (Integer function case)
4361 when PC_Len_NF => declare
4362 N : constant Natural := Node.NF.all;
4364 if Cursor + N > Length then
4367 Cursor := Cursor + N;
4372 -- Len (integer pointer case)
4375 if Cursor + Node.NP.all > Length then
4378 Cursor := Cursor + Node.NP.all;
4382 -- NotAny (one character case)
4384 when PC_NotAny_CH =>
4386 and then Subject (Cursor + 1) /= Node.Char
4388 Cursor := Cursor + 1;
4394 -- NotAny (character set case)
4396 when PC_NotAny_CS =>
4398 and then not Is_In (Subject (Cursor + 1), Node.CS)
4400 Cursor := Cursor + 1;
4406 -- NotAny (string function case)
4408 when PC_NotAny_VF => declare
4409 U : constant VString := Node.VF.all;
4410 S : Big_String_Access;
4414 Get_String (U, S, L);
4418 not Is_In (Subject (Cursor + 1), S (1 .. L))
4420 Cursor := Cursor + 1;
4427 -- NotAny (string pointer case)
4429 when PC_NotAny_VP => declare
4430 U : constant VString := Node.VP.all;
4431 S : Big_String_Access;
4435 Get_String (U, S, L);
4439 not Is_In (Subject (Cursor + 1), S (1 .. L))
4441 Cursor := Cursor + 1;
4448 -- NSpan (one character case)
4451 while Cursor < Length
4452 and then Subject (Cursor + 1) = Node.Char
4454 Cursor := Cursor + 1;
4459 -- NSpan (character set case)
4462 while Cursor < Length
4463 and then Is_In (Subject (Cursor + 1), Node.CS)
4465 Cursor := Cursor + 1;
4470 -- NSpan (string function case)
4472 when PC_NSpan_VF => declare
4473 U : constant VString := Node.VF.all;
4474 S : Big_String_Access;
4478 Get_String (U, S, L);
4480 while Cursor < Length
4481 and then Is_In (Subject (Cursor + 1), S (1 .. L))
4483 Cursor := Cursor + 1;
4489 -- NSpan (string pointer case)
4491 when PC_NSpan_VP => declare
4492 U : constant VString := Node.VP.all;
4493 S : Big_String_Access;
4497 Get_String (U, S, L);
4499 while Cursor < Length
4500 and then Is_In (Subject (Cursor + 1), S (1 .. L))
4502 Cursor := Cursor + 1;
4513 -- Pos (integer case)
4516 if Cursor = Node.Nat then
4522 -- Pos (Integer function case)
4524 when PC_Pos_NF => declare
4525 N : constant Natural := Node.NF.all;
4534 -- Pos (integer pointer case)
4537 if Cursor = Node.NP.all then
4543 -- Predicate function
4545 when PC_Pred_Func =>
4552 -- Region Enter. Initiate new pattern history stack region
4555 Stack (Stack_Ptr + 1).Cursor := Cursor;
4559 -- Region Remove node. This is the node stacked by an R_Enter.
4560 -- It removes the special format stack entry right underneath, and
4561 -- then restores the outer level stack base and signals failure.
4563 -- Note: the cursor value at this stage is actually the (negative)
4564 -- stack base value for the outer level.
4567 Stack_Base := Cursor;
4568 Stack_Ptr := Stack_Ptr - 1;
4571 -- Region restore node. This is the node stacked at the end of an
4572 -- inner level match. Its function is to restore the inner level
4573 -- region, so that alternatives in this region can be sought.
4575 -- Note: the Cursor at this stage is actually the negative of the
4576 -- inner stack base value, which we use to restore the inner region.
4578 when PC_R_Restore =>
4579 Stack_Base := Cursor;
4588 -- Initiate recursive match (pattern pointer case)
4591 Stack (Stack_Ptr + 1).Node := Node.Pthen;
4594 if Stack_Ptr + Node.PP.all.Stk >= Stack_Size then
4595 raise Pattern_Stack_Overflow;
4597 Node := Node.PP.all.P;
4601 -- RPos (integer case)
4604 if Cursor = (Length - Node.Nat) then
4610 -- RPos (integer function case)
4612 when PC_RPos_NF => declare
4613 N : constant Natural := Node.NF.all;
4615 if Length - Cursor = N then
4622 -- RPos (integer pointer case)
4625 if Cursor = (Length - Node.NP.all) then
4631 -- RTab (integer case)
4634 if Cursor <= (Length - Node.Nat) then
4635 Cursor := Length - Node.Nat;
4641 -- RTab (integer function case)
4643 when PC_RTab_NF => declare
4644 N : constant Natural := Node.NF.all;
4646 if Length - Cursor >= N then
4647 Cursor := Length - N;
4654 -- RTab (integer pointer case)
4657 if Cursor <= (Length - Node.NP.all) then
4658 Cursor := Length - Node.NP.all;
4664 -- Cursor assignment
4667 Node.Var.all := Cursor;
4670 -- Span (one character case)
4672 when PC_Span_CH => declare
4678 and then Subject (P + 1) = Node.Char
4691 -- Span (character set case)
4693 when PC_Span_CS => declare
4699 and then Is_In (Subject (P + 1), Node.CS)
4712 -- Span (string function case)
4714 when PC_Span_VF => declare
4715 U : constant VString := Node.VF.all;
4716 S : Big_String_Access;
4721 Get_String (U, S, L);
4725 and then Is_In (Subject (P + 1), S (1 .. L))
4738 -- Span (string pointer case)
4740 when PC_Span_VP => declare
4741 U : constant VString := Node.VP.all;
4742 S : Big_String_Access;
4747 Get_String (U, S, L);
4751 and then Is_In (Subject (P + 1), S (1 .. L))
4764 -- String (two character case)
4767 if (Length - Cursor) >= 2
4768 and then Subject (Cursor + 1 .. Cursor + 2) = Node.Str2
4770 Cursor := Cursor + 2;
4776 -- String (three character case)
4779 if (Length - Cursor) >= 3
4780 and then Subject (Cursor + 1 .. Cursor + 3) = Node.Str3
4782 Cursor := Cursor + 3;
4788 -- String (four character case)
4791 if (Length - Cursor) >= 4
4792 and then Subject (Cursor + 1 .. Cursor + 4) = Node.Str4
4794 Cursor := Cursor + 4;
4800 -- String (five character case)
4803 if (Length - Cursor) >= 5
4804 and then Subject (Cursor + 1 .. Cursor + 5) = Node.Str5
4806 Cursor := Cursor + 5;
4812 -- String (six character case)
4815 if (Length - Cursor) >= 6
4816 and then Subject (Cursor + 1 .. Cursor + 6) = Node.Str6
4818 Cursor := Cursor + 6;
4824 -- String (case of more than six characters)
4826 when PC_String => declare
4827 Len : constant Natural := Node.Str'Length;
4829 if (Length - Cursor) >= Len
4830 and then Node.Str.all = Subject (Cursor + 1 .. Cursor + Len)
4832 Cursor := Cursor + Len;
4839 -- String (function case)
4841 when PC_String_VF => declare
4842 U : constant VString := Node.VF.all;
4843 S : Big_String_Access;
4847 Get_String (U, S, L);
4849 if (Length - Cursor) >= L
4850 and then S (1 .. L) = Subject (Cursor + 1 .. Cursor + L)
4852 Cursor := Cursor + L;
4859 -- String (pointer case)
4861 when PC_String_VP => declare
4862 U : constant VString := Node.VP.all;
4863 S : Big_String_Access;
4867 Get_String (U, S, L);
4869 if (Length - Cursor) >= L
4870 and then S (1 .. L) = Subject (Cursor + 1 .. Cursor + L)
4872 Cursor := Cursor + L;
4885 -- Tab (integer case)
4888 if Cursor <= Node.Nat then
4895 -- Tab (integer function case)
4897 when PC_Tab_NF => declare
4898 N : constant Natural := Node.NF.all;
4908 -- Tab (integer pointer case)
4911 if Cursor <= Node.NP.all then
4912 Cursor := Node.NP.all;
4918 -- Unanchored movement
4920 when PC_Unanchored =>
4922 -- All done if we tried every position
4924 if Cursor > Length then
4927 -- Otherwise extend the anchor point, and restack ourself
4930 Cursor := Cursor + 1;
4935 -- Write immediate. This node performs the actual write
4937 when PC_Write_Imm =>
4940 Subject (Stack (Stack_Base - 1).Cursor + 1 .. Cursor));
4944 -- Write on match. This node sets up for the eventual write
4946 when PC_Write_OnM =>
4947 Stack (Stack_Base - 1).Node := Node;
4948 Push (CP_Assign'Access);
4954 -- We are NOT allowed to fall though this case statement, since every
4955 -- match routine must end by executing a goto to the appropriate point
4956 -- in the finite state machine model.
4958 pragma Warnings (Off);
4960 pragma Warnings (On);
4967 -- Maintenance note: There is a LOT of code duplication between XMatch
4968 -- and XMatchD. This is quite intentional, the point is to avoid any
4969 -- unnecessary debugging overhead in the XMatch case, but this does mean
4970 -- that any changes to XMatchD must be mirrored in XMatch. In case of
4971 -- any major changes, the proper approach is to delete XMatch, make the
4972 -- changes to XMatchD, and then make a copy of XMatchD, removing all
4973 -- calls to Dout, and all Put and Put_Line operations. This copy becomes
4980 Start : out Natural;
4984 -- Pointer to current pattern node. Initialized from Pat_P, and then
4985 -- updated as the match proceeds through its constituent elements.
4987 Length : constant Natural := Subject'Length;
4988 -- Length of string (= Subject'Last, since Subject'First is always 1)
4990 Cursor : Integer := 0;
4991 -- If the value is non-negative, then this value is the index showing
4992 -- the current position of the match in the subject string. The next
4993 -- character to be matched is at Subject (Cursor + 1). Note that since
4994 -- our view of the subject string in XMatch always has a lower bound
4995 -- of one, regardless of original bounds, that this definition exactly
4996 -- corresponds to the cursor value as referenced by functions like Pos.
4998 -- If the value is negative, then this is a saved stack pointer,
4999 -- typically a base pointer of an inner or outer region. Cursor
5000 -- temporarily holds such a value when it is popped from the stack
5001 -- by Fail. In all cases, Cursor is reset to a proper non-negative
5002 -- cursor value before the match proceeds (e.g. by propagating the
5003 -- failure and popping a "real" cursor value from the stack.
5005 PE_Unanchored : aliased PE := (PC_Unanchored, 0, Pat_P);
5006 -- Dummy pattern element used in the unanchored case
5008 Region_Level : Natural := 0;
5009 -- Keeps track of recursive region level. This is used only for
5010 -- debugging, it is the number of saved history stack base values.
5013 -- The pattern matching failure stack for this call to Match
5015 Stack_Ptr : Stack_Range;
5016 -- Current stack pointer. This points to the top element of the stack
5017 -- that is currently in use. At the outer level this is the special
5018 -- entry placed on the stack according to the anchor mode.
5020 Stack_Init : constant Stack_Range := Stack'First + 1;
5021 -- This is the initial value of the Stack_Ptr and Stack_Base. The
5022 -- initial (Stack'First) element of the stack is not used so that
5023 -- when we pop the last element off, Stack_Ptr is still in range.
5025 Stack_Base : Stack_Range;
5026 -- This value is the stack base value, i.e. the stack pointer for the
5027 -- first history stack entry in the current stack region. See separate
5028 -- section on handling of recursive pattern matches.
5030 Assign_OnM : Boolean := False;
5031 -- Set True if assign-on-match or write-on-match operations may be
5032 -- present in the history stack, which must then be scanned on a
5033 -- successful match.
5035 procedure Dout (Str : String);
5036 -- Output string to standard error with bars indicating region level
5038 procedure Dout (Str : String; A : Character);
5039 -- Calls Dout with the string S ('A
')
5041 procedure Dout (Str : String; A : Character_Set);
5042 -- Calls Dout with the string S ("A")
5044 procedure Dout (Str : String; A : Natural);
5045 -- Calls Dout with the string S (A)
5047 procedure Dout (Str : String; A : String);
5048 -- Calls Dout with the string S ("A")
5050 function Img (P : PE_Ptr) return String;
5051 -- Returns a string of the form #nnn where nnn is P.Index
5053 procedure Pop_Region;
5054 pragma Inline (Pop_Region);
5055 -- Used at the end of processing of an inner region. If the inner
5056 -- region left no stack entries, then all trace of it is removed.
5057 -- Otherwise a PC_Restore_Region entry is pushed to ensure proper
5058 -- handling of alternatives in the inner region.
5060 procedure Push (Node : PE_Ptr);
5061 pragma Inline (Push);
5062 -- Make entry in pattern matching stack with current cursor value
5064 procedure Push_Region;
5065 pragma Inline (Push_Region);
5066 -- This procedure makes a new region on the history stack. The
5067 -- caller first establishes the special entry on the stack, but
5068 -- does not push the stack pointer. Then this call stacks a
5069 -- PC_Remove_Region node, on top of this entry, using the cursor
5070 -- field of the PC_Remove_Region entry to save the outer level
5071 -- stack base value, and resets the stack base to point to this
5072 -- PC_Remove_Region node.
5078 procedure Dout (Str : String) is
5080 for J in 1 .. Region_Level loop
5087 procedure Dout (Str : String; A : Character) is
5089 Dout (Str & " ('" & A & "')");
5092 procedure Dout (Str : String; A : Character_Set) is
5094 Dout (Str & " (" & Image (To_Sequence (A)) & ')');
5097 procedure Dout (Str : String; A : Natural) is
5099 Dout (Str & " (" & A & ')');
5102 procedure Dout (Str : String; A : String) is
5104 Dout (Str & " (" & Image (A) & ')');
5111 function Img (P : PE_Ptr) return String is
5113 return "#" & Integer (P.Index) & " ";
5120 procedure Pop_Region is
5122 Region_Level := Region_Level - 1;
5124 -- If nothing was pushed in the inner region, we can just get
5125 -- rid of it entirely, leaving no traces that it was ever there
5127 if Stack_Ptr = Stack_Base then
5128 Stack_Ptr := Stack_Base - 2;
5129 Stack_Base := Stack (Stack_Ptr + 2).Cursor;
5131 -- If stuff was pushed in the inner region, then we have to
5132 -- push a PC_R_Restore node so that we properly handle possible
5133 -- rematches within the region.
5136 Stack_Ptr := Stack_Ptr + 1;
5137 Stack (Stack_Ptr).Cursor := Stack_Base;
5138 Stack (Stack_Ptr).Node := CP_R_Restore'Access;
5139 Stack_Base := Stack (Stack_Base).Cursor;
5147 procedure Push (Node : PE_Ptr) is
5149 Stack_Ptr := Stack_Ptr + 1;
5150 Stack (Stack_Ptr).Cursor := Cursor;
5151 Stack (Stack_Ptr).Node := Node;
5158 procedure Push_Region is
5160 Region_Level := Region_Level + 1;
5161 Stack_Ptr := Stack_Ptr + 2;
5162 Stack (Stack_Ptr).Cursor := Stack_Base;
5163 Stack (Stack_Ptr).Node := CP_R_Remove'Access;
5164 Stack_Base := Stack_Ptr;
5167 -- Start of processing for XMatchD
5171 Put_Line ("Initiating pattern match, subject = " & Image (Subject));
5172 Put ("--------------------------------------");
5174 for J in 1 .. Length loop
5179 Put_Line ("subject length = " & Length);
5181 if Pat_P = null then
5182 Uninitialized_Pattern;
5185 -- Check we have enough stack for this pattern. This check deals with
5186 -- every possibility except a match of a recursive pattern, where we
5187 -- make a check at each recursion level.
5189 if Pat_S >= Stack_Size - 1 then
5190 raise Pattern_Stack_Overflow;
5193 -- In anchored mode, the bottom entry on the stack is an abort entry
5195 if Anchored_Mode then
5196 Stack (Stack_Init).Node := CP_Cancel'Access;
5197 Stack (Stack_Init).Cursor := 0;
5199 -- In unanchored more, the bottom entry on the stack references
5200 -- the special pattern element PE_Unanchored, whose Pthen field
5201 -- points to the initial pattern element. The cursor value in this
5202 -- entry is the number of anchor moves so far.
5205 Stack (Stack_Init).Node := PE_Unanchored'Unchecked_Access;
5206 Stack (Stack_Init).Cursor := 0;
5209 Stack_Ptr := Stack_Init;
5210 Stack_Base := Stack_Ptr;
5215 -----------------------------------------
5216 -- Main Pattern Matching State Control --
5217 -----------------------------------------
5219 -- This is a state machine which uses gotos to change state. The
5220 -- initial state is Match, to initiate the matching of the first
5221 -- element, so the goto Match above starts the match. In the
5222 -- following descriptions, we indicate the global values that
5223 -- are relevant for the state transition.
5225 -- Come here if entire match fails
5228 Dout ("match fails");
5234 -- Come here if entire match succeeds
5236 -- Cursor current position in subject string
5239 Dout ("match succeeds");
5240 Start := Stack (Stack_Init).Cursor + 1;
5242 Dout ("first matched character index = " & Start);
5243 Dout ("last matched character index = " & Stop);
5244 Dout ("matched substring = " & Image (Subject (Start .. Stop)));
5246 -- Scan history stack for deferred assignments or writes
5249 for S in Stack'First .. Stack_Ptr loop
5250 if Stack (S).Node = CP_Assign'Access then
5252 Inner_Base : constant Stack_Range :=
5253 Stack (S + 1).Cursor;
5254 Special_Entry : constant Stack_Range :=
5256 Node_OnM : constant PE_Ptr :=
5257 Stack (Special_Entry).Node;
5258 Start : constant Natural :=
5259 Stack (Special_Entry).Cursor + 1;
5260 Stop : constant Natural := Stack (S).Cursor;
5263 if Node_OnM.Pcode = PC_Assign_OnM then
5264 Set_Unbounded_String
5265 (Node_OnM.VP.all, Subject (Start .. Stop));
5267 (Img (Stack (S).Node) &
5268 "deferred assignment of " &
5269 Image (Subject (Start .. Stop)));
5271 elsif Node_OnM.Pcode = PC_Write_OnM then
5272 Put_Line (Node_OnM.FP.all, Subject (Start .. Stop));
5274 (Img (Stack (S).Node) &
5275 "deferred write of " &
5276 Image (Subject (Start .. Stop)));
5289 -- Come here if attempt to match current element fails
5291 -- Stack_Base current stack base
5292 -- Stack_Ptr current stack pointer
5295 Cursor := Stack (Stack_Ptr).Cursor;
5296 Node := Stack (Stack_Ptr).Node;
5297 Stack_Ptr := Stack_Ptr - 1;
5300 Dout ("failure, cursor reset to " & Cursor);
5305 -- Come here if attempt to match current element succeeds
5307 -- Cursor current position in subject string
5308 -- Node pointer to node successfully matched
5309 -- Stack_Base current stack base
5310 -- Stack_Ptr current stack pointer
5313 Dout ("success, cursor = " & Cursor);
5316 -- Come here to match the next pattern element
5318 -- Cursor current position in subject string
5319 -- Node pointer to node to be matched
5320 -- Stack_Base current stack base
5321 -- Stack_Ptr current stack pointer
5325 --------------------------------------------------
5326 -- Main Pattern Match Element Matching Routines --
5327 --------------------------------------------------
5329 -- Here is the case statement that processes the current node. The
5330 -- processing for each element does one of five things:
5332 -- goto Succeed to move to the successor
5333 -- goto Match_Succeed if the entire match succeeds
5334 -- goto Match_Fail if the entire match fails
5335 -- goto Fail to signal failure of current match
5337 -- Processing is NOT allowed to fall through
5344 Dout (Img (Node) & "matching Cancel");
5350 Dout (Img (Node) & "setting up alternative " & Img (Node.Alt));
5355 -- Any (one character case)
5358 Dout (Img (Node) & "matching Any", Node.Char);
5361 and then Subject (Cursor + 1) = Node.Char
5363 Cursor := Cursor + 1;
5369 -- Any (character set case)
5372 Dout (Img (Node) & "matching Any", Node.CS);
5375 and then Is_In (Subject (Cursor + 1), Node.CS)
5377 Cursor := Cursor + 1;
5383 -- Any (string function case)
5385 when PC_Any_VF => declare
5386 U : constant VString := Node.VF.all;
5387 S : Big_String_Access;
5391 Get_String (U, S, L);
5393 Dout (Img (Node) & "matching Any", S (1 .. L));
5396 and then Is_In (Subject (Cursor + 1), S (1 .. L))
5398 Cursor := Cursor + 1;
5405 -- Any (string pointer case)
5407 when PC_Any_VP => declare
5408 U : constant VString := Node.VP.all;
5409 S : Big_String_Access;
5413 Get_String (U, S, L);
5414 Dout (Img (Node) & "matching Any", S (1 .. L));
5417 and then Is_In (Subject (Cursor + 1), S (1 .. L))
5419 Cursor := Cursor + 1;
5426 -- Arb (initial match)
5429 Dout (Img (Node) & "matching Arb");
5437 Dout (Img (Node) & "extending Arb");
5439 if Cursor < Length then
5440 Cursor := Cursor + 1;
5447 -- Arbno_S (simple Arbno initialize). This is the node that
5448 -- initiates the match of a simple Arbno structure.
5452 "setting up Arbno alternative " & Img (Node.Alt));
5457 -- Arbno_X (Arbno initialize). This is the node that initiates
5458 -- the match of a complex Arbno structure.
5462 "setting up Arbno alternative " & Img (Node.Alt));
5467 -- Arbno_Y (Arbno rematch). This is the node that is executed
5468 -- following successful matching of one instance of a complex
5471 when PC_Arbno_Y => declare
5472 Null_Match : constant Boolean :=
5473 Cursor = Stack (Stack_Base - 1).Cursor;
5476 Dout (Img (Node) & "extending Arbno");
5479 -- If arbno extension matched null, then immediately fail
5482 Dout ("Arbno extension matched null, so fails");
5486 -- Here we must do a stack check to make sure enough stack
5487 -- is left. This check will happen once for each instance of
5488 -- the Arbno pattern that is matched. The Nat field of a
5489 -- PC_Arbno pattern contains the maximum stack entries needed
5490 -- for the Arbno with one instance and the successor pattern
5492 if Stack_Ptr + Node.Nat >= Stack'Last then
5493 raise Pattern_Stack_Overflow;
5499 -- Assign. If this node is executed, it means the assign-on-match
5500 -- or write-on-match operation will not happen after all, so we
5501 -- is propagate the failure, removing the PC_Assign node.
5504 Dout (Img (Node) & "deferred assign/write cancelled");
5507 -- Assign immediate. This node performs the actual assignment
5509 when PC_Assign_Imm =>
5511 (Img (Node) & "executing immediate assignment of " &
5512 Image (Subject (Stack (Stack_Base - 1).Cursor + 1 .. Cursor)));
5513 Set_Unbounded_String
5515 Subject (Stack (Stack_Base - 1).Cursor + 1 .. Cursor));
5519 -- Assign on match. This node sets up for the eventual assignment
5521 when PC_Assign_OnM =>
5522 Dout (Img (Node) & "registering deferred assignment");
5523 Stack (Stack_Base - 1).Node := Node;
5524 Push (CP_Assign'Access);
5532 Dout (Img (Node) & "matching or extending Bal");
5533 if Cursor >= Length or else Subject (Cursor + 1) = ')' then
5536 elsif Subject (Cursor + 1) = '(' then
5538 Paren_Count : Natural := 1;
5542 Cursor := Cursor + 1;
5544 if Cursor >= Length then
5547 elsif Subject (Cursor + 1) = '(' then
5548 Paren_Count := Paren_Count + 1;
5550 elsif Subject (Cursor + 1) = ')' then
5551 Paren_Count := Paren_Count - 1;
5552 exit when Paren_Count = 0;
5558 Cursor := Cursor + 1;
5562 -- Break (one character case)
5565 Dout (Img (Node) & "matching Break", Node.Char);
5567 while Cursor < Length loop
5568 if Subject (Cursor + 1) = Node.Char then
5571 Cursor := Cursor + 1;
5577 -- Break (character set case)
5580 Dout (Img (Node) & "matching Break", Node.CS);
5582 while Cursor < Length loop
5583 if Is_In (Subject (Cursor + 1), Node.CS) then
5586 Cursor := Cursor + 1;
5592 -- Break (string function case)
5594 when PC_Break_VF => declare
5595 U : constant VString := Node.VF.all;
5596 S : Big_String_Access;
5600 Get_String (U, S, L);
5601 Dout (Img (Node) & "matching Break", S (1 .. L));
5603 while Cursor < Length loop
5604 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
5607 Cursor := Cursor + 1;
5614 -- Break (string pointer case)
5616 when PC_Break_VP => declare
5617 U : constant VString := Node.VP.all;
5618 S : Big_String_Access;
5622 Get_String (U, S, L);
5623 Dout (Img (Node) & "matching Break", S (1 .. L));
5625 while Cursor < Length loop
5626 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
5629 Cursor := Cursor + 1;
5636 -- BreakX (one character case)
5638 when PC_BreakX_CH =>
5639 Dout (Img (Node) & "matching BreakX", Node.Char);
5641 while Cursor < Length loop
5642 if Subject (Cursor + 1) = Node.Char then
5645 Cursor := Cursor + 1;
5651 -- BreakX (character set case)
5653 when PC_BreakX_CS =>
5654 Dout (Img (Node) & "matching BreakX", Node.CS);
5656 while Cursor < Length loop
5657 if Is_In (Subject (Cursor + 1), Node.CS) then
5660 Cursor := Cursor + 1;
5666 -- BreakX (string function case)
5668 when PC_BreakX_VF => declare
5669 U : constant VString := Node.VF.all;
5670 S : Big_String_Access;
5674 Get_String (U, S, L);
5675 Dout (Img (Node) & "matching BreakX", S (1 .. L));
5677 while Cursor < Length loop
5678 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
5681 Cursor := Cursor + 1;
5688 -- BreakX (string pointer case)
5690 when PC_BreakX_VP => declare
5691 U : constant VString := Node.VP.all;
5692 S : Big_String_Access;
5696 Get_String (U, S, L);
5697 Dout (Img (Node) & "matching BreakX", S (1 .. L));
5699 while Cursor < Length loop
5700 if Is_In (Subject (Cursor + 1), S (1 .. L)) then
5703 Cursor := Cursor + 1;
5710 -- BreakX_X (BreakX extension). See section on "Compound Pattern
5711 -- Structures". This node is the alternative that is stacked
5712 -- to skip past the break character and extend the break.
5715 Dout (Img (Node) & "extending BreakX");
5716 Cursor := Cursor + 1;
5719 -- Character (one character string)
5722 Dout (Img (Node) & "matching '" & Node.Char & ''');
5725 and then Subject (Cursor + 1) = Node.Char
5727 Cursor := Cursor + 1;
5736 if Stack_Base = Stack_Init then
5737 Dout ("end of pattern
");
5740 -- End of recursive inner match. See separate section on
5741 -- handing of recursive pattern matches for details.
5744 Dout ("terminating recursive match
");
5745 Node := Stack (Stack_Base - 1).Node;
5753 Dout (Img (Node) & "matching Fail
");
5756 -- Fence (built in pattern)
5759 Dout (Img (Node) & "matching Fence
");
5760 Push (CP_Cancel'Access);
5763 -- Fence function node X. This is the node that gets control
5764 -- after a successful match of the fenced pattern.
5767 Dout (Img (Node) & "matching Fence
function");
5768 Stack_Ptr := Stack_Ptr + 1;
5769 Stack (Stack_Ptr).Cursor := Stack_Base;
5770 Stack (Stack_Ptr).Node := CP_Fence_Y'Access;
5771 Stack_Base := Stack (Stack_Base).Cursor;
5772 Region_Level := Region_Level - 1;
5775 -- Fence function node Y. This is the node that gets control on
5776 -- a failure that occurs after the fenced pattern has matched.
5778 -- Note: the Cursor at this stage is actually the inner stack
5779 -- base value. We don't reset this, but we do use it to strip
5780 -- off all the entries made by the fenced pattern.
5783 Dout (Img (Node) & "pattern matched by Fence caused failure
");
5784 Stack_Ptr := Cursor - 2;
5787 -- Len (integer case)
5790 Dout (Img (Node) & "matching Len
", Node.Nat);
5792 if Cursor + Node.Nat > Length then
5795 Cursor := Cursor + Node.Nat;
5799 -- Len (Integer function case)
5801 when PC_Len_NF => declare
5802 N : constant Natural := Node.NF.all;
5805 Dout (Img (Node) & "matching Len
", N);
5807 if Cursor + N > Length then
5810 Cursor := Cursor + N;
5815 -- Len (integer pointer case)
5818 Dout (Img (Node) & "matching Len
", Node.NP.all);
5820 if Cursor + Node.NP.all > Length then
5823 Cursor := Cursor + Node.NP.all;
5827 -- NotAny (one character case)
5829 when PC_NotAny_CH =>
5830 Dout (Img (Node) & "matching NotAny
", Node.Char);
5833 and then Subject (Cursor + 1) /= Node.Char
5835 Cursor := Cursor + 1;
5841 -- NotAny (character set case)
5843 when PC_NotAny_CS =>
5844 Dout (Img (Node) & "matching NotAny
", Node.CS);
5847 and then not Is_In (Subject (Cursor + 1), Node.CS)
5849 Cursor := Cursor + 1;
5855 -- NotAny (string function case)
5857 when PC_NotAny_VF => declare
5858 U : constant VString := Node.VF.all;
5859 S : Big_String_Access;
5863 Get_String (U, S, L);
5864 Dout (Img (Node) & "matching NotAny
", S (1 .. L));
5868 not Is_In (Subject (Cursor + 1), S (1 .. L))
5870 Cursor := Cursor + 1;
5877 -- NotAny (string pointer case)
5879 when PC_NotAny_VP => declare
5880 U : constant VString := Node.VP.all;
5881 S : Big_String_Access;
5885 Get_String (U, S, L);
5886 Dout (Img (Node) & "matching NotAny
", S (1 .. L));
5890 not Is_In (Subject (Cursor + 1), S (1 .. L))
5892 Cursor := Cursor + 1;
5899 -- NSpan (one character case)
5902 Dout (Img (Node) & "matching NSpan
", Node.Char);
5904 while Cursor < Length
5905 and then Subject (Cursor + 1) = Node.Char
5907 Cursor := Cursor + 1;
5912 -- NSpan (character set case)
5915 Dout (Img (Node) & "matching NSpan
", Node.CS);
5917 while Cursor < Length
5918 and then Is_In (Subject (Cursor + 1), Node.CS)
5920 Cursor := Cursor + 1;
5925 -- NSpan (string function case)
5927 when PC_NSpan_VF => declare
5928 U : constant VString := Node.VF.all;
5929 S : Big_String_Access;
5933 Get_String (U, S, L);
5934 Dout (Img (Node) & "matching NSpan
", S (1 .. L));
5936 while Cursor < Length
5937 and then Is_In (Subject (Cursor + 1), S (1 .. L))
5939 Cursor := Cursor + 1;
5945 -- NSpan (string pointer case)
5947 when PC_NSpan_VP => declare
5948 U : constant VString := Node.VP.all;
5949 S : Big_String_Access;
5953 Get_String (U, S, L);
5954 Dout (Img (Node) & "matching NSpan
", S (1 .. L));
5956 while Cursor < Length
5957 and then Is_In (Subject (Cursor + 1), S (1 .. L))
5959 Cursor := Cursor + 1;
5966 Dout (Img (Node) & "matching
null");
5969 -- Pos (integer case)
5972 Dout (Img (Node) & "matching Pos
", Node.Nat);
5974 if Cursor = Node.Nat then
5980 -- Pos (Integer function case)
5982 when PC_Pos_NF => declare
5983 N : constant Natural := Node.NF.all;
5986 Dout (Img (Node) & "matching Pos
", N);
5995 -- Pos (integer pointer case)
5998 Dout (Img (Node) & "matching Pos
", Node.NP.all);
6000 if Cursor = Node.NP.all then
6006 -- Predicate function
6008 when PC_Pred_Func =>
6009 Dout (Img (Node) & "matching predicate
function");
6017 -- Region Enter. Initiate new pattern history stack region
6020 Dout (Img (Node) & "starting match
of nested pattern
");
6021 Stack (Stack_Ptr + 1).Cursor := Cursor;
6025 -- Region Remove node. This is the node stacked by an R_Enter.
6026 -- It removes the special format stack entry right underneath, and
6027 -- then restores the outer level stack base and signals failure.
6029 -- Note: the cursor value at this stage is actually the (negative)
6030 -- stack base value for the outer level.
6033 Dout ("failure
, match
of nested pattern terminated
");
6034 Stack_Base := Cursor;
6035 Region_Level := Region_Level - 1;
6036 Stack_Ptr := Stack_Ptr - 1;
6039 -- Region restore node. This is the node stacked at the end of an
6040 -- inner level match. Its function is to restore the inner level
6041 -- region, so that alternatives in this region can be sought.
6043 -- Note: the Cursor at this stage is actually the negative of the
6044 -- inner stack base value, which we use to restore the inner region.
6046 when PC_R_Restore =>
6047 Dout ("failure
, search
for alternatives
in nested pattern
");
6048 Region_Level := Region_Level + 1;
6049 Stack_Base := Cursor;
6055 Dout (Img (Node) & "matching Rest
");
6059 -- Initiate recursive match (pattern pointer case)
6062 Stack (Stack_Ptr + 1).Node := Node.Pthen;
6064 Dout (Img (Node) & "initiating recursive match
");
6066 if Stack_Ptr + Node.PP.all.Stk >= Stack_Size then
6067 raise Pattern_Stack_Overflow;
6069 Node := Node.PP.all.P;
6073 -- RPos (integer case)
6076 Dout (Img (Node) & "matching RPos
", Node.Nat);
6078 if Cursor = (Length - Node.Nat) then
6084 -- RPos (integer function case)
6086 when PC_RPos_NF => declare
6087 N : constant Natural := Node.NF.all;
6090 Dout (Img (Node) & "matching RPos
", N);
6092 if Length - Cursor = N then
6099 -- RPos (integer pointer case)
6102 Dout (Img (Node) & "matching RPos
", Node.NP.all);
6104 if Cursor = (Length - Node.NP.all) then
6110 -- RTab (integer case)
6113 Dout (Img (Node) & "matching RTab
", Node.Nat);
6115 if Cursor <= (Length - Node.Nat) then
6116 Cursor := Length - Node.Nat;
6122 -- RTab (integer function case)
6124 when PC_RTab_NF => declare
6125 N : constant Natural := Node.NF.all;
6128 Dout (Img (Node) & "matching RPos
", N);
6130 if Length - Cursor >= N then
6131 Cursor := Length - N;
6138 -- RTab (integer pointer case)
6141 Dout (Img (Node) & "matching RPos
", Node.NP.all);
6143 if Cursor <= (Length - Node.NP.all) then
6144 Cursor := Length - Node.NP.all;
6150 -- Cursor assignment
6153 Dout (Img (Node) & "matching Setcur
");
6154 Node.Var.all := Cursor;
6157 -- Span (one character case)
6159 when PC_Span_CH => declare
6160 P : Natural := Cursor;
6163 Dout (Img (Node) & "matching Span
", Node.Char);
6166 and then Subject (P + 1) = Node.Char
6179 -- Span (character set case)
6181 when PC_Span_CS => declare
6182 P : Natural := Cursor;
6185 Dout (Img (Node) & "matching Span
", Node.CS);
6188 and then Is_In (Subject (P + 1), Node.CS)
6201 -- Span (string function case)
6203 when PC_Span_VF => declare
6204 U : constant VString := Node.VF.all;
6205 S : Big_String_Access;
6210 Get_String (U, S, L);
6211 Dout (Img (Node) & "matching Span
", S (1 .. L));
6215 and then Is_In (Subject (P + 1), S (1 .. L))
6228 -- Span (string pointer case)
6230 when PC_Span_VP => declare
6231 U : constant VString := Node.VP.all;
6232 S : Big_String_Access;
6237 Get_String (U, S, L);
6238 Dout (Img (Node) & "matching Span
", S (1 .. L));
6242 and then Is_In (Subject (P + 1), S (1 .. L))
6255 -- String (two character case)
6258 Dout (Img (Node) & "matching
" & Image (Node.Str2));
6260 if (Length - Cursor) >= 2
6261 and then Subject (Cursor + 1 .. Cursor + 2) = Node.Str2
6263 Cursor := Cursor + 2;
6269 -- String (three character case)
6272 Dout (Img (Node) & "matching
" & Image (Node.Str3));
6274 if (Length - Cursor) >= 3
6275 and then Subject (Cursor + 1 .. Cursor + 3) = Node.Str3
6277 Cursor := Cursor + 3;
6283 -- String (four character case)
6286 Dout (Img (Node) & "matching
" & Image (Node.Str4));
6288 if (Length - Cursor) >= 4
6289 and then Subject (Cursor + 1 .. Cursor + 4) = Node.Str4
6291 Cursor := Cursor + 4;
6297 -- String (five character case)
6300 Dout (Img (Node) & "matching
" & Image (Node.Str5));
6302 if (Length - Cursor) >= 5
6303 and then Subject (Cursor + 1 .. Cursor + 5) = Node.Str5
6305 Cursor := Cursor + 5;
6311 -- String (six character case)
6314 Dout (Img (Node) & "matching
" & Image (Node.Str6));
6316 if (Length - Cursor) >= 6
6317 and then Subject (Cursor + 1 .. Cursor + 6) = Node.Str6
6319 Cursor := Cursor + 6;
6325 -- String (case of more than six characters)
6327 when PC_String => declare
6328 Len : constant Natural := Node.Str'Length;
6331 Dout (Img (Node) & "matching
" & Image (Node.Str.all));
6333 if (Length - Cursor) >= Len
6334 and then Node.Str.all = Subject (Cursor + 1 .. Cursor + Len)
6336 Cursor := Cursor + Len;
6343 -- String (function case)
6345 when PC_String_VF => declare
6346 U : constant VString := Node.VF.all;
6347 S : Big_String_Access;
6351 Get_String (U, S, L);
6352 Dout (Img (Node) & "matching
" & Image (S (1 .. L)));
6354 if (Length - Cursor) >= L
6355 and then S (1 .. L) = Subject (Cursor + 1 .. Cursor + L)
6357 Cursor := Cursor + L;
6364 -- String (vstring pointer case)
6366 when PC_String_VP => declare
6367 U : constant VString := Node.VP.all;
6368 S : Big_String_Access;
6372 Get_String (U, S, L);
6373 Dout (Img (Node) & "matching
" & Image (S (1 .. L)));
6375 if (Length - Cursor) >= L
6376 and then S (1 .. L) = Subject (Cursor + 1 .. Cursor + L)
6378 Cursor := Cursor + L;
6388 Dout (Img (Node) & "matching Succeed
");
6392 -- Tab (integer case)
6395 Dout (Img (Node) & "matching Tab
", Node.Nat);
6397 if Cursor <= Node.Nat then
6404 -- Tab (integer function case)
6406 when PC_Tab_NF => declare
6407 N : constant Natural := Node.NF.all;
6410 Dout (Img (Node) & "matching Tab
", N);
6420 -- Tab (integer pointer case)
6423 Dout (Img (Node) & "matching Tab
", Node.NP.all);
6425 if Cursor <= Node.NP.all then
6426 Cursor := Node.NP.all;
6432 -- Unanchored movement
6434 when PC_Unanchored =>
6435 Dout ("attempting to move anchor point
");
6437 -- All done if we tried every position
6439 if Cursor > Length then
6442 -- Otherwise extend the anchor point, and restack ourself
6445 Cursor := Cursor + 1;
6450 -- Write immediate. This node performs the actual write
6452 when PC_Write_Imm =>
6453 Dout (Img (Node) & "executing immediate write
of " &
6454 Subject (Stack (Stack_Base - 1).Cursor + 1 .. Cursor));
6458 Subject (Stack (Stack_Base - 1).Cursor + 1 .. Cursor));
6462 -- Write on match. This node sets up for the eventual write
6464 when PC_Write_OnM =>
6465 Dout (Img (Node) & "registering deferred write
");
6466 Stack (Stack_Base - 1).Node := Node;
6467 Push (CP_Assign'Access);
6473 -- We are NOT allowed to fall though this case statement, since every
6474 -- match routine must end by executing a goto to the appropriate point
6475 -- in the finite state machine model.
6477 pragma Warnings (Off);
6479 pragma Warnings (On);
6482 end GNAT.Spitbol.Patterns;