mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-07 23:32:42 +01:00
Removed first slash in [[ref:libraries/...]] wiki links.
git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1612 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
@@ -5,7 +5,7 @@ The best way to speed up a program is of course to improve the algorithms and da
|
||||
|
||||
Try to keep the number of classes and objects in your system as low as possible to ensure maximum efficiency. This should never hinder the design of the system, though.
|
||||
|
||||
You can also use the functionality provided by the [[ref:/libraries/base/reference/memory_chart|MEMORY]] class to tweak the garbage collector behavior according to your needs. However, be careful with this, since providing erroneous parameters might lead to memory leaks, huge memory consumption, or on the contrary a dramatic slow down of the application. If you are not entirely sure what a parameter is for, avoid changing it. The default values should fit for most standard applications.
|
||||
You can also use the functionality provided by the [[ref:libraries/base/reference/memory_chart|MEMORY]] class to tweak the garbage collector behavior according to your needs. However, be careful with this, since providing erroneous parameters might lead to memory leaks, huge memory consumption, or on the contrary a dramatic slow down of the application. If you are not entirely sure what a parameter is for, avoid changing it. The default values should fit for most standard applications.
|
||||
|
||||
On top of that, EiffelStudio provides powerful optimizations, some being done automatically, others being configurable. To obtain a maximum efficiency, it is recommended to [[Generating executables|Finalize]] your program from scratch and without using precompiled libraries.
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
[[Property:title|Handling exceptions]]
|
||||
[[Property:weight|4]]
|
||||
[[Property:uuid|43ce73b9-3ac4-4f71-34a3-f359a66d9082]]
|
||||
It is possible to raise and catch exceptions in Eiffel. Catching exceptions is done by using the rescue keyword. The [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] class provides helper features to analyze the caught exception and handle it.
|
||||
It is possible to raise and catch exceptions in Eiffel. Catching exceptions is done by using the rescue keyword. The [[ref:libraries/base/reference/exceptions_chart|EXCEPTIONS]] class provides helper features to analyze the caught exception and handle it.
|
||||
|
||||
The [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] class also provides ways to raise exception, via its feature [[ref:libraries/base/reference/exceptions_flatshort|raise]] .
|
||||
The [[ref:libraries/base/reference/exceptions_chart|EXCEPTIONS]] class also provides ways to raise exception, via its feature [[ref:libraries/base/reference/exceptions_flatshort|raise]] .
|
||||
|
||||
When an exception is raised while the application is being debugged, the application stops immediately and the debugger displays the context in which the exception occurred, whether or not the exception is rescued.
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ By default the profiler will profile the entire program. However it is possible
|
||||
* You must [[Generating executables|recompile]] your project for the changes to take effect.
|
||||
|
||||
It is also possible to dynamically start and stop the profiler in a program. To do this:
|
||||
* Create an object of type [[ref:/libraries/base/reference/profiling_setting_chart|PROFILING_SETTING]] .
|
||||
* Create an object of type [[ref:libraries/base/reference/profiling_setting_chart|PROFILING_SETTING]] .
|
||||
* Call [[ref:libraries/base/reference/profiling_setting_flatshort|start_profiling]] on this object to start the profiler.
|
||||
* Call [[ref:libraries/base/reference/profiling_setting_flatshort|stop_profiling]] on this object to stop the profiler.
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ Last, here's the output when '''Trace''' is '''True''' for both the root cluster
|
||||
=Dynamic control=
|
||||
|
||||
It is also possible to enable and disable the trace dynamically. To do this:
|
||||
* Create an object of type [[ref:/libraries/base/reference/tracing_setting_chart|TRACING_SETTING]] .
|
||||
* Create an object of type [[ref:libraries/base/reference/tracing_setting_chart|TRACING_SETTING]] .
|
||||
* Call [[ref:libraries/base/reference/tracing_setting_flatshort|enable_tracing]] on this object to start the trace.
|
||||
* Call [[ref:libraries/base/reference/tracing_setting_flatshort|disable_tracing]] on this object to stop the trace.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
In both trees of the [[Object tool|object tool]], objects are displayed. The values displayed for each object fall into two categories: the object's attributes (grouped under the '''attributes''' folder [[Image:feature-attribute-icon]] ) and its once routines (grouped under the '''once routines''' folder [[Image:feature-once-icon]] ).
|
||||
|
||||
The following symbol scheme is used to categorize each item:
|
||||
* [[Image:debugger-object-immediate-icon]] An attribute of a basic Eiffel type, such as [[ref:/libraries/base/reference/kernel/integer_chart.xml|INTEGER]] or [[ref:/libraries/base/reference/kernel/classic/double_chart.xml|DOUBLE]]
|
||||
* [[Image:debugger-object-immediate-icon]] An attribute of a basic Eiffel type, such as [[ref:libraries/base/reference/kernel/integer_chart.xml|INTEGER]] or [[ref:libraries/base/reference/kernel/classic/double_chart.xml|DOUBLE]]
|
||||
* [[Image:debugger-object-eiffel-icon]] An attribute that is a reference to an object
|
||||
* [[Image:debugger-object-void-icon]] A Void reference
|
||||
* [[Image:debugger-object-expanded-icon]] An object that is expanded
|
||||
|
||||
@@ -6,7 +6,7 @@ For virtually any object displayed in the Object tool, it is possible for the de
|
||||
In order to have the instances of a class display such a string in the object tool, make the class an heir to class <eiffel>DEBUG_OUTPUT</eiffel>. Then implement the feature <eiffel>debug_output</eiffel> to return the string to be displayed. At run-time, the debugger will automatically query this feature on all objects that define it, and then will display the results in the object tool and the [[Expression evaluation|evaluation tool]].
|
||||
|
||||
|
||||
{{sample|The numeric *<code>_REF</code> classes inherit (through class <eiffel>NUMERIC</eiffel>) from the class <eiffel>DEBUG_OUTPUT</eiffel> so that it is possible to see immediately the value of *<code>_REF</code> objects in the Object tool. The *<code>_REF</code> classes are reference versions of the basic Eiffel classes such as [[ref:/libraries/base/reference/kernel/integer_chart.xml|INTEGER]] and [[ref:/libraries/base/reference/kernel/classic/double_chart.xml|DOUBLE]]. So, without <eiffel>DEBUG_OUTPUT</eiffel>, if you wanted to see, for example, the value of the [[ref:/libraries/base/reference/kernel/integer_chart.xml|INTEGER]] associated with an instance of [[ref:/libraries/base/reference/kernel/integer_ref_chart.xml|INTEGER_REF]] displayed in the Object tool, you would have expand the reference first.}}
|
||||
{{sample|The numeric *<code>_REF</code> classes inherit (through class <eiffel>NUMERIC</eiffel>) from the class <eiffel>DEBUG_OUTPUT</eiffel> so that it is possible to see immediately the value of *<code>_REF</code> objects in the Object tool. The *<code>_REF</code> classes are reference versions of the basic Eiffel classes such as [[ref:libraries/base/reference/kernel/integer_chart.xml|INTEGER]] and [[ref:libraries/base/reference/kernel/classic/double_chart.xml|DOUBLE]]. So, without <eiffel>DEBUG_OUTPUT</eiffel>, if you wanted to see, for example, the value of the [[ref:libraries/base/reference/kernel/integer_chart.xml|INTEGER]] associated with an instance of [[ref:libraries/base/reference/kernel/integer_ref_chart.xml|INTEGER_REF]] displayed in the Object tool, you would have expand the reference first.}}
|
||||
|
||||
|
||||
{{tip|If an object has a long string output or an output with carriage returns, for instance, pick-and-drop it to the expanded display command [[Image:debugger-expand-info-icon]] in the object tool. }}
|
||||
|
||||
@@ -17,7 +17,7 @@ When an exception occurs (for instance, an assertion violation), the object tool
|
||||
|
||||
All objects can be expanded to see the values of their attributes. They are also pickable, so that it is possible to drop them onto the Object tool, an [[Expression evaluation|expression evaluator tool]] (also know as Watch tool), or an editor.
|
||||
|
||||
It is also possible to use the [[Set slice size command|set slice size command]] with [[ref:/libraries/base/reference/special_chart|SPECIAL]] objects or [[ref:/libraries/base/reference/native_array_chart|NATIVE_ARRAY]] (.NET) objects.
|
||||
It is also possible to use the [[Set slice size command|set slice size command]] with [[ref:libraries/base/reference/special_chart|SPECIAL]] objects or [[ref:libraries/base/reference/native_array_chart|NATIVE_ARRAY]] (.NET) objects.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Depending the nature of the dropped object, you can view it with one or more of
|
||||
** <code>deep_physicial_size</code>
|
||||
** <code>physical_size</code>
|
||||
|
||||
{{note|The "string display" viewer is available for objects with a string representation, for instance objects whose types conform to [[ref:/libraries/base/reference/string_8_chart|STRING_8]] or conform to [[ref:/libraries/base/reference/debug_output_chart|DEBUG_OUTPUT]] (see [[Debug output|Debug Output]]. )}}
|
||||
{{note|The "string display" viewer is available for objects with a string representation, for instance objects whose types conform to [[ref:libraries/base/reference/string_8_chart|STRING_8]] or conform to [[ref:libraries/base/reference/debug_output_chart|DEBUG_OUTPUT]] (see [[Debug output|Debug Output]]. )}}
|
||||
|
||||
{{note|The "XML display" is available for objects eligible for "String display", and whose string representation has XML content. The viewer displays XML in a tree-enabled grid.}}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[Property:title|Set slice size command]]
|
||||
[[Property:weight|3]]
|
||||
[[Property:uuid|ce2469a3-cf00-554e-47bd-5e8b2fdbc783]]
|
||||
Located in the object tool toolbar, this command [[Image:debugger-set-sizes-icon]] changes the display size of special objects (i.e. objects whose class is [[ref:/libraries/base/reference/special_chart|SPECIAL]] ). Because special objects may contain thousands of attributes, only the first fifty are displayed by default. If left-clicked, a dialog is popped up that sets the exploration indices of special objects that will be loaded in the future.
|
||||
Located in the object tool toolbar, this command [[Image:debugger-set-sizes-icon]] changes the display size of special objects (i.e. objects whose class is [[ref:libraries/base/reference/special_chart|SPECIAL]] ). Because special objects may contain thousands of attributes, only the first fifty are displayed by default. If left-clicked, a dialog is popped up that sets the exploration indices of special objects that will be loaded in the future.
|
||||
|
||||
This pop-up also shows the "Maximum displayed string size" in the grid ([[Object tool|object tool]], or the [[Expression evaluation|watch tools]]).
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ A container can be studied from three viewpoints: access, storage and traversal.
|
||||
* The '''storage''' criterion affects how the items are put together. For example some containers are finite, others potentially infinite; among finite structures, some are bounded, others unbounded.
|
||||
* The '''traversal''' criterion affects how, if in any way, the items of a container can be traversed. A traversal is a mechanism which makes it possible to examine each item of a container once, in a clearly specified order. For example some containers can be traversed sequentially, in one direction or two; tree structures lend themselves to preorder, postorder and breadth-first traversals.
|
||||
|
||||
For each of these criteria the Base library offers a single-inheritance hierarchy of deferred classes. The top of the access hierarchy is class [[ref:libraries/base/reference/collection_chart|COLLECTION]] ; the top of the storage hierarchy is class [[ref:/libraries/base/reference/box_chart|BOX]] ; the top of the traversal hierarchy is class [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] . These three classes are heirs of the most general class [[ref:libraries/base/reference/container_chart|CONTAINER]] .
|
||||
For each of these criteria the Base library offers a single-inheritance hierarchy of deferred classes. The top of the access hierarchy is class [[ref:libraries/base/reference/collection_chart|COLLECTION]] ; the top of the storage hierarchy is class [[ref:libraries/base/reference/box_chart|BOX]] ; the top of the traversal hierarchy is class [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] . These three classes are heirs of the most general class [[ref:libraries/base/reference/container_chart|CONTAINER]] .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
[[Property:title|EiffelBase Data Structures, Lists]]
|
||||
[[Property:weight|1]]
|
||||
[[Property:uuid|23f540e0-16d5-807c-30af-74d3416a5709]]
|
||||
Many applications need sequential structures, also called linear structures, in particular lists and circular chains. Apart from three classes describing individual list cells, all the classes involved are descendants of class [[ref:/libraries/base/reference/linear_chart|LINEAR]] , one of the deferred classes describing general traversal properties and introduced in the chapter that described the general data structure taxonomy. More precisely, all but one of the classes of interest for the present discussion are descendants, direct or indirect, from a class called [[ref:/libraries/base/reference/chain_chart|CHAIN]] which describes general sequential structures possessing a cursor as well as insertion properties. The exception is class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] , which describes infinite structures; all the others describe finite structures. <br/>
|
||||
[[ref:/libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] , which describes a more general notion of sequence. [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] is a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] . There are two main categories of sequential structures: some, called circular chains, are cyclic; others, called lists, are not. Another distinction exists between dynamic structures, which may be extended at will, and fixed ones, which have a bounded capacity. <br/>
|
||||
Many applications need sequential structures, also called linear structures, in particular lists and circular chains. Apart from three classes describing individual list cells, all the classes involved are descendants of class [[ref:libraries/base/reference/linear_chart|LINEAR]] , one of the deferred classes describing general traversal properties and introduced in the chapter that described the general data structure taxonomy. More precisely, all but one of the classes of interest for the present discussion are descendants, direct or indirect, from a class called [[ref:libraries/base/reference/chain_chart|CHAIN]] which describes general sequential structures possessing a cursor as well as insertion properties. The exception is class [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] , which describes infinite structures; all the others describe finite structures. <br/>
|
||||
[[ref:libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] , which describes a more general notion of sequence. [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] is a descendant of [[ref:libraries/base/reference/linear_chart|LINEAR]] . There are two main categories of sequential structures: some, called circular chains, are cyclic; others, called lists, are not. Another distinction exists between dynamic structures, which may be extended at will, and fixed ones, which have a bounded capacity. <br/>
|
||||
In all of the structures under review you may insert two or more occurrences of a given item in such a way that the occurrences are distinguishable. In other words, the structures are bags rather than just sets, although it is possible to use them to implement sets.
|
||||
|
||||
=Higher Level Traversal Classes=
|
||||
|
||||
The list and chain classes are characterized, for their traversal properties, as being linear and, more precisely, bilinear. In the traversal hierarchy, the relevant deferred classes are [[ref:/libraries/base/reference/linear_chart|LINEAR]] and [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , introduced in the [[EiffelBase, Abstract Container Structures: The Taxonomy|discussion]] of the general taxonomy.
|
||||
The list and chain classes are characterized, for their traversal properties, as being linear and, more precisely, bilinear. In the traversal hierarchy, the relevant deferred classes are [[ref:libraries/base/reference/linear_chart|LINEAR]] and [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , introduced in the [[EiffelBase, Abstract Container Structures: The Taxonomy|discussion]] of the general taxonomy.
|
||||
|
||||
==Linear structures==
|
||||
|
||||
[[ref:/libraries/base/reference/linear_chart|LINEAR]] describes sequential structures that may be traversed one way. It introduces in particular the following features, illustrated on the figure below:
|
||||
[[ref:libraries/base/reference/linear_chart|LINEAR]] describes sequential structures that may be traversed one way. It introduces in particular the following features, illustrated on the figure below:
|
||||
* <eiffel>after</eiffel>, a boolean-valued query which determines whether you have moved past the last position (a more precise specification is given below).
|
||||
* <eiffel>off</eiffel>, a boolean-valued query which is false if and only if there is no item at the current position; for [[ref:/libraries/base/reference/linear_chart|LINEAR]] this is the same as:
|
||||
* <eiffel>off</eiffel>, a boolean-valued query which is false if and only if there is no item at the current position; for [[ref:libraries/base/reference/linear_chart|LINEAR]] this is the same as:
|
||||
<code>is_empty and not after</code>
|
||||
|
||||
* <eiffel>item</eiffel>, a query which returns the item at the current position - provided of course there is one, as expressed by the precondition:
|
||||
@@ -32,11 +32,11 @@ The list and chain classes are characterized, for their traversal properties, as
|
||||
|
||||
There is also a procedure <eiffel>search</eiffel> with one argument, which determines whether the value of that argument appears in the structure at or after the current position, and if not makes <eiffel>after</eiffel> become true. This procedure is internally used by the default implementation of the <eiffel>has</eiffel> function (the general membership test) for linear structures. Like has for all containers, <eiffel>search</eiffel> uses object or reference equality depending on the value set for <eiffel>object_comparison</eiffel>.
|
||||
|
||||
An invariant property of [[ref:/libraries/base/reference/linear_chart|LINEAR]] structures is that the current position may go off one step past the last item if any, but no further. The precondition of <eiffel>forth</eiffel> - not after - helps ensure this. The first item (if any) being at position 1, the maximum allowable position is <eiffel>count</eiffel> + 1, where <eiffel>count</eiffel> is the number of items.
|
||||
An invariant property of [[ref:libraries/base/reference/linear_chart|LINEAR]] structures is that the current position may go off one step past the last item if any, but no further. The precondition of <eiffel>forth</eiffel> - not after - helps ensure this. The first item (if any) being at position 1, the maximum allowable position is <eiffel>count</eiffel> + 1, where <eiffel>count</eiffel> is the number of items.
|
||||
|
||||
==Bilinear structures==
|
||||
|
||||
[[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] describes linear structures which may be traversed both ways. It inherits from [[ref:/libraries/base/reference/linear_chart|LINEAR]] and extends it with two new features which ensure complete symmetry between the two directions of movement:
|
||||
[[ref:libraries/base/reference/bilinear_chart|BILINEAR]] describes linear structures which may be traversed both ways. It inherits from [[ref:libraries/base/reference/linear_chart|LINEAR]] and extends it with two new features which ensure complete symmetry between the two directions of movement:
|
||||
* <eiffel>before</eiffel>, a boolean-valued query which determines whether you have moved to the left of the first position (a more precise specification is given below).
|
||||
* <eiffel>back</eiffel>, a command to move backward by one position; the precondition is not before.
|
||||
|
||||
@@ -48,20 +48,20 @@ For bilinear structures the position can range between 0 (not just 1) and count
|
||||
|
||||
==Invariant properties for after, before and off==
|
||||
|
||||
The redefinition of <eiffel>off</eiffel> illustrates a general methodological advice about invariants: be careful about not over-constraining the invariant by including properties that may be made more general in descendants. It might have been tempting to include in [[ref:/libraries/base/reference/linear_chart|LINEAR]] an invariant clause of the form
|
||||
The redefinition of <eiffel>off</eiffel> illustrates a general methodological advice about invariants: be careful about not over-constraining the invariant by including properties that may be made more general in descendants. It might have been tempting to include in [[ref:libraries/base/reference/linear_chart|LINEAR]] an invariant clause of the form
|
||||
<code>
|
||||
off = is_empty or after</code>
|
||||
|
||||
This property, however, would be too constraining. More precisely, it is always true that the right-hand side implies the left-hand-side: if a linear structure is either empty or after, then it is off. But the converse is not true, since certain kinds of linear structure, for example bilinear ones, may be off but neither empty nor after. <br/>
|
||||
The actual invariant for class [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] is obtained in three stages. In class [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] the feature off is deferred and a basic property of that feature is expressed by the invariant clause
|
||||
The actual invariant for class [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] is obtained in three stages. In class [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] the feature off is deferred and a basic property of that feature is expressed by the invariant clause
|
||||
<code>
|
||||
empty_constraint:is_empty implies off</code>
|
||||
|
||||
In [[ref:/libraries/base/reference/linear_chart|LINEAR]] , feature <eiffel>off</eiffel> is effected through an implementation which returns the value of the expression <eiffel>is_empty</eiffel> or <eiffel>after</eiffel>. The class adds an invariant clause which, however, says less than the implementation to leave some room for variation:
|
||||
In [[ref:libraries/base/reference/linear_chart|LINEAR]] , feature <eiffel>off</eiffel> is effected through an implementation which returns the value of the expression <eiffel>is_empty</eiffel> or <eiffel>after</eiffel>. The class adds an invariant clause which, however, says less than the implementation to leave some room for variation:
|
||||
<code>
|
||||
after_constraint:after implies off</code>
|
||||
|
||||
Finally [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , an heir of [[ref:/libraries/base/reference/linear_chart|LINEAR]] , redefines <eiffel>off</eiffel> to return the value of the expression
|
||||
Finally [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , an heir of [[ref:libraries/base/reference/linear_chart|LINEAR]] , redefines <eiffel>off</eiffel> to return the value of the expression
|
||||
<code>
|
||||
before or after</code>
|
||||
|
||||
@@ -73,7 +73,7 @@ The new implementation of <eiffel>off</eiffel>
|
||||
<code>
|
||||
after or before</code>
|
||||
|
||||
would not guarantee the invariant clause inherited from [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] were it not for another clause introduced in [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] :
|
||||
would not guarantee the invariant clause inherited from [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] were it not for another clause introduced in [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] :
|
||||
<code>
|
||||
empty_property: is_empty implies (after or before )</code>
|
||||
|
||||
@@ -81,7 +81,7 @@ which indicates that an empty bilinear structure must always be <eiffel>after</e
|
||||
<code>
|
||||
not_both: not(after and before)</code>
|
||||
|
||||
The flat-short form of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] shows the complete reconstructed invariant:
|
||||
The flat-short form of [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] shows the complete reconstructed invariant:
|
||||
<code>
|
||||
not_both: not (after and before)
|
||||
empty_property: is_empty implies (after or before)
|
||||
@@ -104,13 +104,13 @@ For a more general form of this scheme, applicable to circular chains as well as
|
||||
end</code>
|
||||
|
||||
The value of <code>lin.off</code> is always true for an empty structure, so in this case the loop will, correctly, execute only its initialization actions if present. <br/>
|
||||
This is a very common pattern, which you will find in the library classes themselves (for example has is implemented in this way) and many application clients. The iterator classes corresponding to linear structures ([[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ) turn this pattern and several related ones into actual reusable routines. <br/>
|
||||
This is a very common pattern, which you will find in the library classes themselves (for example has is implemented in this way) and many application clients. The iterator classes corresponding to linear structures ([[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ) turn this pattern and several related ones into actual reusable routines. <br/>
|
||||
For bilinear structures there is another traversal mechanism going backward rather than forward; it is the same as above except that <eiffel>finish</eiffel> replaces <eiffel>start</eiffel> and <eiffel>back</eiffel> replaces <eiffel>finish</eiffel>. The exit condition remains <eiffel>off</eiffel> since <eiffel>before</eiffel>, like <eiffel>after</eiffel>, implies <eiffel>off</eiffel>.
|
||||
|
||||
==A precise view of after and before==
|
||||
|
||||
Getting the specification of <eiffel>after</eiffel> and before <eiffel>right</eiffel>, so that it will handle all cases properly, requires some care. <br/>
|
||||
For every one of the structures under discussion there is a notion of current position, which we may call the cursor position even though for the moment the cursor is a virtual notion only. (Actual cursor objects will come later when we combine [[ref:/libraries/base/reference/linear_chart|LINEAR]] , [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] and other classes from the traversal hierarchy with [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] and other classes from the collection hierarchy.) The informal definition is that <eiffel>after</eiffel> is true if and only if the cursor - in this informal sense of a fictitious marker signaling the current position - is one position after the last item, if any, and that <eiffel>before</eiffel> is true if and only if the cursor is one position before the first item. When the cursor is on any of the items, <eiffel>after</eiffel> and <eiffel>before</eiffel> are false; <eiffel>after</eiffel> holds when the cursor is to the right of the last item, and <eiffel>before</eiffel> when it is to the left of the first item. This leaves open the question of what conventions to take for an empty structure. If iteration schemes of the above type are to work, then <eiffel>after</eiffel> must be true for an empty structure. For a bilinear structure, however, we should have total symmetry between the two pairs of features
|
||||
For every one of the structures under discussion there is a notion of current position, which we may call the cursor position even though for the moment the cursor is a virtual notion only. (Actual cursor objects will come later when we combine [[ref:libraries/base/reference/linear_chart|LINEAR]] , [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] and other classes from the traversal hierarchy with [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] and other classes from the collection hierarchy.) The informal definition is that <eiffel>after</eiffel> is true if and only if the cursor - in this informal sense of a fictitious marker signaling the current position - is one position after the last item, if any, and that <eiffel>before</eiffel> is true if and only if the cursor is one position before the first item. When the cursor is on any of the items, <eiffel>after</eiffel> and <eiffel>before</eiffel> are false; <eiffel>after</eiffel> holds when the cursor is to the right of the last item, and <eiffel>before</eiffel> when it is to the left of the first item. This leaves open the question of what conventions to take for an empty structure. If iteration schemes of the above type are to work, then <eiffel>after</eiffel> must be true for an empty structure. For a bilinear structure, however, we should have total symmetry between the two pairs of features
|
||||
* <eiffel>start</eiffel>, <eiffel>forth</eiffel>, <eiffel>after</eiffel>.
|
||||
* <eiffel>finish</eiffel>, <eiffel>back</eiffel>, <eiffel>before</eiffel>.
|
||||
|
||||
@@ -128,7 +128,7 @@ When a structure is created, some initializations will have to be made; the defa
|
||||
<code>
|
||||
if after and not is_empty then...</code>
|
||||
|
||||
The solution finally retained for the Base libraries uses a different technique, which has turned out to be preferable. The idea is to replace the conceptual picture by one in which there are always two fictitious sentinel items. The two sentinel items are only present conceptually. They are of course not taken into account for the computation of <eiffel>count</eiffel> and, although it is possible to conceive of an implementation which would actually reserve space for them (for example in an array representation), none of the implementations used in Base for the classes of this documentation and other descendants of [[ref:/libraries/base/reference/linear_chart|LINEAR]] do. The only purpose of the sentinels is to provide two valid theoretical cursor positions, which exist regardless of the number of actual (non-sentinel) items in the structure. <br/>
|
||||
The solution finally retained for the Base libraries uses a different technique, which has turned out to be preferable. The idea is to replace the conceptual picture by one in which there are always two fictitious sentinel items. The two sentinel items are only present conceptually. They are of course not taken into account for the computation of <eiffel>count</eiffel> and, although it is possible to conceive of an implementation which would actually reserve space for them (for example in an array representation), none of the implementations used in Base for the classes of this documentation and other descendants of [[ref:libraries/base/reference/linear_chart|LINEAR]] do. The only purpose of the sentinels is to provide two valid theoretical cursor positions, which exist regardless of the number of actual (non-sentinel) items in the structure. <br/>
|
||||
The sentinel items always appear at positions 0 and <eiffel>count</eiffel> + 1; this property is true even if the structure is empty of items, in which case count is zero. As a result, the following properties are part of the invariant:
|
||||
<code>
|
||||
0 <= index
|
||||
@@ -151,22 +151,22 @@ Finally, the only way to make delicate design decisions is to express the issues
|
||||
|
||||
=Sequences And Chains=
|
||||
|
||||
Still deferred, classes [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] and[[ref:/libraries/base/reference/chain_chart|CHAIN]] provide the basis for all list and chain classes, as well as for many trees and for dispensers. <br/>
|
||||
SEQUENCE is constructed with the full extent of the technique described in the discussion of the taxonomy: using multiple inheritance to combine one class each from the access, traversal and storage hierarchy. [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] indeed has three parents:
|
||||
* [[ref:/libraries/base/reference/active_chart|ACTIVE]] gives the access properties. A sequence is an active structure with a notion of current item. Remember that active structures are a special case of bags.
|
||||
* [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , as studied above, indicates that a sequence may be traversed both ways.
|
||||
* FINITE, from the storage hierarchy, indicates that the class describes finite sequences. (A class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] is also present, as described below.)
|
||||
Still deferred, classes [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] and[[ref:libraries/base/reference/chain_chart|CHAIN]] provide the basis for all list and chain classes, as well as for many trees and for dispensers. <br/>
|
||||
SEQUENCE is constructed with the full extent of the technique described in the discussion of the taxonomy: using multiple inheritance to combine one class each from the access, traversal and storage hierarchy. [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] indeed has three parents:
|
||||
* [[ref:libraries/base/reference/active_chart|ACTIVE]] gives the access properties. A sequence is an active structure with a notion of current item. Remember that active structures are a special case of bags.
|
||||
* [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , as studied above, indicates that a sequence may be traversed both ways.
|
||||
* FINITE, from the storage hierarchy, indicates that the class describes finite sequences. (A class [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] is also present, as described below.)
|
||||
|
||||
To the features of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] principally adds features for adding, changing and removing items. A few procedures in particular serve to insert items at the end:
|
||||
To the features of [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] principally adds features for adding, changing and removing items. A few procedures in particular serve to insert items at the end:
|
||||
* <code>s .put ( v )</code> adds v at the end of a sequence s.
|
||||
* <eiffel> extend</eiffel> and <eiffel>force</eiffel>, at the [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] level, do the same as <eiffel>put</eiffel>.
|
||||
* <eiffel> extend</eiffel> and <eiffel>force</eiffel>, at the [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] level, do the same as <eiffel>put</eiffel>.
|
||||
* <code>s .append ( s1 )</code> adds to the end of s the items of s1 (another sequence), preserving their s1 order.
|
||||
|
||||
Other procedures work on the current position:
|
||||
* <code>s.</code><eiffel>remove</eiffel> removes the item at current position.
|
||||
* <code>s.replace ( v )</code> replaces by v the item at current position.
|
||||
|
||||
SEQUENCE, however, does not provide a procedure to insert an item at the current position, since not all implementations of sequences support this possibility; you will find it in descendants of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] seen below. <br/>
|
||||
SEQUENCE, however, does not provide a procedure to insert an item at the current position, since not all implementations of sequences support this possibility; you will find it in descendants of [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] seen below. <br/>
|
||||
Yet another group of features are based on the first occurrence of a certain item, or on all occurrences:
|
||||
* <code>s.prune ( v ) removes the first occurrence of v in s</code>, if any.
|
||||
* <code>s.prune_all ( v ) removes all occurrences of v</code>.
|
||||
@@ -176,16 +176,16 @@ These procedures have various abstract preconditions: <code>s .extendible for ad
|
||||
==Chains==
|
||||
|
||||
Chains are sequences with a few more properties: items may be accessed through their indices, and it is possible to define cursor objects attached to individual items. <br/>
|
||||
Class [[ref:/libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] . It gets its access properties from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] (which adds the notion of cursor to the features of [[ref:/libraries/base/reference/active_chart|ACTIVE]] , already present in [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] ) and is also an heir of [[ref:/libraries/base/reference/indexable_chart|INDEXABLE]] . This ancestry implies in particular the presence of the following features:
|
||||
* <eiffel>cursor</eiffel>, from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which makes it possible to keep a reference to an item of the structure.
|
||||
* <eiffel>i_th</eiffel> and <eiffel>put_i_th</eiffel> from [[ref:/libraries/base/reference/table_chart|TABLE]] , via [[ref:/libraries/base/reference/indexable_chart|INDEXABLE]] , which make it possible to access and replace the value of an item given by its integer index.
|
||||
Class [[ref:libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] . It gets its access properties from [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] (which adds the notion of cursor to the features of [[ref:libraries/base/reference/active_chart|ACTIVE]] , already present in [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] ) and is also an heir of [[ref:libraries/base/reference/indexable_chart|INDEXABLE]] . This ancestry implies in particular the presence of the following features:
|
||||
* <eiffel>cursor</eiffel>, from [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which makes it possible to keep a reference to an item of the structure.
|
||||
* <eiffel>i_th</eiffel> and <eiffel>put_i_th</eiffel> from [[ref:libraries/base/reference/table_chart|TABLE]] , via [[ref:libraries/base/reference/indexable_chart|INDEXABLE]] , which make it possible to access and replace the value of an item given by its integer index.
|
||||
|
||||
These features were called <eiffel>item</eiffel> and <eiffel>put</eiffel> in [[ref:/libraries/base/reference/table_chart|TABLE]] , but are renamed here to remove the conflict with homonymous features from [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] . <br/>
|
||||
Procedure <eiffel>put</eiffel> for chains is the version obtained from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which has the same effect as <eiffel>replace</eiffel> - replacing the value of the item at cursor position. The <eiffel>put</eiffel> procedure from [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] is renamed <eiffel>sequence_ put</eiffel>. This feature is not exported by [[ref:/libraries/base/reference/chain_chart|CHAIN]] , however, since its effect (adding an item at the end) may be obtained through the simpler name <eiffel>extend</eiffel>.
|
||||
These features were called <eiffel>item</eiffel> and <eiffel>put</eiffel> in [[ref:libraries/base/reference/table_chart|TABLE]] , but are renamed here to remove the conflict with homonymous features from [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] . <br/>
|
||||
Procedure <eiffel>put</eiffel> for chains is the version obtained from [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which has the same effect as <eiffel>replace</eiffel> - replacing the value of the item at cursor position. The <eiffel>put</eiffel> procedure from [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] is renamed <eiffel>sequence_ put</eiffel>. This feature is not exported by [[ref:libraries/base/reference/chain_chart|CHAIN]] , however, since its effect (adding an item at the end) may be obtained through the simpler name <eiffel>extend</eiffel>.
|
||||
|
||||
==Dynamic chains==
|
||||
|
||||
By default, chains can only be extended at the end, through <eiffel>extend</eiffel> and <eiffel>sequence_put</eiffel>. Of particular interest are those chains where clients can insert and remove items at any position. Such chains are said to be dynamic, and described by [[ref:/libraries/base/reference/chain_chart|CHAIN]] 's heir [[ref:/libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] . The new features are predictable:
|
||||
By default, chains can only be extended at the end, through <eiffel>extend</eiffel> and <eiffel>sequence_put</eiffel>. Of particular interest are those chains where clients can insert and remove items at any position. Such chains are said to be dynamic, and described by [[ref:libraries/base/reference/chain_chart|CHAIN]] 's heir [[ref:libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] . The new features are predictable:
|
||||
* Procedure <eiffel>put_front</eiffel> adds an item before the first. (As noted, the procedures to add an item after the last are already available in chains.)
|
||||
* Procedures <eiffel>put_left</eiffel> and <eiffel>put_right</eiffel> add an item at the left and right of the cursor position.
|
||||
* Procedures <eiffel>remove_left</eiffel> and remove_right remove an item at the left and right or the cursor position.
|
||||
@@ -198,17 +198,17 @@ The class also provides implementations of <eiffel>prune</eiffel>, <eiffel>prune
|
||||
A chain is a finite sequential structure. This property means that items are arranged in a linear order and may be traversed from the first to the last. To do this you may use a loop of the form shown above, based on procedures <eiffel>start</eiffel> and <eiffel>forth</eiffel>. <br/>
|
||||
This property leaves room for several variants. In particular chains may be straight or circular.
|
||||
* A straight chain, which from now on will be called a list, has a beginning and an end.
|
||||
* A circular chain, as represented by class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] and its descendants, has a much more flexible notion of first item. It is organized so that every item has a successor.
|
||||
* A circular chain, as represented by class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] and its descendants, has a much more flexible notion of first item. It is organized so that every item has a successor.
|
||||
|
||||
This representation is conceptual only; in fact the implementations of circular chains found in the Base libraries are based on lists, implemented in one of the ways described below (in particular linked and arrayed). <br/>
|
||||
The major originality of circular chains is that unless the structure is empty procedure <eiffel>forth</eiffel> is always applicable: it will cycle past the last item, coming back to the <br/>
|
||||
first. The symmetric property applies to <eiffel>back</eiffel>. The cyclic nature of <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular chains is expressed precisely by the assertions. The version of <eiffel>forth</eiffel> for class [[ref:/libraries/base/reference/chain_chart|CHAIN]] , which comes from [[ref:/libraries/base/reference/linear_chart|LINEAR]] , has precondition
|
||||
first. The symmetric property applies to <eiffel>back</eiffel>. The cyclic nature of <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular chains is expressed precisely by the assertions. The version of <eiffel>forth</eiffel> for class [[ref:libraries/base/reference/chain_chart|CHAIN]] , which comes from [[ref:libraries/base/reference/linear_chart|LINEAR]] , has precondition
|
||||
<code>not after</code>
|
||||
|
||||
Similarly, the precondition for back is
|
||||
<code>not before</code>
|
||||
|
||||
For lists, after becomes true when the cursor moves past the last item. For circular chains, however, after and before are never true except for an empty structure; this is expressed by the invariant clauses of class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] :
|
||||
For lists, after becomes true when the cursor moves past the last item. For circular chains, however, after and before are never true except for an empty structure; this is expressed by the invariant clauses of class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] :
|
||||
<code>not before</code>
|
||||
|
||||
For a non-empty circular chain, then, you can circle forever around the items, using forth or back.
|
||||
@@ -218,7 +218,7 @@ For a non-empty circular chain, then, you can circle forever around the items, u
|
||||
For a list, the first and last items are fixed, and correspond to specific places in the physical representation. <br/>
|
||||
A circular chain also needs a notion of first item, if only to enable a client to initiate a traversal through procedure start. Similarly, there is a last item - the one just before the first in a cyclic traversal. (If the chain has just one item, it is both first and last.) <br/>
|
||||
For circular chains, however, there is no reason why the first item should always remain the same. One of the benefits that clients may expect from the use of a circular <br/>
|
||||
structure is the ability to choose any item as the logical first. Class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] offers for that purpose the procedure <eiffel>set_start</eiffel> which designates the current cursor position as the first in the circular chain. Subsequent calls to <eiffel>start</eiffel> will move the cursor to this position; calls to <eiffel>finish</eiffel> will move the cursor to the cyclically preceding position. With most implementations, there will then be two notions of first position: the logical first, which clients may freely choose through calls to <eiffel>set_start</eiffel>; and the <eiffel>physical first</eiffel>, which results from the implementation. In a representation using an array with indices from 1 to <eiffel>capacity</eiffel>, for example, the physical first is position 1, and the logical first may be any index in the permitted range. In a linked representation, there will be a cell first element corresponding to the physical first, but the logical first is any cell in the chain. <br/>
|
||||
structure is the ability to choose any item as the logical first. Class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] offers for that purpose the procedure <eiffel>set_start</eiffel> which designates the current cursor position as the first in the circular chain. Subsequent calls to <eiffel>start</eiffel> will move the cursor to this position; calls to <eiffel>finish</eiffel> will move the cursor to the cyclically preceding position. With most implementations, there will then be two notions of first position: the logical first, which clients may freely choose through calls to <eiffel>set_start</eiffel>; and the <eiffel>physical first</eiffel>, which results from the implementation. In a representation using an array with indices from 1 to <eiffel>capacity</eiffel>, for example, the physical first is position 1, and the logical first may be any index in the permitted range. In a linked representation, there will be a cell first element corresponding to the physical first, but the logical first is any cell in the chain. <br/>
|
||||
In such cases the circular chain classes have features called <eiffel>standard_first</eiffel>, <eiffel>standard_last</eiffel>, <eiffel>standard_start</eiffel> and so on, which are not exported (so that you will not see them in the flat-short forms) but serve to implement visible features such as <eiffel>first</eiffel>, <eiffel>last</eiffel> and <eiffel>forth</eiffel>. For example a possible implementation of <eiffel>forth</eiffel> for circular chains is
|
||||
<code>forth is
|
||||
-- Move cursor to next item, cyclically.
|
||||
@@ -245,7 +245,7 @@ loop
|
||||
end</code>
|
||||
|
||||
would not work if <code>lin</code> is a non-empty circular structure: <eiffel>off</eiffel> would never become true, so that the loop would forever cycle over the structure's items. The same would apply to a loop using finish and back instead of <eiffel>start</eiffel> and <eiffel>forth</eiffel>. This behavior is the natural result of the semantics defined for <eiffel>off</eiffel> , <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular structures. But it prevents us from using these features to perform a single traversal which will visit every item once. <br/>
|
||||
Using <eiffel>exhausted</eiffel> in lieu of off solves this problem. In class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] , <eiffel>exhausted</eiffel> is an attribute which is set to false by <eiffel>start</eiffel> and <eiffel>finish</eiffel>, and is set to true by <eiffel>forth</eiffel> when advancing from the last item to the first and by <eiffel>back</eiffel> when backing up from the first item to the last. So you should write the loop as
|
||||
Using <eiffel>exhausted</eiffel> in lieu of off solves this problem. In class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] , <eiffel>exhausted</eiffel> is an attribute which is set to false by <eiffel>start</eiffel> and <eiffel>finish</eiffel>, and is set to true by <eiffel>forth</eiffel> when advancing from the last item to the first and by <eiffel>back</eiffel> when backing up from the first item to the last. So you should write the loop as
|
||||
<code>from
|
||||
lin.start
|
||||
|
||||
@@ -261,18 +261,18 @@ loop
|
||||
lin.forth
|
||||
end</code>
|
||||
|
||||
This form is applicable to all linear structures, circular or not, since <eiffel>exhausted</eiffel> is introduced in class [[ref:/libraries/base/reference/linear_chart|LINEAR]] as a function which returns the same value as <eiffel>off</eiffel> .Its redefinition into an attribute, modified by <eiffel>start</eiffel>,<eiffel> finish</eiffel>, <eiffel>forth</eiffel> and <eiffel>back</eiffel>, does not occur until class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] . <br/>
|
||||
Because <eiffel>exhausted</eiffel> is more general than <eiffel>off</eiffel> , the iteration scheme just given (and its equivalent going backwards) is preferable to the earlier one using <eiffel>off </eiffel>, especially if there is any chance that the iteration might one day be applied to a lin structure that is circular. Classes of the Iteration library, in particular [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , rely on this scheme for iterating over linear structures.
|
||||
This form is applicable to all linear structures, circular or not, since <eiffel>exhausted</eiffel> is introduced in class [[ref:libraries/base/reference/linear_chart|LINEAR]] as a function which returns the same value as <eiffel>off</eiffel> .Its redefinition into an attribute, modified by <eiffel>start</eiffel>,<eiffel> finish</eiffel>, <eiffel>forth</eiffel> and <eiffel>back</eiffel>, does not occur until class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] . <br/>
|
||||
Because <eiffel>exhausted</eiffel> is more general than <eiffel>off</eiffel> , the iteration scheme just given (and its equivalent going backwards) is preferable to the earlier one using <eiffel>off </eiffel>, especially if there is any chance that the iteration might one day be applied to a lin structure that is circular. Classes of the Iteration library, in particular [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , rely on this scheme for iterating over linear structures.
|
||||
|
||||
==Dynamic structures==
|
||||
|
||||
For both lists and circular chains, the most flexible variants, said to be dynamic, allow insertions and deletions at any position. <br/>
|
||||
The corresponding classes are descendants of [[ref:/libraries/base/reference/dynamic_list_chart|DYNAMIC_LIST]] and [[ref:/libraries/base/reference/dynamic_circular_chart|DYNAMIC_CIRCULAR]] , themselves heirs of [[ref:/libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] studied above. <br/>
|
||||
The corresponding classes are descendants of [[ref:libraries/base/reference/dynamic_list_chart|DYNAMIC_LIST]] and [[ref:libraries/base/reference/dynamic_circular_chart|DYNAMIC_CIRCULAR]] , themselves heirs of [[ref:libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] studied above. <br/>
|
||||
|
||||
|
||||
==Infinite sequences==
|
||||
|
||||
Class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCES]] , built by inheritance from [[ref:/libraries/base/reference/countable_chart|COUNTABLE]] , [[ref:/libraries/base/reference/linear_chart|LINEAR]] and [[ref:/libraries/base/reference/active_chart|ACTIVE]] , is similar to [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] but describes infinite rather than finite sequences.
|
||||
Class [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCES]] , built by inheritance from [[ref:libraries/base/reference/countable_chart|COUNTABLE]] , [[ref:libraries/base/reference/linear_chart|LINEAR]] and [[ref:libraries/base/reference/active_chart|ACTIVE]] , is similar to [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] but describes infinite rather than finite sequences.
|
||||
|
||||
=Implementations=
|
||||
|
||||
@@ -285,22 +285,22 @@ as two categories with two subcategories each:
|
||||
* Linked implementations, which may be one-way or two-way.
|
||||
* Arrayed implementations, which may be resizable or fixed.
|
||||
|
||||
A linked implementation uses linked cells, each containing an item and a reference to the next cell. One-way structures are described by classes whose names begin with LINKED_, for example [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . Two-way structures use cells which, in addition to the reference to the next cell, also include a reference to the previous one. Their names begin with TWO_WAY_. <br/>
|
||||
A linked implementation uses linked cells, each containing an item and a reference to the next cell. One-way structures are described by classes whose names begin with LINKED_, for example [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] . Two-way structures use cells which, in addition to the reference to the next cell, also include a reference to the previous one. Their names begin with TWO_WAY_. <br/>
|
||||
An arrayed implementation uses an array to represent a linear structure. If the array is resizable, the corresponding class name begins with ARRAYED_, for example <br/>
|
||||
[[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] ; if not, the prefix is FIXED_.
|
||||
[[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] ; if not, the prefix is FIXED_.
|
||||
|
||||
==Linked structures==
|
||||
|
||||
A linked structure requires two classes: one, such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , describes the list proper; the other, such as [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , describes the individual list cells. The figure should help understand the difference; it describes a linked list, but the implementation of linked circular chains is similar.
|
||||
A linked structure requires two classes: one, such as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] , describes the list proper; the other, such as [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , describes the individual list cells. The figure should help understand the difference; it describes a linked list, but the implementation of linked circular chains is similar.
|
||||
|
||||
|
||||
[[Image:linked-list|fig.3: Linked list and linked cells]]
|
||||
|
||||
|
||||
The instance of type [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] shown at the top contains general information about the list, such as the number of items (<eiffel>count</eiffel>) and a reference to the first element (first). Because lists are active structures with a notion of current position, there is also a reference active to the cell at the current position. An entity declared as
|
||||
The instance of type [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] shown at the top contains general information about the list, such as the number of items (<eiffel>count</eiffel>) and a reference to the first element (first). Because lists are active structures with a notion of current position, there is also a reference active to the cell at the current position. An entity declared as
|
||||
<code>my_list: LINKED_LIST [SOME_TYPE]</code>
|
||||
|
||||
will have as its run-time value (if not void) a reference to such an object, which is really a list header. The actual list content is given by the [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] instances, each of which contains a value of type <eiffel>SOME_TYPE</eiffel> and a reference to the next item, called <eiffel>right</eiffel>. <br/>
|
||||
will have as its run-time value (if not void) a reference to such an object, which is really a list header. The actual list content is given by the [[ref:libraries/base/reference/linkable_chart|LINKABLE]] instances, each of which contains a value of type <eiffel>SOME_TYPE</eiffel> and a reference to the next item, called <eiffel>right</eiffel>. <br/>
|
||||
Clearly, a header of type <code>LINKED_LIST [SOME_TYPE]</code> will be associated with cells of type <code>LINKABLE [SOME_TYPE]</code>. <br/>
|
||||
Features such as active and first are used only for the implementation; they are not exported, and so you will not find them in the flat-short specifications, although the figures show them to illustrate the representation technique. <br/>
|
||||
A similar implementation is used for two-way-linked structures such as two-way lists and two-way circular chains.
|
||||
@@ -311,14 +311,14 @@ A similar implementation is used for two-way-linked structures such as two-way l
|
||||
|
||||
==Linked cells==
|
||||
|
||||
The classes describing list cells are descendants of a deferred class called [[ref:/libraries/base/reference/cell_chart|CELL]] , whose features are:
|
||||
The classes describing list cells are descendants of a deferred class called [[ref:libraries/base/reference/cell_chart|CELL]] , whose features are:
|
||||
* <eiffel>item</eiffel>, the contents of the cell.
|
||||
* <eiffel>put </eiffel> <code>( v :</code> <code>like </code> <eiffel>item</eiffel> <code>)</code>, which replaces the contents of the cell by a new value.
|
||||
|
||||
Class [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] is an effective descendant of [[ref:/libraries/base/reference/cell_chart|CELL]] , used for one-way linked structures. It introduces features <eiffel>right</eiffel>, a reference to another cell to which the current <br/>
|
||||
cell will be linked. Two-way linked structures use [[ref:/libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] , an heir of [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] which to the above features adds <eiffel>left</eiffel>, a reference to the preceding cell in the structure.
|
||||
Class [[ref:libraries/base/reference/linkable_chart|LINKABLE]] is an effective descendant of [[ref:libraries/base/reference/cell_chart|CELL]] , used for one-way linked structures. It introduces features <eiffel>right</eiffel>, a reference to another cell to which the current <br/>
|
||||
cell will be linked. Two-way linked structures use [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] , an heir of [[ref:libraries/base/reference/linkable_chart|LINKABLE]] which to the above features adds <eiffel>left</eiffel>, a reference to the preceding cell in the structure.
|
||||
|
||||
{{caution|Do not confuse the <eiffel>item</eiffel> feature of [[ref:/libraries/base/reference/cell_chart|CELL]] and its descendants, such as [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , with the <eiffel>item</eiffel> feature of the classes describing linear structures, such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . For a linked list, <eiffel>item</eiffel> returns the item at cursor position. }}
|
||||
{{caution|Do not confuse the <eiffel>item</eiffel> feature of [[ref:libraries/base/reference/cell_chart|CELL]] and its descendants, such as [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , with the <eiffel>item</eiffel> feature of the classes describing linear structures, such as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] . For a linked list, <eiffel>item</eiffel> returns the item at cursor position. }}
|
||||
|
||||
It may be implemented as
|
||||
<code>item: G is
|
||||
@@ -327,39 +327,39 @@ It may be implemented as
|
||||
Result := active.item
|
||||
end</code>
|
||||
|
||||
using the <eiffel>item</eiffel> feature of [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , applied to <eiffel>active</eiffel>.
|
||||
using the <eiffel>item</eiffel> feature of [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , applied to <eiffel>active</eiffel>.
|
||||
|
||||
==One-way and two-way linked chains==
|
||||
|
||||
If you look at the interfaces of one-way and two-way linked structures, you will notice that they are almost identical. This is because it is possible to implement features such as <eiffel>back</eiffel> for one-way structures such as described by [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:/libraries/base/reference/linked_circular_chart|LINKED_CIRCULAR]] . A simple implementation of <eiffel>back</eiffel> stores away a reference to the current active item, executes <eiffel>start</eiffel>, and then performs <eiffel>forth</eiffel> until the item to the right of the cursor position is the previous <eiffel>active</eiffel>. <br/>
|
||||
If you look at the interfaces of one-way and two-way linked structures, you will notice that they are almost identical. This is because it is possible to implement features such as <eiffel>back</eiffel> for one-way structures such as described by [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:libraries/base/reference/linked_circular_chart|LINKED_CIRCULAR]] . A simple implementation of <eiffel>back</eiffel> stores away a reference to the current active item, executes <eiffel>start</eiffel>, and then performs <eiffel>forth</eiffel> until the item to the right of the cursor position is the previous <eiffel>active</eiffel>. <br/>
|
||||
Although correct, such an implementation is of course rather inefficient since it requires a traversal of the list. In terms of algorithmic complexity, it is in O (<eiffel>count</eiffel>), meaning that its execution time is on the average proportional to the number of items in the structure. In contrast, <eiffel>forth</eiffel> is O (1), that is to say, takes an execution time bounded by a constant.
|
||||
|
||||
{{caution|As a consequence, you should not use one-way linked structures if you need to execute more than occasional <eiffel>back</eiffel> operations (and other operations requiring access to previous items, such as <eiffel>remove_left</eiffel>). }}
|
||||
|
||||
Two-way linked structures, such as those described by [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] , treat the two directions symmetrically, so that <eiffel>back</eiffel> will be just as efficient as <eiffel>forth</eiffel>. Hence the following important advice: If you need to traverse a linked structure both ways, not just left to right, use the <eiffel>TWO_WAY_</eiffel> classes, not the <eiffel>LINKED_</eiffel> versions. The <eiffel>TWO_WAY_</eiffel> structures will take up more space, since they use [[ref:/libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] rather than [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] cells, but for most applications this space penalty is justified by the considerable gains in time that will result if right-to-left operations are frequently needed.
|
||||
Two-way linked structures, such as those described by [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] , treat the two directions symmetrically, so that <eiffel>back</eiffel> will be just as efficient as <eiffel>forth</eiffel>. Hence the following important advice: If you need to traverse a linked structure both ways, not just left to right, use the <eiffel>TWO_WAY_</eiffel> classes, not the <eiffel>LINKED_</eiffel> versions. The <eiffel>TWO_WAY_</eiffel> structures will take up more space, since they use [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] rather than [[ref:libraries/base/reference/linkable_chart|LINKABLE]] cells, but for most applications this space penalty is justified by the considerable gains in time that will result if right-to-left operations are frequently needed.
|
||||
|
||||
==Arrayed chains==
|
||||
|
||||
Arrayed structures as described by [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] and [[ref:/libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] use arrays for their implementations. A list or circular chain of <eiffel>count</eiffel> items may be stored in positions 1 to <eiffel>count</eiffel> of an array of <eiffel>capacity</eiffel> items, where <eiffel>capacity</eiffel> >= <eiffel>count</eiffel>. <br/>
|
||||
An instance of [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] , as the name suggests, has a fixed number of items. In particular:
|
||||
* Query extendible has value false for [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] : you may replace existing items, but not add any, even at the end. A [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] is created with a certain number of items and retains that number.
|
||||
* As a result, [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] joins the deferred feature count of [[ref:/libraries/base/reference/list_chart|LIST]] with the feature count of ARRAY, which satisfies the property <eiffel>count</eiffel> = <eiffel>capacity</eiffel>.
|
||||
Arrayed structures as described by [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] and [[ref:libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] use arrays for their implementations. A list or circular chain of <eiffel>count</eiffel> items may be stored in positions 1 to <eiffel>count</eiffel> of an array of <eiffel>capacity</eiffel> items, where <eiffel>capacity</eiffel> >= <eiffel>count</eiffel>. <br/>
|
||||
An instance of [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] , as the name suggests, has a fixed number of items. In particular:
|
||||
* Query extendible has value false for [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] : you may replace existing items, but not add any, even at the end. A [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] is created with a certain number of items and retains that number.
|
||||
* As a result, [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] joins the deferred feature count of [[ref:libraries/base/reference/list_chart|LIST]] with the feature count of ARRAY, which satisfies the property <eiffel>count</eiffel> = <eiffel>capacity</eiffel>.
|
||||
* Query <eiffel>prunable </eiffel>has value false too: it is not possible to remove an item from a fixed list.
|
||||
|
||||
In contrast, [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] has almost the same interface as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . In particular, it is possible to add items at the end using procedure <eiffel>extend</eiffel>; if the call causes the list to grow beyond the current array's capacity, it will trigger a resizing. This is achieved by using the procedure <eiffel>force</eiffel> of class ARRAY to implement <eiffel>extend</eiffel>. [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] even has the insertion procedures (<eiffel>put_front</eiffel>, <eiffel>put_left</eiffel>, <eiffel>put_right</eiffel>) and removal procedures (<eiffel>prune</eiffel>, <eiffel>remove</eiffel>, <eiffel>remove_left</eiffel>, <eiffel>remove_right</eiffel>) that apply to arbitrary positions and appear in the linked implementations. These procedures, however, are rather inefficient, since they usually require moving a whole set of array items, an O (count) operation. (Procedure <eiffel>extend</eiffel> does not suffer from this problem, since it is easy to add an item to the end of an array, especially if there is still room so that no resizing is necessary.)
|
||||
In contrast, [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] has almost the same interface as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] . In particular, it is possible to add items at the end using procedure <eiffel>extend</eiffel>; if the call causes the list to grow beyond the current array's capacity, it will trigger a resizing. This is achieved by using the procedure <eiffel>force</eiffel> of class ARRAY to implement <eiffel>extend</eiffel>. [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] even has the insertion procedures (<eiffel>put_front</eiffel>, <eiffel>put_left</eiffel>, <eiffel>put_right</eiffel>) and removal procedures (<eiffel>prune</eiffel>, <eiffel>remove</eiffel>, <eiffel>remove_left</eiffel>, <eiffel>remove_right</eiffel>) that apply to arbitrary positions and appear in the linked implementations. These procedures, however, are rather inefficient, since they usually require moving a whole set of array items, an O (count) operation. (Procedure <eiffel>extend</eiffel> does not suffer from this problem, since it is easy to add an item to the end of an array, especially if there is still room so that no resizing is necessary.)
|
||||
|
||||
{{caution|The situation of these features in [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] is similar to the situation of <eiffel>back</eiffel> in classes describing one-way linked structures: it is convenient to include them because they may be needed once in a while and an implementation exists; but using them more than occasionally may result in serious inefficiencies. If you do need to perform arbitrary insertions and removal, use linked structures, not arrayed ones. }}
|
||||
{{caution|The situation of these features in [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] is similar to the situation of <eiffel>back</eiffel> in classes describing one-way linked structures: it is convenient to include them because they may be needed once in a while and an implementation exists; but using them more than occasionally may result in serious inefficiencies. If you do need to perform arbitrary insertions and removal, use linked structures, not arrayed ones. }}
|
||||
|
||||
Arrayed structures, however, use up less space than linked representations. So they are appropriate for chains on which, except possibly for insertions at the end, few insertion and removal operations or none at all are expected after creation. [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] offers few advantages over [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] . [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] may be useful, however, for cases in which the fixed number of items is part of the specification, and any attempt to add more items must be treated as an error. For circular chains only one variant is available, [[ref:/libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] , although writing a <eiffel>FIXED_</eiffel> version would be a simple exercise.
|
||||
Arrayed structures, however, use up less space than linked representations. So they are appropriate for chains on which, except possibly for insertions at the end, few insertion and removal operations or none at all are expected after creation. [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] offers few advantages over [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] . [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] may be useful, however, for cases in which the fixed number of items is part of the specification, and any attempt to add more items must be treated as an error. For circular chains only one variant is available, [[ref:libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] , although writing a <eiffel>FIXED_</eiffel> version would be a simple exercise.
|
||||
|
||||
==Multi-arrayed lists==
|
||||
|
||||
For lists one more variant is available, combining some of the advantages of arrayed and linked implementations: [[ref:/libraries/base/reference/multi_array_list_chart|MULTI_ARRAY_LIST]] . With this implementation a list is <br/>
|
||||
For lists one more variant is available, combining some of the advantages of arrayed and linked implementations: [[ref:libraries/base/reference/multi_array_list_chart|MULTI_ARRAY_LIST]] . With this implementation a list is <br/>
|
||||
divided into a number of blocks. Each block is an array, but the successive arrays are linked.
|
||||
|
||||
=Sorted Linear Structures=
|
||||
|
||||
The class [[ref:/libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , an heir of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , is declared as
|
||||
The class [[ref:libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , an heir of [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , is declared as
|
||||
<code>deferred class
|
||||
COMPARABLE_STRUCT [G -> COMPARABLE]
|
||||
inherit
|
||||
@@ -372,13 +372,13 @@ As indicated by the constrained generic parameter it describes bilinear structur
|
||||
{{caution|The class name COMPARABLE_STRUCT, chosen for brevity's sake, is slightly misleading: it is not the structures that are comparable but their items. }}
|
||||
|
||||
COMPARABLE_STRUCT introduces the features <eiffel>min</eiffel> and <eiffel>max</eiffel>, giving access to the minimum and maximum elements of a structure; these are always present for a finite <br/>
|
||||
structure with a total order relation. [[ref:/libraries/base/reference/sorted_struct_chart|SORTED_STRUCT]] , an heir of [[ref:/libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , describes structures that can be sorted; it introduces the query sorted and the command sort. <br/>
|
||||
The deferred class [[ref:/libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] describes lists whose items are kept ordered in a way that is compatible with a partial order relation defined on them. The class is declared as
|
||||
structure with a total order relation. [[ref:libraries/base/reference/sorted_struct_chart|SORTED_STRUCT]] , an heir of [[ref:libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , describes structures that can be sorted; it introduces the query sorted and the command sort. <br/>
|
||||
The deferred class [[ref:libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] describes lists whose items are kept ordered in a way that is compatible with a partial order relation defined on them. The class is declared as
|
||||
<code>deferred class
|
||||
PART_SORTED_LIST [G -> COMPARABLE]...</code>
|
||||
|
||||
An implementation based on two-way linked lists is available through the effective heir [[ref:/libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] . <br/>
|
||||
The deferred class [[ref:/libraries/base/reference/sorted_list_chart|SORTED_LIST]] , which inherits from [[ref:/libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] , assumes that the order relation on G is a total order. As a result, the class is able to introduce features <eiffel>min</eiffel>, <eiffel>max</eiffel> and <eiffel>median</eiffel>. Here too a two-way linked list implementation is available, through the effective class [[ref:/libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] .
|
||||
An implementation based on two-way linked lists is available through the effective heir [[ref:libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] . <br/>
|
||||
The deferred class [[ref:libraries/base/reference/sorted_list_chart|SORTED_LIST]] , which inherits from [[ref:libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] , assumes that the order relation on G is a total order. As a result, the class is able to introduce features <eiffel>min</eiffel>, <eiffel>max</eiffel> and <eiffel>median</eiffel>. Here too a two-way linked list implementation is available, through the effective class [[ref:libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[[Property:uuid|4f65d62b-940b-c3c2-557e-d709a2a1bcaf]]
|
||||
A dispenser is called that way because of the image of a vending machine (a dispenser) of a rather primitive nature, in which there is only one button. If you press the button and the dispenser is not empty, you get one of its items in the exit tray at the bottom, but you do not choose that item: the machine does. There is also an input slot at the top, into which you may deposit new items; but you have no control over the order in which successive button press operations will retrieve these items.
|
||||
|
||||
The deferred class [[ref:/libraries/base/reference/dispenser_chart|DISPENSER]] provides the facilities which will be shared by all specialized classes. In fact, the interface of all dispenser classes is nearly identical, with the exception of a few extra possibilities offered by priority queues. Many kinds of dispenser are possible, each defined by the relation that the machine defines between the order in which items are inserted and the order in which they arereturned. The Base libraries support three important categories - stacks, queues, and priority queues:
|
||||
The deferred class [[ref:libraries/base/reference/dispenser_chart|DISPENSER]] provides the facilities which will be shared by all specialized classes. In fact, the interface of all dispenser classes is nearly identical, with the exception of a few extra possibilities offered by priority queues. Many kinds of dispenser are possible, each defined by the relation that the machine defines between the order in which items are inserted and the order in which they arereturned. The Base libraries support three important categories - stacks, queues, and priority queues:
|
||||
* A stack is a dispenser with a last-in, first-out (LIFO) internal policy: items come out in the reverse order of their insertion. Each button press returns the last deposited item.
|
||||
* A queue is a dispenser with a first-in, first-out (FIFO) internal policy: items come out in the order of their insertion. Each button press returns the oldest item deposited and not yet removed.
|
||||
* In a priority queue, items have an associated notion of order; the element that comes out at any given time is the largest of those which are in the dispenser.
|
||||
@@ -12,24 +12,24 @@ The deferred class [[ref:/libraries/base/reference/dispenser_chart|DISPENSER]]
|
||||
|
||||
Stacks - dispensers with a LIFO retrieval policy - are a ubiquitous structure in software development. Their most famous application is to parsing (syntactic analysis), but many other types of systems use one or more stacks. Class STACK describes general stacks, without commitment to a representation. This is a deferred class which may not be directly instantiated. The fundamental operations are put (add an element at end of queue), item (retrieve the oldest element, non-destructively), remove (remove the oldest element), is_empty (test for empty queue). <br/>
|
||||
Three effective heirs are provided:
|
||||
* [[ref:/libraries/base/reference/linked_stack_chart|LINKED_STACK]] : stacks implemented as linked lists, with no limit on the number of items (<eiffel>count</eiffel>).
|
||||
* [[ref:/libraries/base/reference/bounded_stack_chart|BOUNDED_STACK]] : stacks implemented as arrays. For such stacks, the maximum number of items (<eiffel>capacity</eiffel>) is set at creation time.
|
||||
* [[ref:/libraries/base/reference/arrayed_stack_chart|ARRAYED_STACK]] : also implemented as arrays, but in this case there is no limit on the number of items; the interface is the same as [[ref:/libraries/base/reference/linked_stack_chart|LINKED_STACK]] except for the creation procedure. If the number of elements exceeds the initially allocated capacity, the array will simply be resized.
|
||||
* [[ref:libraries/base/reference/linked_stack_chart|LINKED_STACK]] : stacks implemented as linked lists, with no limit on the number of items (<eiffel>count</eiffel>).
|
||||
* [[ref:libraries/base/reference/bounded_stack_chart|BOUNDED_STACK]] : stacks implemented as arrays. For such stacks, the maximum number of items (<eiffel>capacity</eiffel>) is set at creation time.
|
||||
* [[ref:libraries/base/reference/arrayed_stack_chart|ARRAYED_STACK]] : also implemented as arrays, but in this case there is no limit on the number of items; the interface is the same as [[ref:libraries/base/reference/linked_stack_chart|LINKED_STACK]] except for the creation procedure. If the number of elements exceeds the initially allocated capacity, the array will simply be resized.
|
||||
|
||||
==Queues==
|
||||
|
||||
Class [[ref:/libraries/base/reference/queue_chart|QUEUE]] describes general queues, without commitment to a representation. This is a deferred class which may not be directly instantiated. Three non-deferred heirs are also provided, distinguished by the same properties as their stack counterparts:
|
||||
* [[ref:/libraries/base/reference/linked_queue_chart|LINKED_QUEUE]]
|
||||
* [[ref:/libraries/base/reference/bounded_queue_chart|BOUNDED_QUEUE]]
|
||||
* [[ref:/libraries/base/reference/arrayed_queue_chart|ARRAYED_QUEUE]]
|
||||
Class [[ref:libraries/base/reference/queue_chart|QUEUE]] describes general queues, without commitment to a representation. This is a deferred class which may not be directly instantiated. Three non-deferred heirs are also provided, distinguished by the same properties as their stack counterparts:
|
||||
* [[ref:libraries/base/reference/linked_queue_chart|LINKED_QUEUE]]
|
||||
* [[ref:libraries/base/reference/bounded_queue_chart|BOUNDED_QUEUE]]
|
||||
* [[ref:libraries/base/reference/arrayed_queue_chart|ARRAYED_QUEUE]]
|
||||
|
||||
==Priority Queues==
|
||||
|
||||
In a priority queue, each item has an associated priority value, and there is an order relation on these values. The item returned by item or removed by remove is the element with the highest priority.The most general class is [[ref:/libraries/base/reference/priority_queue_chart|PRIORITY_QUEUE]] , which is deferred. Two effective variants are provided:
|
||||
* [[ref:/libraries/base/reference/linked_priority_queue_chart|LINKED_PRIORITY_QUEUE]] , a linked list implementation.
|
||||
* [[ref:/libraries/base/reference/heap_priority_queue_chart|HEAP_PRIORITY_QUEUE]] which is more efficient and is to be preferred in most cases. A heap is organized like a binary tree, although physically stored in an array; elements with a high priority percolate towards the root.
|
||||
In a priority queue, each item has an associated priority value, and there is an order relation on these values. The item returned by item or removed by remove is the element with the highest priority.The most general class is [[ref:libraries/base/reference/priority_queue_chart|PRIORITY_QUEUE]] , which is deferred. Two effective variants are provided:
|
||||
* [[ref:libraries/base/reference/linked_priority_queue_chart|LINKED_PRIORITY_QUEUE]] , a linked list implementation.
|
||||
* [[ref:libraries/base/reference/heap_priority_queue_chart|HEAP_PRIORITY_QUEUE]] which is more efficient and is to be preferred in most cases. A heap is organized like a binary tree, although physically stored in an array; elements with a high priority percolate towards the root.
|
||||
|
||||
Because it must be possible to compare priorities, the type of the items must conform to [[ref:/libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] . Constrained genericity ensures this; all the priority queue classes have a formal generic parameter constrained by [[ref:/libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] .
|
||||
Because it must be possible to compare priorities, the type of the items must conform to [[ref:libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] . Constrained genericity ensures this; all the priority queue classes have a formal generic parameter constrained by [[ref:libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ Here, given with its full implementation, is a typical Iteration library routine
|
||||
The precise form of the procedure in the class relies on a call to another procedure, until_continue, and on inherited assertions. Here everything has been unfolded for illustration purposes. <br/>
|
||||
This procedure will traverse the linear structure identified by target and apply the procedure calledaction on every item up to but excluding the first one satisfying test. <br/>
|
||||
The class similarly offers <eiffel>do_all</eiffel>, <eiffel>do_while</eiffel>, <eiffel>do_for</eiffel>, <eiffel>do_if</eiffel> and other procedures representing the common control structures. It also includes functions such as <eiffel>exists</eiffel> and <eiffel>forall</eiffel>, corresponding to the usual quantifiers. <br/>
|
||||
These iteration schemes depend on the procedure <eiffel>action</eiffel>, defining the action to be applied to successive elements, and on the function <eiffel>test</eiffel>, defining the boolean query to be applied to these elements. These features are declared in class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] (the highest-level deferred class of the Iteration library); here is <eiffel>test</eiffel>:
|
||||
These iteration schemes depend on the procedure <eiffel>action</eiffel>, defining the action to be applied to successive elements, and on the function <eiffel>test</eiffel>, defining the boolean query to be applied to these elements. These features are declared in class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] (the highest-level deferred class of the Iteration library); here is <eiffel>test</eiffel>:
|
||||
<code>
|
||||
test: BOOLEAN
|
||||
-- Test to be applied to item at current position in
|
||||
@@ -96,12 +96,12 @@ These iteration schemes depend on the procedure <eiffel>action</eiffel>, definin
|
||||
not_off: not target.off
|
||||
end</code>
|
||||
|
||||
This indicates that the value of the boolean function <eiffel>test</eiffel> will be obtained by applying <eiffel>item_test</eiffel> to the item at the current position in the target structure. In [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , function <eiffel>item_test</eiffel> always return ; descendant classes will redefine it so as to describe the desired test. Similarly, <eiffel>action</eiffel> is declared in class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] as a call to <eiffel>item_action</eiffel>. Descendants will redefine <eiffel>item_action</eiffel>, which as initially declared in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] is a procedure with a null body. <br/>
|
||||
This indicates that the value of the boolean function <eiffel>test</eiffel> will be obtained by applying <eiffel>item_test</eiffel> to the item at the current position in the target structure. In [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , function <eiffel>item_test</eiffel> always return ; descendant classes will redefine it so as to describe the desired test. Similarly, <eiffel>action</eiffel> is declared in class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] as a call to <eiffel>item_action</eiffel>. Descendants will redefine <eiffel>item_action</eiffel>, which as initially declared in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] is a procedure with a null body. <br/>
|
||||
Going through <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel> provides an extra degree of flexibility. Normally the action and test performed at each step apply to <eiffel>target</eiffel> <code> . </code><eiffel>item></eiffel>, so that it suffices to redefine the <eiffel>item_features</eiffel>. This is the case with all examples studied in this chapter. In a more general setting, however, you might need to redefine <eiffel>action</eiffel> and <eiffel>test</eiffel> themselves.
|
||||
|
||||
==An example use of iteration==
|
||||
|
||||
Here now is an example illustrating the use of these mechanisms. The result will enable us to resize all the paragraphs of a text up to the first one that has been modified - as we might need to do, in a text processing system, to process an interactive user request. Assume a class <eiffel>TEXT</eiffel> that describes lists of paragraphs with certain additional features. The example will also assume a class <eiffel>PARAGRAPH</eiffel> with a procedure <eiffel>resize</eiffel>, and a boolean-valued attribute <eiffel>modified</eiffel> which indicates whether a paragraph has been modified. Class <eiffel>TEXT</eiffel> inherits from [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and so is a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] :
|
||||
Here now is an example illustrating the use of these mechanisms. The result will enable us to resize all the paragraphs of a text up to the first one that has been modified - as we might need to do, in a text processing system, to process an interactive user request. Assume a class <eiffel>TEXT</eiffel> that describes lists of paragraphs with certain additional features. The example will also assume a class <eiffel>PARAGRAPH</eiffel> with a procedure <eiffel>resize</eiffel>, and a boolean-valued attribute <eiffel>modified</eiffel> which indicates whether a paragraph has been modified. Class <eiffel>TEXT</eiffel> inherits from [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] and so is a descendant of [[ref:libraries/base/reference/linear_chart|LINEAR]] :
|
||||
<code>
|
||||
class
|
||||
TEXT
|
||||
@@ -151,7 +151,7 @@ feature {NONE}
|
||||
end</code>
|
||||
|
||||
Thanks to the iteration mechanism, the procedure <eiffel>resize_paragraphs</eiffel> simply needs two procedure calls:
|
||||
* To set its argument <code>t</code> as the iteration target, it uses procedure <eiffel>set</eiffel>. (This procedure is from class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] which passes it on to all iterator classes.)
|
||||
* To set its argument <code>t</code> as the iteration target, it uses procedure <eiffel>set</eiffel>. (This procedure is from class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] which passes it on to all iterator classes.)
|
||||
* Then it simply calls <eiffel>until_do</eiffel> as defined above.
|
||||
|
||||
Procedure <eiffel>item_action</eiffel> is redefined to describe the operation to be performed on each successive element. Function <eiffel>item_test</eiffel> is redefined to describe the exit test. <br/>
|
||||
@@ -165,43 +165,43 @@ Let us now explore the classes of the Iteration library and the different ways o
|
||||
==Overview of the classes==
|
||||
|
||||
There are only four Iteration classes, whose simple inheritance structure appeared at the beginning of this chapter.
|
||||
* [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , a deferred class which describes the most general notion.
|
||||
* [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating over linear structures and chains.
|
||||
* [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] , a repeated heir of [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating in either direction over a bilinear structure.
|
||||
* [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , for iterating over trees.
|
||||
* [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , a deferred class which describes the most general notion.
|
||||
* [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating over linear structures and chains.
|
||||
* [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] , a repeated heir of [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating in either direction over a bilinear structure.
|
||||
* [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , for iterating over trees.
|
||||
|
||||
As you will remember from the [[EiffelBase, Abstract Container Structures: The Taxonomy|presentation]] of the abstract overall taxonomy, the traversal hierarchy describes how data structures can be traversed; its most general class is [[ref:/libraries/base/reference/two_way_list_chart|TRAVERSABLE]] . <br/>
|
||||
As you will remember from the [[EiffelBase, Abstract Container Structures: The Taxonomy|presentation]] of the abstract overall taxonomy, the traversal hierarchy describes how data structures can be traversed; its most general class is [[ref:libraries/base/reference/two_way_list_chart|TRAVERSABLE]] . <br/>
|
||||
Each one of the iterator classes is paired with a traversal class (or two in one case):
|
||||
|
||||
|
||||
{| border="1"
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/iterator_chart|ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/two_way_list_chart|TRAVERSABLE]]
|
||||
| [[ref:libraries/base/reference/iterator_chart|ITERATOR]]
|
||||
| [[ref:libraries/base/reference/two_way_list_chart|TRAVERSABLE]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/linear_chart|LINEAR]]
|
||||
| [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/linear_chart|LINEAR]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]]
|
||||
| [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] , [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]]
|
||||
| [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] , [[ref:libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE]]
|
||||
| [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/cursor_tree_chart|CURSOR_TREE]]
|
||||
|}
|
||||
|
||||
|
||||
Each iterator class relies on the corresponding traversal class to provide the features for traversing the corresponding data structures, such as <eiffel>start</eiffel>, <eiffel>forth</eiffel>, and <eiffel>exhausted</eiffel> for linear structures. <br/>
|
||||
Of course the data structure class used in connection with a given iterator class does not need to be the iterator's exact correspondent as given by the above table; it may be any one of its descendants. For example you may use [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] to iterate over data structures described not just by [[ref:/libraries/base/reference/linear_chart|LINEAR]] but also by such descendants as [[ref:/libraries/base/reference/list_chart|LIST]] , [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , or even [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] if you do not need the backward iteration features (for which you will have to use [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ).
|
||||
Of course the data structure class used in connection with a given iterator class does not need to be the iterator's exact correspondent as given by the above table; it may be any one of its descendants. For example you may use [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] to iterate over data structures described not just by [[ref:libraries/base/reference/linear_chart|LINEAR]] but also by such descendants as [[ref:libraries/base/reference/list_chart|LIST]] , [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , or even [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] if you do not need the backward iteration features (for which you will have to use [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ).
|
||||
|
||||
==General iteration facilities==
|
||||
|
||||
Class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] defines the features that apply to all forms of iterator. <br/>
|
||||
An iterator will always apply to a certain target structure. The target is introduced in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] by the feature target: [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] [G] <br/>
|
||||
Both the iterator classes and the traversal classes are generic, with a formal generic parameter G. The actual generic parameters will be matched through the choice of iteration target: for a generic derivation of the form <eiffel>SOME_ITERATOR</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] the target can only be of type <eiffel>SOME_TRAVERSABLE</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] for the same <eiffel>ACTUAL_TYPE</eiffel>, where <eiffel>SOME_TRAVERSABLE</eiffel> is the traversal class matching <eiffel>SOME_ITERATOR</eiffel> according to the preceding table ([[ref:/libraries/base/reference/linear_chart|LINEAR]] for [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] and so on), or one of its proper descendants. <br/>
|
||||
Each of the proper descendants of [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] redefines the type of target to the matching proper descendant of [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] , to cover more specific variants of the iteration target, For example in [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] the feature is redefined to be of type [[ref:/libraries/base/reference/linear_chart|LINEAR]] . [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] also introduces the procedure for selecting a target:
|
||||
Class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] defines the features that apply to all forms of iterator. <br/>
|
||||
An iterator will always apply to a certain target structure. The target is introduced in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] by the feature target: [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] [G] <br/>
|
||||
Both the iterator classes and the traversal classes are generic, with a formal generic parameter G. The actual generic parameters will be matched through the choice of iteration target: for a generic derivation of the form <eiffel>SOME_ITERATOR</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] the target can only be of type <eiffel>SOME_TRAVERSABLE</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] for the same <eiffel>ACTUAL_TYPE</eiffel>, where <eiffel>SOME_TRAVERSABLE</eiffel> is the traversal class matching <eiffel>SOME_ITERATOR</eiffel> according to the preceding table ([[ref:libraries/base/reference/linear_chart|LINEAR]] for [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] and so on), or one of its proper descendants. <br/>
|
||||
Each of the proper descendants of [[ref:libraries/base/reference/iterator_chart|ITERATOR]] redefines the type of target to the matching proper descendant of [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] , to cover more specific variants of the iteration target, For example in [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] the feature is redefined to be of type [[ref:libraries/base/reference/linear_chart|LINEAR]] . [[ref:libraries/base/reference/iterator_chart|ITERATOR]] also introduces the procedure for selecting a target:
|
||||
<code>
|
||||
set (s: like target)
|
||||
-- Make s the new target of iterations.
|
||||
@@ -214,7 +214,7 @@ Each of the proper descendants of [[ref:/libraries/base/reference/iterator_chart
|
||||
target /= Void
|
||||
end</code>
|
||||
|
||||
Next [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces the routines describing the elementary action and test that will be applied to items of the iteration targets:
|
||||
Next [[ref:libraries/base/reference/iterator_chart|ITERATOR]] introduces the routines describing the elementary action and test that will be applied to items of the iteration targets:
|
||||
<code>
|
||||
action
|
||||
-- Action to be applied to item at current position in
|
||||
@@ -248,8 +248,8 @@ Next [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces the r
|
||||
|
||||
These routines rely on two others, <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>, which both take an argument of type G, the formal generic parameter. The reason, already noted above, is that in a vast majority of cases the iterated action and test solely depend, at each step of the traversal, on the item (of type G) at the current position. To define an iteration process, then, it suffices to redefine<eiffel> item_action</eiffel> and <eiffel>item_test</eiffel> in a descendant of the appropriate iteration class. Only in complex cases will it be necessary to redefine <eiffel>action</eiffel> and <eiffel>test</eiffel> themselves. <br/>
|
||||
If you encounter such a case, note the caveat about action changing the target's structure. Understandably enough, an iterator that attempts to change the data structure while traversing it may engage in strange behavior. No such risk exists if you only redefine <eiffel>item_action</eiffel>, which may change the contents of items but not the structure itself. <br/>
|
||||
Another feature introduced in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] is the query <eiffel>invariant_value</eiffel>, describing invariant properties that must be ensured at the beginning of any iteration and preserved by every iteration step. As declared in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] this query always returns true, but proper descendants can redefine it to describe more interesting invariant properties. <br/>
|
||||
Finally, [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces in deferred form the general iteration routines applicable to all iteration variants. They include two queries corresponding to the quantifiers of first-order predicate calculus:
|
||||
Another feature introduced in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] is the query <eiffel>invariant_value</eiffel>, describing invariant properties that must be ensured at the beginning of any iteration and preserved by every iteration step. As declared in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] this query always returns true, but proper descendants can redefine it to describe more interesting invariant properties. <br/>
|
||||
Finally, [[ref:libraries/base/reference/iterator_chart|ITERATOR]] introduces in deferred form the general iteration routines applicable to all iteration variants. They include two queries corresponding to the quantifiers of first-order predicate calculus:
|
||||
* <eiffel>for_all</eiffel> will return true if all items of the target structure satisfy test.
|
||||
* <eiffel>exists</eiffel> will return true if at least one item satisfies test.
|
||||
|
||||
@@ -260,12 +260,12 @@ The other routines are commands which will traverse the target structure and app
|
||||
* <eiffel>do_until</eiffel>, to all items up to and including the first one that satisfies test.
|
||||
* <eiffel>while_do</eiffel> and <eiffel>do_while</eiffel>, to all items up to the first one that does not satisfy test. (This can also be achieved with <eiffel>until_do</eiffel> or <eiffel>do_until </eiffel> by choosing the opposite test.)
|
||||
|
||||
All these features, and most of the other iteration features introduced in proper descendants of [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] and described next, have no argument. Information about the target of iteration comes from feature <eiffel>target</eiffel>, set by procedure <eiffel>set</eiffel>; information about what needs to be done for each item of the target structure comes from <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>.
|
||||
All these features, and most of the other iteration features introduced in proper descendants of [[ref:libraries/base/reference/iterator_chart|ITERATOR]] and described next, have no argument. Information about the target of iteration comes from feature <eiffel>target</eiffel>, set by procedure <eiffel>set</eiffel>; information about what needs to be done for each item of the target structure comes from <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>.
|
||||
|
||||
==Linear and chain iteration==
|
||||
|
||||
[[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , an effective class, refines the iteration mechanisms for cases in which the target is a linear structure, such as a list in any implementation or a circular chain. <br/>
|
||||
The class effects all the deferred features inherited from [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , taking advantage of the linear traversal mechanisms present in the corresponding traversal class, [[ref:/libraries/base/reference/linear_chart|LINEAR]] . Here for example is the effecting of <eiffel>do_if</eiffel>:
|
||||
[[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , an effective class, refines the iteration mechanisms for cases in which the target is a linear structure, such as a list in any implementation or a circular chain. <br/>
|
||||
The class effects all the deferred features inherited from [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , taking advantage of the linear traversal mechanisms present in the corresponding traversal class, [[ref:libraries/base/reference/linear_chart|LINEAR]] . Here for example is the effecting of <eiffel>do_if</eiffel>:
|
||||
<code>
|
||||
do_if
|
||||
-- Apply action to every item of target satisfying
|
||||
@@ -285,7 +285,7 @@ The class effects all the deferred features inherited from [[ref:/libraries/base
|
||||
end
|
||||
end</code>
|
||||
|
||||
This routine text relies on features <eiffel>start</eiffel>, <eiffel>forth</eiffel> and <eiffel>exhausted</eiffel> which, together with <eiffel>off</eiffel>, have for convenience been carried over to [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] from their counterparts in [[ref:/libraries/base/reference/linear_chart|LINEAR]] , with feature declarations such as
|
||||
This routine text relies on features <eiffel>start</eiffel>, <eiffel>forth</eiffel> and <eiffel>exhausted</eiffel> which, together with <eiffel>off</eiffel>, have for convenience been carried over to [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] from their counterparts in [[ref:libraries/base/reference/linear_chart|LINEAR]] , with feature declarations such as
|
||||
<code>
|
||||
off: BOOLEAN
|
||||
-- Is position of target off?
|
||||
@@ -296,18 +296,18 @@ This routine text relies on features <eiffel>start</eiffel>, <eiffel>forth</eiff
|
||||
end</code>
|
||||
|
||||
and similarly for the others. <br/>
|
||||
In addition to effecting the general iteration features from [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , class [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] introduces iteration features that apply to the specific case of linear structures:
|
||||
In addition to effecting the general iteration features from [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , class [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] introduces iteration features that apply to the specific case of linear structures:
|
||||
* <eiffel>search (b :BOOLEAN)</eiffel> moves the iteration to the first position satisfying test if <code>b</code> is true, or not satisfying test if <code>b</code> is false. This use of a boolean argument to switch between two opposite semantics is not part of the recommended style, and you will find few if any other examples in the Base libraries. Here, however, it was deemed preferable to the alternative, which would have involved four separate procedures (if together with <eiffel>search</eiffel> we consider <eiffel>continue_search</eiffel> discussed next).
|
||||
* With a linear structure we can implement an iteration corresponding to the 'for' loop of traditional programming languages, defined by three integers: the starting position, the number of items to be traversed, and the step between consecutive items. This is provided by procedure <eiffel>do_for</eiffel> <code> ( starting , number , step :INTEGER). </code>
|
||||
* Since with a linear target the iterator can advance the cursor step by step, the basic iteration operations are complemented by variants which pick up from the position reached by the last call: <eiffel>continue_until</eiffel>, <eiffel>until_continue</eiffel>, <eiffel>continue_while</eiffel>, <eiffel>while_continue</eiffel>, <eiffel>continue_search</eiffel>, <eiffel>continue_for</eiffel>.
|
||||
|
||||
==Two-way iteration==
|
||||
|
||||
Class [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] has all the features of [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , to which it adds features for iterating backward as well as forward. <br/>
|
||||
Class [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] has all the features of [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , to which it adds features for iterating backward as well as forward. <br/>
|
||||
The class introduces commands <eiffel>finish</eiffel> and <eiffel>back</eiffel>, applying the corresponding operations to the two-way target. It also has a backward variant for every iteration feature. The name of each such variant is the name of the forward feature followed by ''_back'': <eiffel>do_all_back</eiffel>, <eiffel>until_do_back</eiffel> and so on. <br/>
|
||||
An alternative design would have kept just one set of features and added two features: a command reverse to reverse the direction of future iteration operations, and a query backward to find out the direction currently in force. <br/>
|
||||
Contrary to what one might at first imagine, class [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] is extremely short and simple; its <code> Feature </code> clause only contains the declarations of two features, <eiffel>finish</eiffel> and <eiffel>back</eiffel>. <br/>
|
||||
The trick is to use repeated inheritance. [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] inherits twice from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] ; the first inheritance branch yields the forward iteration features, the second yields those for backward iteration. There is no need for any explicit declaration or redeclaration of iteration features. Here is the entire class text that yields this result:
|
||||
Contrary to what one might at first imagine, class [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] is extremely short and simple; its <code> Feature </code> clause only contains the declarations of two features, <eiffel>finish</eiffel> and <eiffel>back</eiffel>. <br/>
|
||||
The trick is to use repeated inheritance. [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] inherits twice from [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] ; the first inheritance branch yields the forward iteration features, the second yields those for backward iteration. There is no need for any explicit declaration or redeclaration of iteration features. Here is the entire class text that yields this result:
|
||||
<code>
|
||||
class
|
||||
TWO_WAY_CHAIN_ITERATOR [G]
|
||||
@@ -379,13 +379,13 @@ This class provides a good example of the economy of expression that the full in
|
||||
|
||||
==Tree iteration==
|
||||
|
||||
Tree iterations, provided by class [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , work on trees of the cursor tree form; only with this form of tree are traversal operations possible. Three forms of iteration are provided: preorder, postorder and breadth-first. They correspond to the three traversal policies described in the discussion of trees. Here too it would seem that a rather lengthy class is needed, but repeated inheritance works wonders. <br/>
|
||||
[[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] simply inherits three times from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , renaming the features appropriately in each case:
|
||||
Tree iterations, provided by class [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , work on trees of the cursor tree form; only with this form of tree are traversal operations possible. Three forms of iteration are provided: preorder, postorder and breadth-first. They correspond to the three traversal policies described in the discussion of trees. Here too it would seem that a rather lengthy class is needed, but repeated inheritance works wonders. <br/>
|
||||
[[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] simply inherits three times from [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , renaming the features appropriately in each case:
|
||||
* <eiffel>pre_do_all</eiffel>, <eiffel>pre_until</eiffel>, and so on.
|
||||
* <eiffel>post_do_all</eiffel>, <eiffel>post_until</eiffel>, and so on.
|
||||
* <eiffel>breadth_do_all</eiffel>, <eiffel>breadth_until</eiffel>, and so on.
|
||||
|
||||
All it needs to do then is to redefine the type of target to be [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE [G]]] , and to redefine six features: the three renamed start (<eiffel>pre_start</eiffel>, etc.) and the three forth ( <eiffel>pre_ forth</eiffel>, and so on). These seven redefinitions give us a full-fledged battery of tree iteration mechanisms.
|
||||
All it needs to do then is to redefine the type of target to be [[ref:libraries/base/reference/cursor_tree_chart|CURSOR_TREE [G]]] , and to redefine six features: the three renamed start (<eiffel>pre_start</eiffel>, etc.) and the three forth ( <eiffel>pre_ forth</eiffel>, and so on). These seven redefinitions give us a full-fledged battery of tree iteration mechanisms.
|
||||
|
||||
=Building and Using Iterators=
|
||||
|
||||
@@ -394,14 +394,14 @@ An application class may use one of the iteration classes in either of two ways:
|
||||
|
||||
==The single descendant technique==
|
||||
|
||||
Assume an application class <eiffel>PROCESSOR</eiffel> that is a proper descendant of one of the effective iteration classes studied in this chapter. Then a routine of <eiffel>PROCESSOR</eiffel>, say <eiffel>iterate</eiffel>, may iterate a certain action over a data structure, subject to a certain test. First, class <eiffel>PROCESSOR</eiffel> must specify the action by redefining item_action and item_test (or, in the most general case, action and test). Then routine iterate must specify the target data structure through a call of the form <code>set (t)</code> where t represents the selected target data structure. The type of t must correspond to the iteration class selected as ancestor of <eiffel>PROCESSOR</eiffel>: for [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] (such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , LINKED_CIRCULAR or any other list or circular chain classes); for [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/linear_chart|BILINEAR]] such as [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] or [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] ; for [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE]] . In all cases the actual generic parameters of the iterator class and ofthe data structure class must be compatible. Then the iteration proper is obtained simply by calling the appropriate procedure, without any qualification or arguments, for example: do_ if <br/>
|
||||
Assume an application class <eiffel>PROCESSOR</eiffel> that is a proper descendant of one of the effective iteration classes studied in this chapter. Then a routine of <eiffel>PROCESSOR</eiffel>, say <eiffel>iterate</eiffel>, may iterate a certain action over a data structure, subject to a certain test. First, class <eiffel>PROCESSOR</eiffel> must specify the action by redefining item_action and item_test (or, in the most general case, action and test). Then routine iterate must specify the target data structure through a call of the form <code>set (t)</code> where t represents the selected target data structure. The type of t must correspond to the iteration class selected as ancestor of <eiffel>PROCESSOR</eiffel>: for [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] it must be a descendant of [[ref:libraries/base/reference/linear_chart|LINEAR]] (such as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , LINKED_CIRCULAR or any other list or circular chain classes); for [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] it must be a descendant of [[ref:libraries/base/reference/linear_chart|BILINEAR]] such as [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] or [[ref:libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] ; for [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] it must be a descendant of [[ref:libraries/base/reference/cursor_tree_chart|CURSOR_TREE]] . In all cases the actual generic parameters of the iterator class and ofthe data structure class must be compatible. Then the iteration proper is obtained simply by calling the appropriate procedure, without any qualification or arguments, for example: do_ if <br/>
|
||||
It is hard to imagine a simpler scheme: no loops, no initialization, no arguments. Feature item_action may need to rely on some variable values. Because it does not take any argument, such values will have to be treated as attributes, with the corresponding <eiffel>set_...</eiffel> procedures to set and change their values. This also applies to the two schemes set next. <br/>
|
||||
The single descendant technique has one drawback: it provides the iterating class, <eiffel>PROCESSOR</eiffel>, with only one set of iteration particulars. This limitation does not affect the number of targets: you may use as many targets as you wish, as long as they are of compatible types, by calling a routine such as iterate several times, or calling several such routines, each call being preceded by a call to set to define a new target. The limitation also does not affect the iterating scheme: one iteration could use do_if, the next do_all and so on. But it does require the action and test to be the same in all cases. <br/>
|
||||
The next two techniques will remove this limitation.
|
||||
|
||||
==Using repeated inheritance==
|
||||
|
||||
One way to obtain several iteration schemes is a simple extension to the single descendant technique. You can use repeated inheritance to provide two or more variants. We have in fact already encountered the technique when studying how to derive [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] and [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] . The general pattern, applied here to just two iteration schemes but easily generalized to more, is straightforward:
|
||||
One way to obtain several iteration schemes is a simple extension to the single descendant technique. You can use repeated inheritance to provide two or more variants. We have in fact already encountered the technique when studying how to derive [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] and [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] from [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] . The general pattern, applied here to just two iteration schemes but easily generalized to more, is straightforward:
|
||||
<code>
|
||||
class
|
||||
DUAL_PROCESSOR
|
||||
|
||||
@@ -27,16 +27,16 @@ With good implementations, however, it is possible to use hash tables with a per
|
||||
x := h.item (k)</code>
|
||||
|
||||
where <eiffel>h</eiffel> is a hash-table and <eiffel>k</eiffel> is a key (for example a string) as conceptually equivalent to the array operations mentioned above. <br/>
|
||||
The quality of a hashed implementation will depend both on the data structure that will store the objects, and on the choice of hashing function. Class [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] attempts to address the first concern; for the second, client developers will be responsible for choosing the proper hashing function, although Base provides a few predefined functions, in particular for class [[ref:/libraries/base/reference/string_8_chart|STRING]] .
|
||||
The quality of a hashed implementation will depend both on the data structure that will store the objects, and on the choice of hashing function. Class [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] attempts to address the first concern; for the second, client developers will be responsible for choosing the proper hashing function, although Base provides a few predefined functions, in particular for class [[ref:libraries/base/reference/string_8_chart|STRING]] .
|
||||
|
||||
==When hash tables are appropriate==
|
||||
|
||||
You may keep objects in a hash table if for each one of these objects you can find a key that uniquely identifies it. The objects and their keys may be of many possible kinds:
|
||||
* '''H1'''. In a simple example, the objects are integers; each integer serves as its own key. (More precisely we will use its absolute value, since it is convenient to have non-negative keys only.) This case is of more than theoretical interest, since it makes hash tables appropriate for storing a set of integers with widely scattered values, for which simple array storage would be a waste of space (see requirement '''A3''' above).
|
||||
* '''H2'''. Frequently, the objects will be composite, that is to say, instances of a developer-defined class, and one of the attributes of that class, of type [[ref:/libraries/base/reference/string_8_chart|STRING]] , can serve as the key. For example if you were writing an Eiffel compiler you would probably need to keep a data structure that includes information about classes of the system. Each class is represented by an object with several fields describing the properties of the class; one of these fields, the class name, corresponding to an attribute of type [[ref:/libraries/base/reference/string_8_chart|STRING]] , will serve as key.
|
||||
* '''H2'''. Frequently, the objects will be composite, that is to say, instances of a developer-defined class, and one of the attributes of that class, of type [[ref:libraries/base/reference/string_8_chart|STRING]] , can serve as the key. For example if you were writing an Eiffel compiler you would probably need to keep a data structure that includes information about classes of the system. Each class is represented by an object with several fields describing the properties of the class; one of these fields, the class name, corresponding to an attribute of type [[ref:libraries/base/reference/string_8_chart|STRING]] , will serve as key.
|
||||
* '''H3'''. Instead of being the full object (as in case '''H1''') or one of the object's fields (as in case '''H2'''), the key may have to be computed through a function of the generating class, which will take into account several attributes of the class (that is to say, for each object, several fields).
|
||||
|
||||
What this practically means is that in all cases you will need, in the generating class of the objects to be stored, a query (attribute or function) that gives the key. The type of the key is highly variable but must in all cases be a descendant of [[ref:/libraries/base/reference/hashable_chart|HASHABLE]] . This is true of both [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] (case '''H1''') and [[ref:/libraries/base/reference/string_8_chart|STRING]] (case '''H2'''). The requirements for being a [[ref:/libraries/base/reference/hashable_chart|HASHABLE]] are not harsh: all you need is a function hash_code that returns a non-negative integer.>
|
||||
What this practically means is that in all cases you will need, in the generating class of the objects to be stored, a query (attribute or function) that gives the key. The type of the key is highly variable but must in all cases be a descendant of [[ref:libraries/base/reference/hashable_chart|HASHABLE]] . This is true of both [[ref:libraries/base/reference/integer_32_chart|INTEGER]] (case '''H1''') and [[ref:libraries/base/reference/string_8_chart|STRING]] (case '''H2'''). The requirements for being a [[ref:libraries/base/reference/hashable_chart|HASHABLE]] are not harsh: all you need is a function hash_code that returns a non-negative integer.>
|
||||
|
||||
==Using hash tables==
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ This yields a simple definition of trees by multiple inheritance from [[ref:libr
|
||||
|
||||
===Dynamic recursive trees===
|
||||
|
||||
An example of dynamic tree structure is provided by class [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] , an heir of both [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] . There is also [[ref:libraries/base/reference/linked_tree_chart|LINKED_TREE]] , which inherits from [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , but [[ref:libraries/base/reference/two_way_tree_chart|TWO_WA Y_TREE]] is generally preferable since children of a node often needs to be traversed both ways; the notion of order is usually less significant here than for lists. Such a form of definition is a particularly effective way of conveying the profoundly recursive nature of trees. The corresponding classes are useful in many different areas such as graphics, text processing and compilation. To create a one-way or two-way linked tree, use
|
||||
An example of dynamic tree structure is provided by class [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] , an heir of both [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] . There is also [[ref:libraries/base/reference/linked_tree_chart|LINKED_TREE]] , which inherits from [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , but [[ref:libraries/base/reference/two_way_tree_chart|TWO_WA Y_TREE]] is generally preferable since children of a node often needs to be traversed both ways; the notion of order is usually less significant here than for lists. Such a form of definition is a particularly effective way of conveying the profoundly recursive nature of trees. The corresponding classes are useful in many different areas such as graphics, text processing and compilation. To create a one-way or two-way linked tree, use
|
||||
<code>create my_tree.make (root_value)</code>
|
||||
|
||||
This will attach my_tree to a new one-node tree, with root_value at the root node. Here my_tree must be declared of type [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] [MY_TYPE] for some type MY_TYPE, and root_value must be of type MY_TYPE. <br/>
|
||||
@@ -100,7 +100,7 @@ Various procedures are available to move the cursor in all directions:
|
||||
* [[ref:libraries/base/reference/cursor_tree_chart|forth]] and [[ref:libraries/base/reference/cursor_tree_chart|back]] move the cursor forward and backward between siblings and can cause the cursor to end up [[ref:libraries/base/reference/cursor_tree_chart|after]] or [[ref:libraries/base/reference/cursor_tree_chart|before]] .
|
||||
* [[ref:libraries/base/reference/cursor_tree_chart|up]] moves the cursor up one level. The call may be made even when the cursor is [[ref:libraries/base/reference/cursor_tree_chart|after]] or [[ref:libraries/base/reference/cursor_tree_chart|before]] . If the cursor is on the root of the tree or below in an empty tree, the cursor ends up [[ref:libraries/base/reference/cursor_tree_chart|above]] .
|
||||
|
||||
You can move the cursor in any one direction ( [[ref:libraries/base/reference/cursor_tree_chart|up]] , [[ref:libraries/base/reference/cursor_tree_chart|down]] , [[ref:libraries/base/reference/cursor_tree_chart|forth]] , [[ref:libraries/base/reference/cursor_tree_chart|back]] ), repeatedly, until it is [[ref:libraries/base/reference/cursor_tree_chart|off]] ( [[ref:libraries/base/reference/cursor_tree_chart|above]] , [[ref:libraries/base/reference/cursor_tree_chart|below,]] [[ref:libraries/base/reference/cursor_tree_chart|after]] , [[ref:libraries/base/reference/cursor_tree_chart|before]] respectively), but once it is [[ref:libraries/base/reference/cursor_tree_chart|off]] , further movement in the same direction is prohibited. For example the precondition of [[ref:/libraries/base/reference/cursor_tree_chart|put_left]] requires [[ref:libraries/base/reference/cursor_tree_chart|before]] to be false, and the precondition of [[ref:/libraries/base/reference/cursor_tree_chart|put_right]] requires [[ref:libraries/base/reference/cursor_tree_chart|after]] to be false. <br/>
|
||||
You can move the cursor in any one direction ( [[ref:libraries/base/reference/cursor_tree_chart|up]] , [[ref:libraries/base/reference/cursor_tree_chart|down]] , [[ref:libraries/base/reference/cursor_tree_chart|forth]] , [[ref:libraries/base/reference/cursor_tree_chart|back]] ), repeatedly, until it is [[ref:libraries/base/reference/cursor_tree_chart|off]] ( [[ref:libraries/base/reference/cursor_tree_chart|above]] , [[ref:libraries/base/reference/cursor_tree_chart|below,]] [[ref:libraries/base/reference/cursor_tree_chart|after]] , [[ref:libraries/base/reference/cursor_tree_chart|before]] respectively), but once it is [[ref:libraries/base/reference/cursor_tree_chart|off]] , further movement in the same direction is prohibited. For example the precondition of [[ref:libraries/base/reference/cursor_tree_chart|put_left]] requires [[ref:libraries/base/reference/cursor_tree_chart|before]] to be false, and the precondition of [[ref:libraries/base/reference/cursor_tree_chart|put_right]] requires [[ref:libraries/base/reference/cursor_tree_chart|after]] to be false. <br/>
|
||||
It is possible to move down from an [[ref:libraries/base/reference/cursor_tree_chart|above]] position; in an empty tree this brings the cursor [[ref:libraries/base/reference/cursor_tree_chart|below]] . Similarly, it is possible to move up from [[ref:libraries/base/reference/cursor_tree_chart|below]] , left from [[ref:libraries/base/reference/cursor_tree_chart|after]] , right from [[ref:libraries/base/reference/cursor_tree_chart|before]] . <br/>
|
||||
The sentinel element above the tree's root is considered to be the root of a forest containing just one tree. This view justifies the convention for the result of arity when the cursor is above: 0 if the tree [[ref:libraries/base/reference/cursor_tree_chart|is_empty]] , 1 if it has a root (viewed as the child of the fictitious sentinel element).
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@ The support cluster offers some commonly needed functionality that do not belong
|
||||
|
||||
==Conversions, mathematical properties and ASCII characters==
|
||||
|
||||
A few utility classes complement the [[EiffelBase, The Kernel|kernel]] facilities. [[ref:/libraries/base/reference/primes_chart|PRIMES]] , [[ref:/libraries/base/reference/random_chart|RANDOM]] and [[ref:/libraries/base/reference/fibonacci_chart|FIBONACCI]] are part of the data structure taxonomy; the others are meant to be used as ancestors by classes needing their features.
|
||||
A few utility classes complement the [[EiffelBase, The Kernel|kernel]] facilities. [[ref:libraries/base/reference/primes_chart|PRIMES]] , [[ref:libraries/base/reference/random_chart|RANDOM]] and [[ref:libraries/base/reference/fibonacci_chart|FIBONACCI]] are part of the data structure taxonomy; the others are meant to be used as ancestors by classes needing their features.
|
||||
|
||||
Two classes provide basic mathematical functions such as logarithms and trigonometric functions: [[ref:/libraries/base/reference/single_math_chart|SINGLE_MATH]] for single precision and [[ref:/libraries/base/reference/double_math_chart|DOUBLE_MATH]] for the double-precision variants. [[ref:/libraries/base/reference/math_const_chart|MATH_CONST]] contains mathematical constants: <code> p </code>, the square root of two, Euler's constant <code> e </code>.
|
||||
Two classes provide basic mathematical functions such as logarithms and trigonometric functions: [[ref:libraries/base/reference/single_math_chart|SINGLE_MATH]] for single precision and [[ref:libraries/base/reference/double_math_chart|DOUBLE_MATH]] for the double-precision variants. [[ref:libraries/base/reference/math_const_chart|MATH_CONST]] contains mathematical constants: <code> p </code>, the square root of two, Euler's constant <code> e </code>.
|
||||
|
||||
[[ref:/libraries/base/reference/primes_chart|PRIMES]] , [[ref:/libraries/base/reference/random_chart|RANDOM]] and [[ref:/libraries/base/reference/fibonacci_chart|FIBONACCI]] are data structure classes - heirs of [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] . In all of these classes function i_th takes an integer argument <code> i </code> and will return the i-th element of the sequence under consideration - prime numbers, pseudo-random numbers or Fibonacci numbers. These sequences are active structures, on which forth will advance the current position and item will return the value at the current position. A few other features are specific to each case: for example [[ref:/libraries/base/reference/random_flatshort|higher_prime]] will yield the smallest prime greater than or equal to a certain value, and [[ref:/libraries/base/reference/random_flatshort|set_seed]] will define the seed to be used for starting the pseudo-random sequence.
|
||||
[[ref:libraries/base/reference/primes_chart|PRIMES]] , [[ref:libraries/base/reference/random_chart|RANDOM]] and [[ref:libraries/base/reference/fibonacci_chart|FIBONACCI]] are data structure classes - heirs of [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] . In all of these classes function i_th takes an integer argument <code> i </code> and will return the i-th element of the sequence under consideration - prime numbers, pseudo-random numbers or Fibonacci numbers. These sequences are active structures, on which forth will advance the current position and item will return the value at the current position. A few other features are specific to each case: for example [[ref:libraries/base/reference/random_flatshort|higher_prime]] will yield the smallest prime greater than or equal to a certain value, and [[ref:libraries/base/reference/random_flatshort|set_seed]] will define the seed to be used for starting the pseudo-random sequence.
|
||||
|
||||
==Internal object structures==
|
||||
|
||||
Class [[ref:/libraries/base/reference/internal_chart|INTERNAL]] provides low-level access to internal object structures. It, too, is meant to be used as ancestor by classes needing its features. <br/>
|
||||
Class [[ref:libraries/base/reference/internal_chart|INTERNAL]] provides low-level access to internal object structures. It, too, is meant to be used as ancestor by classes needing its features. <br/>
|
||||
Here are some of the most useful calls and what they yield, <eiffel>obj</eiffel> being an entity attached to an object <eiffel>O</eiffel> and <eiffel>i</eiffel> an integer:
|
||||
* <eiffel>class_name (obj)</eiffel> : the name of the generator class for O.
|
||||
* <eiffel>dynamic_type (obj) </eiffel> : the integer code for the type of <eiffel>O</eiffel>, where each type in a system is identified by a unique code.
|
||||
@@ -24,7 +24,7 @@ Here are some of the most useful calls and what they yield, <eiffel>obj</eiffel>
|
||||
* <eiffel>yy_field (i, obj) </eiffel> where <eiffel>yy</eiffel> is boolean, character, integer, real or double: the value of the i-th field of <eiffel>O</eiffel>, if of the corresponding type; each declared of the appropriate type in the class.
|
||||
* <eiffel>is_special (obj) </eiffel> : a boolean query which indicates whether <eiffel>O</eiffel> is a special object (the sequence of values representing the elements of an array or the characters of a string).
|
||||
|
||||
{{warning|Only very special cases justify the use of the class [[ref:/libraries/base/reference/internal_chart|INTERNAL]]. Unless you are writing the lowest level of an interface between an Eiffel application and external tools (such as a database management system), and this requires passing to those tools information about the internals of Eiffel objects, you almost certainly should not use [[ref:/libraries/base/reference/internal_chart|INTERNAL]] . }}
|
||||
{{warning|Only very special cases justify the use of the class [[ref:libraries/base/reference/internal_chart|INTERNAL]]. Unless you are writing the lowest level of an interface between an Eiffel application and external tools (such as a database management system), and this requires passing to those tools information about the internals of Eiffel objects, you almost certainly should not use [[ref:libraries/base/reference/internal_chart|INTERNAL]] . }}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ You can then access or modify [[ref:libraries/store/reference/db_table_flatshort
|
||||
end
|
||||
</code>
|
||||
|
||||
{{note|to access attributes data with ''code'', you need to use the [[ref:/libraries/store/reference/db_table_description_flatshort|DB_TABLE_DESCRIPTION]] object associated to your [[ref:libraries/store/reference/db_table_flatshort|DB_TABLE]] object. }}
|
||||
{{note|to access attributes data with ''code'', you need to use the [[ref:libraries/store/reference/db_table_description_flatshort|DB_TABLE_DESCRIPTION]] object associated to your [[ref:libraries/store/reference/db_table_flatshort|DB_TABLE]] object. }}
|
||||
|
||||
===2.3. Getting objects metadata===
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
[[Property:weight|1]]
|
||||
[[Property:uuid|80cd0938-6837-3c17-8515-b4ac60a51d09]]
|
||||
Each interface class has an implementation counterpart that implements specific DBMS handling. The class prefix indicates clearly its layer, for instance:
|
||||
* [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] is the interface to perform a database selection query.
|
||||
* [[ref:/libraries/store/reference/database_selection_flatshort|DATABASE_SELECTION]] [ [[ref:/libraries/store/reference/database_flatshort|DATABASE]] ] is its implementation.
|
||||
* [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] is the interface to perform a database selection query.
|
||||
* [[ref:libraries/store/reference/database_selection_flatshort|DATABASE_SELECTION]] [ [[ref:libraries/store/reference/database_flatshort|DATABASE]] ] is its implementation.
|
||||
|
||||
The abstract [[ref:/libraries/store/reference/database_flatshort|DATABASE]] class represents a DBMS, i.e. it is the Eiffel-side database call interface. It is inherited for instance by the instantiable <eiffel>ORACLE</eiffel> and <eiffel>ODBC</eiffel> classes.
|
||||
The abstract [[ref:libraries/store/reference/database_flatshort|DATABASE]] class represents a DBMS, i.e. it is the Eiffel-side database call interface. It is inherited for instance by the instantiable <eiffel>ORACLE</eiffel> and <eiffel>ODBC</eiffel> classes.
|
||||
|
||||
EiffelStore enables to link common interface objects with database-specific implementation objects using a '''handle'''. This handle also enables to switch between different databases.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[[Property:title|Data Modification]]
|
||||
[[Property:weight|1]]
|
||||
[[Property:uuid|ef5568ff-dc7c-4c85-0174-335fdab1bd84]]
|
||||
Use the [[ref:/libraries/store/reference/db_change_flatshort|DB_CHANGE]] class to perform any operation on your database that does not require access to a result. You can for instance modify table row content, drop table rows, create and delete tables.
|
||||
Use the [[ref:libraries/store/reference/db_change_flatshort|DB_CHANGE]] class to perform any operation on your database that does not require access to a result. You can for instance modify table row content, drop table rows, create and delete tables.
|
||||
|
||||
{{note|Take a look at the [[Data Object Coupling|Data Storing]] capability if you want to '''insert''' table rows. }}
|
||||
|
||||
[[ref:/libraries/store/reference/db_change_flatshort|DB_CHANGE]] allows you to modify the database data using the SQL language:
|
||||
[[ref:libraries/store/reference/db_change_flatshort|DB_CHANGE]] allows you to modify the database data using the SQL language:
|
||||
* Prepare your SQL query and use modify:
|
||||
<code>
|
||||
modification: DB_CHANGE
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
[[Property:weight|4]]
|
||||
[[Property:uuid|c51311cd-8782-0bc3-3ef7-000ea6eee37c]]
|
||||
A smart way to work with relational databases is to have Eiffel objects directly mapping relational tables. Three EiffelStore classes enable this coupling:
|
||||
* [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] objects [[#describe|describe a relational table]] and allow Eiffel to create objects mapping database tables.
|
||||
* [[ref:/libraries/store/reference/db_store_flatshort|DB_STORE]] works directly with [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] objects to [[#insert|insert data into relational tables]] .
|
||||
* [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] can [[#map|map a database query result into Eiffel objects]] .
|
||||
* [[ref:libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] objects [[#describe|describe a relational table]] and allow Eiffel to create objects mapping database tables.
|
||||
* [[ref:libraries/store/reference/db_store_flatshort|DB_STORE]] works directly with [[ref:libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] objects to [[#insert|insert data into relational tables]] .
|
||||
* [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] can [[#map|map a database query result into Eiffel objects]] .
|
||||
|
||||
==Describing relational tables with DB_REPOSITORY==
|
||||
|
||||
A [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] object stores available information about a table. To access this information, you mainly have to give the table name and load the table description:
|
||||
A [[ref:libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] object stores available information about a table. To access this information, you mainly have to give the table name and load the table description:
|
||||
<code>
|
||||
repository: DB_REPOSITORY
|
||||
|
||||
@@ -25,8 +25,8 @@ A [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] obje
|
||||
{{tip|Loading a table description is often a costly operation: table has to be fetched among existing tables then every table column description must be loaded. Hence it is better to store and reuse a repository (maybe with a HASH_TABLE) once it has been loaded. }}
|
||||
|
||||
|
||||
Using the table information, [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] then helps generating Eiffel classes mapping relational tables:
|
||||
* You can directly use {[[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] }.generate_class. Generated class may look like:
|
||||
Using the table information, [[ref:libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] then helps generating Eiffel classes mapping relational tables:
|
||||
* You can directly use {[[ref:libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] }.generate_class. Generated class may look like:
|
||||
<code>
|
||||
class CONTACTS
|
||||
|
||||
@@ -50,10 +50,10 @@ feature -- Settings
|
||||
|
||||
==Inserting data in the database==
|
||||
|
||||
[[ref:/libraries/store/reference/db_store_flatshort|DB_STORE]] lets you easily insert rows into a table using:
|
||||
* the table description provided by [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] .
|
||||
[[ref:libraries/store/reference/db_store_flatshort|DB_STORE]] lets you easily insert rows into a table using:
|
||||
* the table description provided by [[ref:libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] .
|
||||
* a class mapping the relational table.
|
||||
This is straight-forward since you only have to give [[ref:/libraries/store/reference/db_store_flatshort|DB_STORE]] the object filled with the table values. Suppose you want to add a contact into your database:
|
||||
This is straight-forward since you only have to give [[ref:libraries/store/reference/db_store_flatshort|DB_STORE]] the object filled with the table values. Suppose you want to add a contact into your database:
|
||||
<code>
|
||||
storage: DB_STORE
|
||||
contacts_rep: DB_REPOSITORY
|
||||
@@ -70,7 +70,7 @@ This is straight-forward since you only have to give [[ref:/libraries/store/refe
|
||||
|
||||
==Accessing database content with Eiffel objects==
|
||||
|
||||
[[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] lets you map data retrieved from the database into Eiffel objects: Result column names must match object attributes names so you can use for instance classes created by [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] . Class <eiffel>DB_ACTION</eiffel> redefines ACTION and can be used to retrieve Eiffel objects directly into an ARRAYED_LIST:
|
||||
[[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] lets you map data retrieved from the database into Eiffel objects: Result column names must match object attributes names so you can use for instance classes created by [[ref:libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] . Class <eiffel>DB_ACTION</eiffel> redefines ACTION and can be used to retrieve Eiffel objects directly into an ARRAYED_LIST:
|
||||
<code>
|
||||
selection: DB_SELECTION
|
||||
list_filling: DB_ACTION [CONTACTS]
|
||||
@@ -89,7 +89,7 @@ This is straight-forward since you only have to give [[ref:/libraries/store/refe
|
||||
</code>
|
||||
|
||||
|
||||
{{note|You can see how actions are used in [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] . }}
|
||||
{{note|You can see how actions are used in [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] . }}
|
||||
<br/>
|
||||
|
||||
{{seealso|<br/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[Property:title|Database control]]
|
||||
[[Property:weight|7]]
|
||||
[[Property:uuid|432c6e51-36d5-b469-c924-eb821713256a]]
|
||||
Use the [[ref:/libraries/store/reference/db_control_flatshort|DB_CONTROL]] class to check or change database status and behavior. The main operations you are likely to use are:
|
||||
Use the [[ref:libraries/store/reference/db_control_flatshort|DB_CONTROL]] class to check or change database status and behavior. The main operations you are likely to use are:
|
||||
* Handling database errors.
|
||||
* Connecting to the database.
|
||||
* Committing changes in the database.
|
||||
@@ -10,7 +10,7 @@ Use the [[ref:/libraries/store/reference/db_control_flatshort|DB_CONTROL]] clas
|
||||
|
||||
Every EiffelStore interface class has an is_ok feature. This enables to check directly if the last database operation has been successful.
|
||||
|
||||
When an error is detected, you can use [[ref:/libraries/store/reference/db_control_flatshort|DB_CONTROL]] to obtain further information about the error:
|
||||
When an error is detected, you can use [[ref:libraries/store/reference/db_control_flatshort|DB_CONTROL]] to obtain further information about the error:
|
||||
* error_message provides a description of the error that occurred.
|
||||
* error_code returns a code corresponding to the error type. This code enables to handle specific errors within your code without parsing the error_message.
|
||||
* warning_message provides a warning message about the last transaction performed.
|
||||
@@ -19,7 +19,7 @@ Once you have handled your error, for instance by displaying the error_message o
|
||||
|
||||
==Managing database connection==
|
||||
|
||||
[[ref:/libraries/store/reference/db_control_flatshort|DB_CONTROL]] lets you connect, check your connection, and disconnect from the database.
|
||||
[[ref:libraries/store/reference/db_control_flatshort|DB_CONTROL]] lets you connect, check your connection, and disconnect from the database.
|
||||
|
||||
The following example sum up these capabilities:
|
||||
<code>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[[Property:title|Database Selection]]
|
||||
[[Property:weight|2]]
|
||||
[[Property:uuid|de759a74-b3e1-c937-e620-67526c116925]]
|
||||
Use the [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] class to select data from the database. Once you have selected the data, you can [[Selection Access|access]] it with convenience using adaptative EiffelStore structures.
|
||||
Use the [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] class to select data from the database. Once you have selected the data, you can [[Selection Access|access]] it with convenience using adaptative EiffelStore structures.
|
||||
|
||||
{{note|Take a look at the [[Data Object Coupling|Database/Eiffel objects Coupling]] if you need information about your database structure. }}
|
||||
|
||||
[[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] enables your application to get database content using SQL 'select' queries:
|
||||
[[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] enables your application to get database content using SQL 'select' queries:
|
||||
* You can carry out 'select' queries in an intuitive way using directly the SQL language:
|
||||
<code>
|
||||
selection: DB_SELECTION
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[[Property:uuid|37222a07-a8f8-e57d-45f0-3b28cd66d660]]
|
||||
If you have to execute database queries which only differ in the expression values, you can create a template query and then bind variables into this template for each execution.
|
||||
|
||||
This mechanism can be applied for requests with a result ([[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] ) or without ([[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] ). Hence both classes inherits from STRING_HDL that actually handle variable binding.
|
||||
This mechanism can be applied for requests with a result ([[ref:libraries/store/reference/db_selection_chart|DB_SELECTION]] ) or without ([[ref:libraries/store/reference/db_change_chart|DB_CHANGE]] ). Hence both classes inherits from STRING_HDL that actually handle variable binding.
|
||||
|
||||
To use variable binding:
|
||||
* [[#create|Create]] a template query.
|
||||
@@ -24,7 +24,7 @@ Variables syntax is simple: the ':' special character followed by the variable n
|
||||
selection.set_query ("Select * from CONTACTS where Firstname = ':" + Bind_var + "'")
|
||||
</code>
|
||||
|
||||
{{note|The code example shows how to bind variables to a [[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] object but the mechanism is exactly the same for [[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] objects. }}
|
||||
{{note|The code example shows how to bind variables to a [[ref:libraries/store/reference/db_selection_chart|DB_SELECTION]] object but the mechanism is exactly the same for [[ref:libraries/store/reference/db_change_chart|DB_CHANGE]] objects. }}
|
||||
|
||||
==Binding variables to a query==
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ To use DB_RESULT, process in 2 steps:
|
||||
|
||||
==Retrieving DB_RESULT objects==
|
||||
|
||||
[[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] class provides different ways to customize result loading:
|
||||
* You want to access an '''unique''' row: [[ref:/libraries/store/reference/db_result_flatshort|DB_RESULT]] object is accessible via cursor:
|
||||
[[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] class provides different ways to customize result loading:
|
||||
* You want to access an '''unique''' row: [[ref:libraries/store/reference/db_result_flatshort|DB_RESULT]] object is accessible via cursor:
|
||||
<code>
|
||||
selection: DB_SELECTION
|
||||
my_result: DB_RESULT
|
||||
@@ -27,7 +27,7 @@ To use DB_RESULT, process in 2 steps:
|
||||
end
|
||||
</code>
|
||||
|
||||
* You want to load a '''complete list''' of rows: [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] can store [[ref:/libraries/store/reference/db_result_flatshort|DB_RESULT]] objects in a list. To do this, you have mainly to provide a LIST object to DB_SELECTION with set_container:
|
||||
* You want to load a '''complete list''' of rows: [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] can store [[ref:libraries/store/reference/db_result_flatshort|DB_RESULT]] objects in a list. To do this, you have mainly to provide a LIST object to DB_SELECTION with set_container:
|
||||
<code>
|
||||
selection: DB_SELECTION
|
||||
container: ARRAYED_LIST [DB_RESULT]
|
||||
@@ -48,10 +48,10 @@ To use DB_RESULT, process in 2 steps:
|
||||
end
|
||||
</code>
|
||||
|
||||
{{tip|Provide [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] with the LIST structure convenient for what you need to do with the results. }}
|
||||
{{tip|Provide [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] with the LIST structure convenient for what you need to do with the results. }}
|
||||
|
||||
* You want to '''select part''' of the result set: you can set an action in [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] that will be executed each time a row is loaded. This action can for instance manipulate current row and define a stop condition.
|
||||
** You need to define a descendant of class ACTION and set it to [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] :
|
||||
* You want to '''select part''' of the result set: you can set an action in [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] that will be executed each time a row is loaded. This action can for instance manipulate current row and define a stop condition.
|
||||
** You need to define a descendant of class ACTION and set it to [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] :
|
||||
<code>
|
||||
class
|
||||
MY_ACTION
|
||||
@@ -75,7 +75,7 @@ inherit
|
||||
Result := i >= Max_result
|
||||
end
|
||||
</code>
|
||||
** Then set action to [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] :
|
||||
** Then set action to [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] :
|
||||
<code>
|
||||
selection: DB_SELECTION
|
||||
action: MY_ACTION
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
[[Property:uuid|9979af90-07c3-8b20-448e-04454a75c801]]
|
||||
When sending requests to the database, the request is first parsed then executed. Instead of parsing many times the same requests, i.e. with only changes in expression values, most of RDBMS enable to '''precompile''' requests. These requests can then be executed as routines and are identified by a name and a signature.
|
||||
|
||||
EiffelStore lets you use stored procedures with [[ref:/libraries/store/reference/db_proc_flatshort|DB_PROC]] class to:
|
||||
EiffelStore lets you use stored procedures with [[ref:libraries/store/reference/db_proc_flatshort|DB_PROC]] class to:
|
||||
* [[#execute|Execute]] a stored procedure.
|
||||
* [[#create|Create]] a stored procedure.
|
||||
|
||||
==Executing a stored procedure==
|
||||
|
||||
To execute a stored procedure:
|
||||
* Create a [[ref:/libraries/store/reference/db_proc_flatshort|DB_PROC]] object and load the stored procedure you want to use:
|
||||
* Create a [[ref:libraries/store/reference/db_proc_flatshort|DB_PROC]] object and load the stored procedure you want to use:
|
||||
<code>
|
||||
procedure: DB_PROC
|
||||
|
||||
@@ -23,9 +23,9 @@ To execute a stored procedure:
|
||||
end
|
||||
</code>
|
||||
|
||||
* Execute the procedure through a [[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] (if a result is expected) or a [[ref:/libraries/store/reference/db_change_chart|DB_CHANGE ]] object (otherwise).
|
||||
* Execute the procedure through a [[ref:libraries/store/reference/db_selection_chart|DB_SELECTION]] (if a result is expected) or a [[ref:libraries/store/reference/db_change_chart|DB_CHANGE ]] object (otherwise).
|
||||
|
||||
{{note|Requests with a result ([[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] ) or without ([[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] ) are both abstract '''expressions'''. DB_PROC executes an abstract expression using an object of [[ref:/libraries/store/reference/db_expression_chart|DB_EXPRESSION]] type, which corresponds to an abstract expression. [[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] and [[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] inherits from [[ref:/libraries/store/reference/db_expression_chart|DB_EXPRESSION]] . }}
|
||||
{{note|Requests with a result ([[ref:libraries/store/reference/db_selection_chart|DB_SELECTION]] ) or without ([[ref:libraries/store/reference/db_change_chart|DB_CHANGE]] ) are both abstract '''expressions'''. DB_PROC executes an abstract expression using an object of [[ref:libraries/store/reference/db_expression_chart|DB_EXPRESSION]] type, which corresponds to an abstract expression. [[ref:libraries/store/reference/db_selection_chart|DB_SELECTION]] and [[ref:libraries/store/reference/db_change_chart|DB_CHANGE]] inherits from [[ref:libraries/store/reference/db_expression_chart|DB_EXPRESSION]] . }}
|
||||
|
||||
You can execute your request mostly like a basic one:
|
||||
** Create your request.
|
||||
|
||||
@@ -23,8 +23,8 @@ This sample contains the following class:
|
||||
|
||||
|
||||
{{seealso|<br/>
|
||||
[[ref:/libraries/vision2/reference/ev_accelerator_chart|EV_ACCELERATOR]] <br/>
|
||||
[[ref:/libraries/vision2/reference/ev_key_chart|EV_KEY]] <br/>
|
||||
[[ref:libraries/vision2/reference/ev_accelerator_chart|EV_ACCELERATOR]] <br/>
|
||||
[[ref:libraries/vision2/reference/ev_key_chart|EV_KEY]] <br/>
|
||||
}}
|
||||
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ EiffelVision 2 ships with a number of samples provided to demonstrate different
|
||||
* [[Widgets Sample|Widgets]] sample. Demonstrates both the appearance and behavior of the available widgets.
|
||||
|
||||
Then explore other samples:
|
||||
* [[Accelerator Sample|Accelerator]] - Demonstrates the use of an [[ref:/libraries/vision2/reference/ev_accelerator_chart|EV_ACCELERATOR]] .
|
||||
* [[Cursor Sample|Cursor]] - Demonstrates how to modify the displayed [[ref:/libraries/vision2/reference/ev_cursor_chart|EV_CURSOR]] for an [[ref:/libraries/vision2/reference/ev_widget_chart|EV_WIDGET]] .
|
||||
* [[Gauges Sample|Gauges]] - Demonstrates different types of [[ref:/libraries/vision2/reference/ev_gauge_chart|EV_GAUGE]] .
|
||||
* [[Standard_dialogs Sample|Standard_dialogs]] - Demonstrates different types of [[ref:/libraries/vision2/reference/ev_standard_dialog_chart|EV_STANDARD_DIALOG]] .
|
||||
* [[Viewport Sample|Viewport]] - Demonstrates [[ref:/libraries/vision2/reference/ev_viewport_chart|EV_VIEWPORT]] .
|
||||
* [[Accelerator Sample|Accelerator]] - Demonstrates the use of an [[ref:libraries/vision2/reference/ev_accelerator_chart|EV_ACCELERATOR]] .
|
||||
* [[Cursor Sample|Cursor]] - Demonstrates how to modify the displayed [[ref:libraries/vision2/reference/ev_cursor_chart|EV_CURSOR]] for an [[ref:libraries/vision2/reference/ev_widget_chart|EV_WIDGET]] .
|
||||
* [[Gauges Sample|Gauges]] - Demonstrates different types of [[ref:libraries/vision2/reference/ev_gauge_chart|EV_GAUGE]] .
|
||||
* [[Standard_dialogs Sample|Standard_dialogs]] - Demonstrates different types of [[ref:libraries/vision2/reference/ev_standard_dialog_chart|EV_STANDARD_DIALOG]] .
|
||||
* [[Viewport Sample|Viewport]] - Demonstrates [[ref:libraries/vision2/reference/ev_viewport_chart|EV_VIEWPORT]] .
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ This sample contains the following class:
|
||||
{{seealso|<br/>
|
||||
EV_VIEWPORT <br/>
|
||||
EV_SPIN_BUTTON <br/>
|
||||
[[ref:/libraries/vision2/reference/ev_button_chart|EV_BUTTON]] <br/>
|
||||
[[ref:libraries/vision2/reference/ev_button_chart|EV_BUTTON]] <br/>
|
||||
}}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ The EiffelVision 2 library includes the following interface clusters:
|
||||
|
||||
* The [[Properties| properties]] cluster contains classes that allow for the customization of Vision 2 widgets and items. Classes such as [[ref:libraries/vision2/reference/ev_colorizable_chart|EV_COLORIZABLE]] and [[ref:libraries/vision2/reference/ev_fontable_chart|EV_FONTABLE]] contain routines that allow for (respectively) color and font to be altered for a widget.
|
||||
|
||||
* The [[Support| support]] cluster includes classes that provide more professional touches to an application, whether these are keyboard shortcuts ([[ref:libraries/vision2/reference/ev_accelerator_list_chart|EV_ACCELERATOR_LIST]]) or graphical output ([[ref:libraries/vision2/reference/ev_graphical_format_chart|EV_GRAPHICAL_FORMAT]]) for drawable widgets such as [[ref:/libraries/vision2/reference/ev_pixmap_chart|EV_PIXMAP]] .
|
||||
* The [[Support| support]] cluster includes classes that provide more professional touches to an application, whether these are keyboard shortcuts ([[ref:libraries/vision2/reference/ev_accelerator_list_chart|EV_ACCELERATOR_LIST]]) or graphical output ([[ref:libraries/vision2/reference/ev_graphical_format_chart|EV_GRAPHICAL_FORMAT]]) for drawable widgets such as [[ref:libraries/vision2/reference/ev_pixmap_chart|EV_PIXMAP]] .
|
||||
|
||||
* The [[Figures| figures]] cluster allows for the projection of two-dimensional shapes (figures) onto an [[ref:libraries/vision2/reference/ev_drawable_chart|EV_DRAWABLE]] or printer via the use of an [[ref:libraries/vision2/reference/ev_projector_chart|EV_PROJECTOR]] .
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ The kernel cluster contains classes that provide functionality common to most Wi
|
||||
|
||||
[[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] is the basis for every EiffelVision 2 application and is considered the most important class in the library. It is responsible for initializing the underlying toolkit that is driving the windowing system on the platform that you compile your system on. It is also where the main event loop that drives your application is executed.
|
||||
|
||||
{{note|It is an '''error''' to attempt to create any EiffelVision 2 components before the application object has been created (see the Flat Contracts view of [[ref:/libraries/vision2/reference/ev_environment_chart|EV_ENVIRONMENT]]). }}
|
||||
{{note|It is an '''error''' to attempt to create any EiffelVision 2 components before the application object has been created (see the Flat Contracts view of [[ref:libraries/vision2/reference/ev_environment_chart|EV_ENVIRONMENT]]). }}
|
||||
|
||||
You may inherit [[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] or use it as a client in order to create your EiffelVision 2 application. A simple method of using EV_APPLICATION is as follows:
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ A simple example of this is demonstrated here:
|
||||
button2.drop_actions.extend (agent print (?))
|
||||
</code>
|
||||
|
||||
Because <eiffel>print</eiffel> takes an argument of type [[ref:/libraries/base/reference/string_8_chart|STRING_8]], button2 becomes a valid drop-target for the pebble contained by button1. Right clicking the mouse pointer over the '''source''' will start the transport, and right clicking with the mouse pointer over a valid '''target''' will complete the transport. The transport can be canceled anytime with a simple left click, just as you would do in EiffelStudio.
|
||||
Because <eiffel>print</eiffel> takes an argument of type [[ref:libraries/base/reference/string_8_chart|STRING_8]], button2 becomes a valid drop-target for the pebble contained by button1. Right clicking the mouse pointer over the '''source''' will start the transport, and right clicking with the mouse pointer over a valid '''target''' will complete the transport. The transport can be canceled anytime with a simple left click, just as you would do in EiffelStudio.
|
||||
|
||||
{{note|Any type of object can be used as the '''pebble'''. When a transport completes, the '''pebble''' that was transported is passed as an argument to all agents in the '''target's''' <code>drop_actions</code> list to which the '''pebble''' [[uuid:b8c10baa-4f50-adfe-a6f8-9cb56a8f1917#Conformance|conforms]]. <br><br>}}
|
||||
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
[[Property:uuid|595bb73e-146a-ea19-221f-40f3415aad34]]
|
||||
==What Is a Widget?==
|
||||
|
||||
A Widget is the fundamental building block of your application's GUI. Components such as Windows, Buttons, Text fields, Check Boxes, List Boxes and layout Containers are examples of widgets. The widget set in EiffelVision 2 provides you with the flexibility to easily create powerful graphical applications. All widgets in EiffelVision 2 inherit from [[ref:/libraries/vision2/reference/ev_widget_chart| EV_WIDGET]], thus the features provided in <eiffel>EV_WIDGET</eiffel> may be called on any widget.
|
||||
A Widget is the fundamental building block of your application's GUI. Components such as Windows, Buttons, Text fields, Check Boxes, List Boxes and layout Containers are examples of widgets. The widget set in EiffelVision 2 provides you with the flexibility to easily create powerful graphical applications. All widgets in EiffelVision 2 inherit from [[ref:libraries/vision2/reference/ev_widget_chart| EV_WIDGET]], thus the features provided in <eiffel>EV_WIDGET</eiffel> may be called on any widget.
|
||||
|
||||
|
||||
==Variations of Widgets==
|
||||
Within EiffelVision 2, widgets have been classified into three different groups:
|
||||
|
||||
* [[Primitives|Primitives]] — These are elements of the user interface that are mainly responsible for interaction with the user, such as an [[ref:/libraries/vision2/reference/ev_button_chart|EV_BUTTON]].
|
||||
* [[Primitives|Primitives]] — These are elements of the user interface that are mainly responsible for interaction with the user, such as an [[ref:libraries/vision2/reference/ev_button_chart|EV_BUTTON]].
|
||||
|
||||
* [[Containers|Containers]] — These are used to contain other widgets and position them in a certain way, such as an [[ref:/libraries/vision2/reference/ev_vertical_box_chart| EV_VERTICAL_BOX ]] that stacks its child widgets one by one vertically.
|
||||
* [[Containers|Containers]] — These are used to contain other widgets and position them in a certain way, such as an [[ref:libraries/vision2/reference/ev_vertical_box_chart| EV_VERTICAL_BOX ]] that stacks its child widgets one by one vertically.
|
||||
|
||||
* [[EiffelVision Dialogs|Dialogs]] — These are pop up dialog boxes used for interacting with the user for tasks such as opening a file (EV_FILE_OPEN_DIALOG) or displaying a message (EV_MESSAGE_DIALOG). You may also construct your own dialog boxes by inheriting from EV_DIALOG.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ In the preceding examples each participant in a communication had to get ready t
|
||||
|
||||
The commands are objects, instances of a general-purpose class <code>COMMAND</code> or its proper descendants. Class <code>COMMAND</code> has, among its features, a procedure <eiffel>execute</eiffel> which executes the current command; some commands are undoable and have an <eiffel>undo</eiffel> procedure.
|
||||
|
||||
In EiffelNet the possible events associated with a socket will be of three kind: a read event; a write event; or a special event (out of bounds operation). The command classes will be descendants of [[ref:/libraries/net/reference/poll_command_chart|POLL_COMMAND]], an heir of <code>COMMAND</code>.
|
||||
In EiffelNet the possible events associated with a socket will be of three kind: a read event; a write event; or a special event (out of bounds operation). The command classes will be descendants of [[ref:libraries/net/reference/poll_command_chart|POLL_COMMAND]], an heir of <code>COMMAND</code>.
|
||||
|
||||
===9.2 Command classes===
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ A Special_C++_feature, if present, indicates one of the following, all illustrat
|
||||
* If the special feature's declaration simply starts with a C++ class name, followed by the associated file name, it indicates that the Eiffel feature will call a C++ member function (also known as a "method") from that class. The name of the member function is by default the same as the name of the Eiffel feature; as usual, you can specify a different name through the alias clause of the external declaration.
|
||||
* If the declaration starts with <code>static</code>, it indicates a call to a C++ static function.
|
||||
* If the declaration starts with <code>new</code>, it indicates a call to one of the constructors in the C++ class, which will create a new instance of that class and apply to it the corresponding constructor function.
|
||||
* If the declaration starts with <code>delete</code>, it indicates a call to a destructor from the C++ class. In this case the Eiffel class may inherit [[ref:/libraries/base/reference/memory_chart|MEMORY]] and redefine the dispose procedure to execute the destructor operations whenever the Eiffel objects are garbage-collected.
|
||||
* If the declaration starts with <code>delete</code>, it indicates a call to a destructor from the C++ class. In this case the Eiffel class may inherit [[ref:libraries/base/reference/memory_chart|MEMORY]] and redefine the dispose procedure to execute the destructor operations whenever the Eiffel objects are garbage-collected.
|
||||
* If the declaration starts with <code>data_member</code>, it indicates access to a data member (attribute in Eiffel terminology) from the C++ class.
|
||||
|
||||
The rest of the possible components are the same as in the C interface: Signature to specify types for arguments and results; possible Include file.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[Property:title|Redefining main_window]]
|
||||
[[Property:weight|1]]
|
||||
[[Property:uuid|f7bfd5d0-86ef-5387-ba79-5461a516bcf6]]
|
||||
When you inherit [[ref:/libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] , you will need to implement the deferred feature main_window as a once function. This will be the main window of your application, and can be any descendent of [[ref:libraries/wel/reference/wel_composite_window_chart|WEL_COMPOSITE_WINDOW]] .
|
||||
When you inherit [[ref:libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] , you will need to implement the deferred feature main_window as a once function. This will be the main window of your application, and can be any descendent of [[ref:libraries/wel/reference/wel_composite_window_chart|WEL_COMPOSITE_WINDOW]] .
|
||||
|
||||
{{note|. See [[Tutorial Step 2|step2]] in the [[WEL Tutorial|tutorial]] for a simple demonstration of how to do this. }}
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
[[Property:title|windows cluster]]
|
||||
[[Property:weight|-1]]
|
||||
[[Property:uuid|dc1af280-2e91-713c-751f-e88ce87197cf]]
|
||||
This cluster contains the different types of windows available to a [[ref:/libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] .
|
||||
This cluster contains the different types of windows available to a [[ref:libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] .
|
||||
|
||||
The following effective window types are available:
|
||||
* [[ref:/libraries/wel/reference/wel_popup_window_chart|WEL_POPUP_WINDOW]]
|
||||
* [[ref:/libraries/wel/reference/wel_modal_dialog_chart|WEL_MODAL_DIALOG]]
|
||||
* [[ref:/libraries/wel/reference/wel_modeless_dialog_chart|WEL_MODELESS_DIALOG]]
|
||||
* [[ref:/libraries/wel/reference/wel_mdi_frame_window_chart|WEL_MDI_FRAME_WINDOW]]
|
||||
* [[ref:/libraries/wel/reference/wel_mdi_client_window_chart|WEL_MDI_CLIENT_WINDOW]]
|
||||
* [[ref:/libraries/wel/reference/wel_mdi_child_window_chart|WEL_MDI_CHILD_WINDOW]]
|
||||
* [[ref:/libraries/wel/reference/wel_main_dialog_chart|WEL_MAIN_DIALOG]]
|
||||
* [[ref:/libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]]
|
||||
* [[ref:/libraries/wel/reference/wel_control_window_chart|WEL_CONTROL_WINDOW]]
|
||||
* [[ref:libraries/wel/reference/wel_popup_window_chart|WEL_POPUP_WINDOW]]
|
||||
* [[ref:libraries/wel/reference/wel_modal_dialog_chart|WEL_MODAL_DIALOG]]
|
||||
* [[ref:libraries/wel/reference/wel_modeless_dialog_chart|WEL_MODELESS_DIALOG]]
|
||||
* [[ref:libraries/wel/reference/wel_mdi_frame_window_chart|WEL_MDI_FRAME_WINDOW]]
|
||||
* [[ref:libraries/wel/reference/wel_mdi_client_window_chart|WEL_MDI_CLIENT_WINDOW]]
|
||||
* [[ref:libraries/wel/reference/wel_mdi_child_window_chart|WEL_MDI_CHILD_WINDOW]]
|
||||
* [[ref:libraries/wel/reference/wel_main_dialog_chart|WEL_MAIN_DIALOG]]
|
||||
* [[ref:libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]]
|
||||
* [[ref:libraries/wel/reference/wel_control_window_chart|WEL_CONTROL_WINDOW]]
|
||||
|
||||
{{note|A WEL application must contain at least one window. See the [[WEL Tutorial]] for details of how to set up your first window within a [[ref:/libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] . }}
|
||||
{{note|A WEL application must contain at least one window. See the [[WEL Tutorial]] for details of how to set up your first window within a [[ref:libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] . }}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ This sample contains the following classes:
|
||||
|
||||
{{seealso|<br/>
|
||||
[[WEL_LIST_VIEW|WEL_LIST_VIEW]] <br/>
|
||||
[[ref:/libraries/wel/reference/wel_combo_box_chart|WEL_COMBO_BOX]] <br/>
|
||||
[[ref:libraries/wel/reference/wel_combo_box_chart|WEL_COMBO_BOX]] <br/>
|
||||
[[WEL_PUSH_BUTTON|WEL_PUSH_BUTTON]] <br/>
|
||||
[[ref:/libraries/wel/reference/wel_edit_chart|WEL_EDIT]] <br/>
|
||||
[[ref:libraries/wel/reference/wel_edit_chart|WEL_EDIT]] <br/>
|
||||
[[WEL_RADIO_BUTTON|WEL_RADIO_BUTTON]] <br/>
|
||||
[[WEL_PUSH_BUTTON|WEL_CHECK_BUTTON]] <br/>
|
||||
[[WEL_MULTIPLE_LINE_EDIT|WEL_MULTIPLE_LINE_EDIT]] <br/>
|
||||
|
||||
@@ -24,7 +24,7 @@ This sample contains only one class:
|
||||
|
||||
{{seealso|<br/>
|
||||
[[Tutorial Step 1|tutorial step 1]] <br/>
|
||||
[[ref:/libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] }}
|
||||
[[ref:libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] }}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ This sample contains the following classes:
|
||||
* RICHEDIT_DEMO
|
||||
|
||||
{{seealso|<br/>
|
||||
[[ref:/libraries/wel/reference/wel_rich_edit_chart|WEL_RICH_EDIT]] <br/>
|
||||
[[ref:libraries/wel/reference/wel_rich_edit_chart|WEL_RICH_EDIT]] <br/>
|
||||
[[WEL_PRINT_DIALOG|WEL_PRINT_DIALOG]] <br/>
|
||||
[[WEL_SAVE_FILE_DIALOG|WEL_SAVE_FILE_DIALOG]] <br/>
|
||||
[[WEL_OPEN_FILE_DIALOG|WEL_OPEN_FILE_DIALOG]] <br/>
|
||||
|
||||
@@ -27,7 +27,7 @@ This sample contains the following classes:
|
||||
|
||||
|
||||
{{seealso|<br/>
|
||||
[[ref:/libraries/wel/reference/wel_rich_edit_chart|WEL_RICH_EDIT]] }}
|
||||
[[ref:libraries/wel/reference/wel_rich_edit_chart|WEL_RICH_EDIT]] }}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ This sample contains the following classes:
|
||||
* <code>APPLICATION_IDS</code>
|
||||
|
||||
{{seealso|<br/>
|
||||
[[ref:/libraries/wel/reference/wel_tree_view_chart|WEL_TREE_VIEW]] }}
|
||||
[[ref:libraries/wel/reference/wel_tree_view_chart|WEL_TREE_VIEW]] }}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ To compile the example:
|
||||
* Click '''OK'''.
|
||||
|
||||
==Running==
|
||||
After launching the sample, you should see a [[ref:libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] displayed. If you click the left mouse button in the client area of the window, the coordinates of the click (Relative to the top left of the client area), will be displayed. Clicking the [[ref:/libraries/wel/reference/wel_push_button_chart|WEL_PUSH_BUTTON]] marked "Clear" will clear the client area of the window.
|
||||
After launching the sample, you should see a [[ref:libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] displayed. If you click the left mouse button in the client area of the window, the coordinates of the click (Relative to the top left of the client area), will be displayed. Clicking the [[ref:libraries/wel/reference/wel_push_button_chart|WEL_PUSH_BUTTON]] marked "Clear" will clear the client area of the window.
|
||||
==Under the Hood==
|
||||
|
||||
A [[ref:libraries/wel/reference/wel_client_dc_chart|WEL_CLIENT_DC]] is used to display output in the client area of the window during the execution of <code>on_left_button_down</code> which has been redefined in <code>MAIN_WINDOW</code>.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[Property:title|Tutorial Step 1]]
|
||||
[[Property:weight|0]]
|
||||
[[Property:uuid|b952d232-1ef9-04a8-bac4-117185aa316d]]
|
||||
This sample shows you how to set up your first [[ref:/libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] consisting of a single [[ref:/libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] . This is one of the simplest WEL applications you can write, and the output is shown below:
|
||||
This sample shows you how to set up your first [[ref:libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] consisting of a single [[ref:libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] . This is one of the simplest WEL applications you can write, and the output is shown below:
|
||||
|
||||
[[Image:step1|step1]]
|
||||
<br/>
|
||||
@@ -24,9 +24,9 @@ After you launch the sample, You should see the window displayed in the screen a
|
||||
|
||||
==Under the Hood==
|
||||
|
||||
Although this system does nothing except create and display a [[ref:/libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] , it shows how to set up your first [[ref:/libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] .
|
||||
Although this system does nothing except create and display a [[ref:libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] , it shows how to set up your first [[ref:libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] .
|
||||
|
||||
This sample only contains one class, TUTORIAL_STEP1 which inherits [[ref:/libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] and redefines <code>main_window</code>
|
||||
This sample only contains one class, TUTORIAL_STEP1 which inherits [[ref:libraries/wel/reference/wel_application_chart|WEL_APPLICATION]] and redefines <code>main_window</code>
|
||||
|
||||
{{seealso|<br/>
|
||||
[[Inheriting WEL_APPLICATION|Inheriting WEL application]] <br/>
|
||||
|
||||
@@ -21,7 +21,7 @@ This sample builds on tutorial [[Tutorial Step 7|step 7]] , and also demonstrate
|
||||
After launching the sample, you will see a [[ref:libraries/wel/reference/wel_frame_window_chart|WEL_FRAME_WINDOW]] displayed. By holding down the left mouse button, and moving the mouse (Within the client area of the window), you will be able to draw on the client are of the window. Selecting "Line_thickness" from the "Line" menu, will display a [[ref:libraries/wel/reference/wel_modal_dialog_chart|WEL_MODAL_DIALOG]] which allows you to change the thickness of the line that is drawn. If you select "Exit" from the "File" menu, you will be prompted if you wish to exit the application. Selecting "New" from the "File" menu will clear the window. Selecting "Save" from the "File" menu will display a [[ref:libraries/wel/reference/wel_save_file_dialog_chart|WEL_SAVE_FILE_DIALOG]] which allows you to specify the filename and location of the picture you have drawn. Selecting "Open" from the "File" menu will display a [[ref:libraries/wel/reference/wel_open_file_dialog_chart|WEL_OPEN_FILE_DIALOG]] which allows you to specify a previously saved drawing to open.
|
||||
|
||||
==Under the Hood==
|
||||
The [[ref:libraries/wel/reference/wel_open_file_dialog_chart|WEL_OPEN_FILE_DIALOG]] and the [[ref:libraries/wel/reference/wel_save_file_dialog_chart|WEL_SAVE_FILE_DIALOG]] are both activated from the redefinition of <code>on_menu_command</code>. A new class, <code>LINES</code> is now used to store the lines drawn by the user and this inherits [[ref:/libraries/base/reference/storable_chart|STORABLE]] which allows it to be easily stored and retrieved.
|
||||
The [[ref:libraries/wel/reference/wel_open_file_dialog_chart|WEL_OPEN_FILE_DIALOG]] and the [[ref:libraries/wel/reference/wel_save_file_dialog_chart|WEL_SAVE_FILE_DIALOG]] are both activated from the redefinition of <code>on_menu_command</code>. A new class, <code>LINES</code> is now used to store the lines drawn by the user and this inherits [[ref:libraries/base/reference/storable_chart|STORABLE]] which allows it to be easily stored and retrieved.
|
||||
This sample contains the following classes:
|
||||
* <code>TUTORIAL_STEP6</code>
|
||||
* <code>MAIN_WINDOW</code>
|
||||
@@ -32,8 +32,8 @@ This sample contains the following classes:
|
||||
* <code>LINE</code>
|
||||
|
||||
{{seealso|<br/>
|
||||
[[ref:/libraries/wel/reference/wel_save_file_dialog_chart|Save file dialog]] <br/>
|
||||
[[ref:/libraries/wel/reference/wel_open_file_dialog_chart|Open file dialog]] }}
|
||||
[[ref:libraries/wel/reference/wel_save_file_dialog_chart|Save file dialog]] <br/>
|
||||
[[ref:libraries/wel/reference/wel_open_file_dialog_chart|Open file dialog]] }}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ The process of recognizing the successive tokens of a text is called lexical ana
|
||||
|
||||
Besides recognizing the tokens, it is usually necessary to recognize the deeper syntactic structure of the text. This process is called '''parsing''' or '''syntax analysis''' and is studied in the next chapter.
|
||||
|
||||
Figure 1 shows the inheritance structure of the classes discussed in this chapter. Class [[ref:/libraries/parse/reference/l_interface_chart|L_INTERFACE]] has also been included although we will only study it in the [[EiffelParse Tutorial]]; it belongs to the Parse library, where it takes care of the interface between parsing and lexical analysis.
|
||||
Figure 1 shows the inheritance structure of the classes discussed in this chapter. Class [[ref:libraries/parse/reference/l_interface_chart|L_INTERFACE]] has also been included although we will only study it in the [[EiffelParse Tutorial]]; it belongs to the Parse library, where it takes care of the interface between parsing and lexical analysis.
|
||||
|
||||
|
||||
[[Image:figure1]]
|
||||
@@ -34,37 +34,37 @@ The classes of the EiffelLex library make it possible to define lexical grammars
|
||||
|
||||
===Overview of the classes===
|
||||
|
||||
For the user of the EiffelLex library, the classes of most direct interest are [[ref:/libraries/lex/reference/token_chart|TOKEN]] , [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] , [[ref:/libraries/lex/reference/metalex_chart|METALEX]] and [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] .
|
||||
For the user of the EiffelLex library, the classes of most direct interest are [[ref:libraries/lex/reference/token_chart|TOKEN]] , [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] , [[ref:libraries/lex/reference/metalex_chart|METALEX]] and [[ref:libraries/lex/reference/scanning_chart|SCANNING]] .
|
||||
|
||||
An instance of [[ref:/libraries/lex/reference/token_chart|TOKEN]] describes a token read from an input file being analyzed, with such properties as the token type, the corresponding string and the position in the text (line, column) where it was found.
|
||||
An instance of [[ref:libraries/lex/reference/token_chart|TOKEN]] describes a token read from an input file being analyzed, with such properties as the token type, the corresponding string and the position in the text (line, column) where it was found.
|
||||
|
||||
An instance of [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] is a lexical analyzer for a certain lexical grammar. Given a reference to such an instance, say analyzer, you may analyze an input text through calls to the features of class [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] , for example:
|
||||
An instance of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] is a lexical analyzer for a certain lexical grammar. Given a reference to such an instance, say analyzer, you may analyze an input text through calls to the features of class [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] , for example:
|
||||
<code>
|
||||
analyzer.get_token
|
||||
</code>
|
||||
|
||||
Class [[ref:/libraries/lex/reference/metalex_chart|METALEX]] defines facilities for building such lexical analyzers. In particular, it provides features for reading the grammar from a file and building the corresponding analyzer. Classes that need to build and use lexical analyzers may be written as descendants of [[ref:/libraries/lex/reference/metalex_chart|METALEX]] to benefit from its general-purpose facilities.
|
||||
Class [[ref:libraries/lex/reference/metalex_chart|METALEX]] defines facilities for building such lexical analyzers. In particular, it provides features for reading the grammar from a file and building the corresponding analyzer. Classes that need to build and use lexical analyzers may be written as descendants of [[ref:libraries/lex/reference/metalex_chart|METALEX]] to benefit from its general-purpose facilities.
|
||||
|
||||
Class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] is one such descendant of [[ref:/libraries/lex/reference/metalex_chart|METALEX]] . It contains all the facilities needed to build an ordinary lexical analyzer and apply it to the analysis of input texts. Because these facilities are simpler to use and are in most cases sufficient, SCANNING will be discussed first; the finer-grain facilities of [[ref:/libraries/lex/reference/metalex_chart|METALEX]] are described towards the end of this chapter.
|
||||
Class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] is one such descendant of [[ref:libraries/lex/reference/metalex_chart|METALEX]] . It contains all the facilities needed to build an ordinary lexical analyzer and apply it to the analysis of input texts. Because these facilities are simpler to use and are in most cases sufficient, SCANNING will be discussed first; the finer-grain facilities of [[ref:libraries/lex/reference/metalex_chart|METALEX]] are described towards the end of this chapter.
|
||||
|
||||
These classes internally rely on others, some of which may be useful for more advanced applications. [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , one of the supporting classes, will be introduced after [[ref:/libraries/lex/reference/metalex_chart|METALEX]] .
|
||||
These classes internally rely on others, some of which may be useful for more advanced applications. [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , one of the supporting classes, will be introduced after [[ref:libraries/lex/reference/metalex_chart|METALEX]] .
|
||||
|
||||
===Library example===
|
||||
|
||||
The EiffelStudio delivery includes (in the examples/library/lex subdirectory) a simple example using the EiffelLex library classes. The example applies EiffelLex library facilities to the analysis of a language which is none other than Eiffel itself.
|
||||
|
||||
The root class of that example, <eiffel>EIFFEL_SCAN</eiffel>, is only a few lines long; it relies on the general mechanism provided by [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] (see below). The actual lexical grammar is given by a lexical grammar file (a concept explained below): the file of name eiffel_regular in the same directory.
|
||||
The root class of that example, <eiffel>EIFFEL_SCAN</eiffel>, is only a few lines long; it relies on the general mechanism provided by [[ref:libraries/lex/reference/scanning_chart|SCANNING]] (see below). The actual lexical grammar is given by a lexical grammar file (a concept explained below): the file of name eiffel_regular in the same directory.
|
||||
|
||||
===Dealing with finite automata===
|
||||
|
||||
Lexical analysis relies on the theory of finite automata. The most advanced of the classes discussed in this chapter, [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , relies on classes describing various forms of automata:
|
||||
* [[ref:/libraries/lex/reference/dfa_chart|DFA]] : deterministic finite automata.
|
||||
* [[ref:/libraries/lex/reference/pdfa_chart|PDFA]] : partially deterministic finite automata.
|
||||
* [[ref:/libraries/lex/reference/ndfa_chart|NDFA]] : non-deterministic finite automata.
|
||||
* [[ref:/libraries/lex/reference/automaton_chart|AUTOMATON]] , the most general: finite automata.
|
||||
* [[ref:/libraries/lex/reference/fixed_automaton_chart|FIXED_AUTOMATON]] , [[ref:/libraries/lex/reference/linked_automaton_chart|LINKED_AUTOMATON]] .
|
||||
Lexical analysis relies on the theory of finite automata. The most advanced of the classes discussed in this chapter, [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , relies on classes describing various forms of automata:
|
||||
* [[ref:libraries/lex/reference/dfa_chart|DFA]] : deterministic finite automata.
|
||||
* [[ref:libraries/lex/reference/pdfa_chart|PDFA]] : partially deterministic finite automata.
|
||||
* [[ref:libraries/lex/reference/ndfa_chart|NDFA]] : non-deterministic finite automata.
|
||||
* [[ref:libraries/lex/reference/automaton_chart|AUTOMATON]] , the most general: finite automata.
|
||||
* [[ref:libraries/lex/reference/fixed_automaton_chart|FIXED_AUTOMATON]] , [[ref:libraries/lex/reference/linked_automaton_chart|LINKED_AUTOMATON]] .
|
||||
|
||||
These classes may also be useful for systems that need to manipulate finite automata for applications other than lexical analysis. The interface of [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , which includes the features from [[ref:/libraries/lex/reference/automaton_chart|AUTOMATON]] , [[ref:/libraries/lex/reference/ndfa_chart|NDFA]] and [[ref:/libraries/lex/reference/pdfa_chart|PDFA]] , will provide the essential information.
|
||||
These classes may also be useful for systems that need to manipulate finite automata for applications other than lexical analysis. The interface of [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , which includes the features from [[ref:libraries/lex/reference/automaton_chart|AUTOMATON]] , [[ref:libraries/lex/reference/ndfa_chart|NDFA]] and [[ref:libraries/lex/reference/pdfa_chart|PDFA]] , will provide the essential information.
|
||||
|
||||
==TOKENS==
|
||||
|
||||
@@ -78,24 +78,24 @@ A lexical analyzer built through any of the techniques described in the rest of
|
||||
==BUILDING AND USING LEXICAL ANALYZERS==
|
||||
|
||||
The general method for performing lexical analysis is the following.
|
||||
# Create an instance of [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] , giving a lexical analyzer for the desired grammar.
|
||||
# Create an instance of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] , giving a lexical analyzer for the desired grammar.
|
||||
# Store the analyzer into a file.
|
||||
# Retrieve the analyzer from the file.
|
||||
# Use the analyzer to analyze the tokens of one or more input texts by calling the various features of class [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] on this object.
|
||||
# Use the analyzer to analyze the tokens of one or more input texts by calling the various features of class [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] on this object.
|
||||
|
||||
Steps 2 and 3 are obviously unnecessary if this process is applied as a single sequence. But in almost all practical cases you will want to use the same grammar to analyze many different input texts. Then steps 1 and 2 will be performed once and for all as soon as the lexical grammar is known, yielding an instance of [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] that step 2 stores into a file; then in every case that requires analyzing a text you will simply retrieve the analyzer and apply it, performing steps 3 and 4 only.
|
||||
Steps 2 and 3 are obviously unnecessary if this process is applied as a single sequence. But in almost all practical cases you will want to use the same grammar to analyze many different input texts. Then steps 1 and 2 will be performed once and for all as soon as the lexical grammar is known, yielding an instance of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] that step 2 stores into a file; then in every case that requires analyzing a text you will simply retrieve the analyzer and apply it, performing steps 3 and 4 only.
|
||||
|
||||
The simplest way to store and retrieve the instance of [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] and all related objects is to use the facilities of class [[ref:/libraries/base/reference/storable_chart|STORABLE]] : procedure store and one of the retrieval procedures. To facilitate this process, [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] inherits from [[ref:/libraries/base/reference/storable_chart|STORABLE]] .
|
||||
The simplest way to store and retrieve the instance of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] and all related objects is to use the facilities of class [[ref:libraries/base/reference/storable_chart|STORABLE]] : procedure store and one of the retrieval procedures. To facilitate this process, [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] inherits from [[ref:libraries/base/reference/storable_chart|STORABLE]] .
|
||||
|
||||
The next sections explain how to perform these various steps. In the most common case, the best technique is to inherit from class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , which provides a framework for retrieving an analyzer file if it exists, creating it from a grammar description otherwise, and proceed with the lexical analysis of one or more input texts.
|
||||
The next sections explain how to perform these various steps. In the most common case, the best technique is to inherit from class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , which provides a framework for retrieving an analyzer file if it exists, creating it from a grammar description otherwise, and proceed with the lexical analysis of one or more input texts.
|
||||
|
||||
==LEXICAL GRAMMAR FILES AND CLASS SCANNING==
|
||||
|
||||
Class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] may be used as an ancestor by classes that need to perform lexical analysis. When using [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] you will need a '''lexical grammar file''' that contains the description of the lexical grammar. Since it is easy to edit and adapt a file without modifying the software proper, this technique provides flexibility and supports the incremental development and testing of lexical analyzers.
|
||||
Class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] may be used as an ancestor by classes that need to perform lexical analysis. When using [[ref:libraries/lex/reference/scanning_chart|SCANNING]] you will need a '''lexical grammar file''' that contains the description of the lexical grammar. Since it is easy to edit and adapt a file without modifying the software proper, this technique provides flexibility and supports the incremental development and testing of lexical analyzers.
|
||||
|
||||
===The build procedure===
|
||||
|
||||
To obtain a lexical analyzer in a descendant of class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , use the procedure
|
||||
To obtain a lexical analyzer in a descendant of class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , use the procedure
|
||||
<code>
|
||||
build (store_file_name, grammar_file_name: STRING)</code>
|
||||
|
||||
@@ -146,7 +146,7 @@ This will read in and process successive input tokens. Procedure <eiffel>analyze
|
||||
|
||||
The initial action <eiffel>begin_analysis</eiffel>, which by default prints a header, and the terminal action <eiffel>end_analysis</eiffel>, which by default does nothing, may also be redefined.
|
||||
|
||||
To build lexical analyzers which provide a higher degree of flexibility, use [[ref:/libraries/lex/reference/metalex_chart|METALEX]] or [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , as described in the last part of this chapter.
|
||||
To build lexical analyzers which provide a higher degree of flexibility, use [[ref:libraries/lex/reference/metalex_chart|METALEX]] or [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , as described in the last part of this chapter.
|
||||
|
||||
==ANALYZING INPUT==
|
||||
|
||||
@@ -154,9 +154,9 @@ Let us look more precisely at how we can use a lexical analyzer to analyze an in
|
||||
|
||||
===Class LEXICAL===
|
||||
|
||||
Procedure <eiffel>analyze</eiffel> takes care of the most common needs of lexical analysis. But if you need more advanced lexical analysis facilities you will need an instance of class [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] (a direct instance of [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] itself or of one of its proper descendants). If you are using class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] as described above, you will have access to such an instance through the attribute <eiffel>analyzer</eiffel>.
|
||||
Procedure <eiffel>analyze</eiffel> takes care of the most common needs of lexical analysis. But if you need more advanced lexical analysis facilities you will need an instance of class [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] (a direct instance of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] itself or of one of its proper descendants). If you are using class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] as described above, you will have access to such an instance through the attribute <eiffel>analyzer</eiffel>.
|
||||
|
||||
This discussion will indeed assume that you have an entity attached to an instance of [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] . The name of that entity is assumed to be <eiffel>analyzer</eiffel>, although it does not need to be the attribute from [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] . You can apply to that <eiffel>analyzer</eiffel> the various exported features features of class [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] , explained below. All the calls described below should use <eiffel>analyzer</eiffel> as their target, as in
|
||||
This discussion will indeed assume that you have an entity attached to an instance of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] . The name of that entity is assumed to be <eiffel>analyzer</eiffel>, although it does not need to be the attribute from [[ref:libraries/lex/reference/scanning_chart|SCANNING]] . You can apply to that <eiffel>analyzer</eiffel> the various exported features features of class [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] , explained below. All the calls described below should use <eiffel>analyzer</eiffel> as their target, as in
|
||||
<code>
|
||||
analyzer.set_file ("my_file_name")
|
||||
</code>
|
||||
@@ -168,12 +168,12 @@ To create a new analyzer, use
|
||||
create analyzer.make_new
|
||||
</code>
|
||||
|
||||
You may also retrieve an analyzer from a previous session. [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] is a descendant from [[ref:/libraries/base/reference/storable_chart|STORABLE]] , so you can use feature retrieved for that purpose. In a descendant of [[ref:/libraries/base/reference/storable_chart|STORABLE]] , simply write
|
||||
You may also retrieve an analyzer from a previous session. [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] is a descendant from [[ref:libraries/base/reference/storable_chart|STORABLE]] , so you can use feature retrieved for that purpose. In a descendant of [[ref:libraries/base/reference/storable_chart|STORABLE]] , simply write
|
||||
<code>
|
||||
analyzer ?= retrieved
|
||||
</code>
|
||||
|
||||
If you do not want to make the class a descendant of [[ref:/libraries/base/reference/storable_chart|STORABLE]] , use the creation procedure <eiffel>make</eiffel> of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] , not to be confused with <eiffel>make_new</eiffel> above:
|
||||
If you do not want to make the class a descendant of [[ref:libraries/base/reference/storable_chart|STORABLE]] , use the creation procedure <eiffel>make</eiffel> of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] , not to be confused with <eiffel>make_new</eiffel> above:
|
||||
<code>
|
||||
create analyzer.make
|
||||
analyzer ?= analyzer.retrieved
|
||||
@@ -183,12 +183,12 @@ If you do not want to make the class a descendant of [[ref:/libraries/base/refer
|
||||
|
||||
To analyze a text, call <eiffel>set_file</eiffel> or <eiffel>set_string</eiffel> to specify the document to be parsed. With the first call, the analysis will be applied to a file; with the second, to a string.
|
||||
|
||||
{{note|if you use procedure <eiffel>analyze</eiffel> of [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , you do not need any such call, since <eiffel>analyze</eiffel> calls <eiffel>set_file</eiffel> on the file name passed as argument. }}
|
||||
{{note|if you use procedure <eiffel>analyze</eiffel> of [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , you do not need any such call, since <eiffel>analyze</eiffel> calls <eiffel>set_file</eiffel> on the file name passed as argument. }}
|
||||
|
||||
===Obtaining the tokens===
|
||||
|
||||
The basic procedure for analyzing successive tokens in the text is <eiffel>get_token</eiffel>, which reads in one token and sets up various attributes of the analyzer to record properties of that token:
|
||||
* <eiffel>last_token</eiffel>, a function of type [[ref:/libraries/lex/reference/token_chart|TOKEN]] , which provides all necessary information on the last token read.
|
||||
* <eiffel>last_token</eiffel>, a function of type [[ref:libraries/lex/reference/token_chart|TOKEN]] , which provides all necessary information on the last token read.
|
||||
* <eiffel>token_line_number</eiffel> and<eiffel> token_column_number</eiffel>, to know where the token is in the text. These queries return results of type <eiffel>INTEGER</eiffel>.
|
||||
* <eiffel>token_type</eiffel>, giving the regular expression type, identified by its integer number (which is the value <eiffel>No_token</eiffel> if no correct token was recognized).
|
||||
* <eiffel>other_possible_tokens</eiffel>, an array giving all the other possible token types of the last token. (If <eiffel>token_type</eiffel> is <eiffel>No_token</eiffel> the array is empty.)
|
||||
@@ -218,13 +218,13 @@ Here is the most common way of using the preceding facilities:
|
||||
end_analysis
|
||||
</code>
|
||||
|
||||
This scheme is used by procedure <eiffel>analyze</eiffel> of class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , so that in standard cases you may simply inherit from that class and redefine procedures <eiffel>begin_analysis</eiffel>, <eiffel>do_a_token</eiffel>, and <eiffel>end_analysis</eiffel>. If you are not inheriting from [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , these names simply denote procedures that you must provide.
|
||||
This scheme is used by procedure <eiffel>analyze</eiffel> of class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , so that in standard cases you may simply inherit from that class and redefine procedures <eiffel>begin_analysis</eiffel>, <eiffel>do_a_token</eiffel>, and <eiffel>end_analysis</eiffel>. If you are not inheriting from [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , these names simply denote procedures that you must provide.
|
||||
|
||||
==REGULAR EXPRESSIONS==
|
||||
|
||||
The EiffelLex library supports a powerful set of construction mechanisms for describing the various types of tokens present in common languages such as programming languages, specification languages or just text formats. These mechanisms are called '''regular expressions'''; any regular expression describes a set of possible tokens, called the '''specimens''' of the regular expression.
|
||||
|
||||
Let us now study the format of regular expressions. This format is used in particular for the lexical grammar files needed by class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] and (as seen below) by procedure <eiffel>read_grammar</eiffel> of class [[ref:/libraries/lex/reference/metalex_chart|METALEX]] . The ''eiffel_regular'' grammar file in the examples directory provides an extensive example.
|
||||
Let us now study the format of regular expressions. This format is used in particular for the lexical grammar files needed by class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] and (as seen below) by procedure <eiffel>read_grammar</eiffel> of class [[ref:libraries/lex/reference/metalex_chart|METALEX]] . The ''eiffel_regular'' grammar file in the examples directory provides an extensive example.
|
||||
|
||||
Each regular expression denotes a set of tokens. For example, the first regular expression seen above, <br/>
|
||||
|
||||
@@ -401,7 +401,7 @@ BOOLEAN
|
||||
|
||||
{{caution|Every keyword in the keyword section must be a specimen of one of the token types defined for the grammar, and that token type must be the last one defined in the lexical grammar file, just before the '''Keywords''' line. So in Eiffel where the keywords have the same lexical structure as identifiers, the last line before the keywords must be the definition of the token type ''Identifier'', as shown above. }}
|
||||
|
||||
{{note|The rule that all keywords must be specimens of one token type is a matter of convenience and simplicity, and only applies if you are using SCANNING and lexical grammar files. There is no such restriction if you rely directly on the more general facilities provided by [[ref:/libraries/lex/reference/metalex_chart|METALEX]] or [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] . Then different keywords may be specimens of different regular expressions; you will have to specify the token type of every keyword, as explained later in this chapter. }}
|
||||
{{note|The rule that all keywords must be specimens of one token type is a matter of convenience and simplicity, and only applies if you are using SCANNING and lexical grammar files. There is no such restriction if you rely directly on the more general facilities provided by [[ref:libraries/lex/reference/metalex_chart|METALEX]] or [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] . Then different keywords may be specimens of different regular expressions; you will have to specify the token type of every keyword, as explained later in this chapter. }}
|
||||
|
||||
===Case sensitivity===
|
||||
|
||||
@@ -433,19 +433,19 @@ The inverse call, corresponding to the default rule, is
|
||||
keywords_ignore_case
|
||||
</code>
|
||||
|
||||
Either of these calls must be executed before you define any keywords; if you are using [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , this means before calling procedure build. Once set, the keyword case-sensitivity policy cannot be changed.
|
||||
Either of these calls must be executed before you define any keywords; if you are using [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , this means before calling procedure build. Once set, the keyword case-sensitivity policy cannot be changed.
|
||||
|
||||
==USING METALEX TO BUILD A LEXICAL ANALYZER==
|
||||
|
||||
(You may skip the rest of this chapter if you only need simple lexical facilities.)
|
||||
|
||||
Class [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , as studied above, relies on a class [[ref:/libraries/lex/reference/metalex_chart|METALEX]] . In some cases, you may prefer to use the features of [[ref:/libraries/lex/reference/metalex_chart|METALEX]] directly. Since [[ref:libraries/lex/reference/scanning_chart|SCANNING]] inherits from [[ref:/libraries/lex/reference/metalex_chart|METALEX]] , anything you do with [[ref:/libraries/lex/reference/metalex_chart|METALEX]] can in fact be done with [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , but you may wish to stay with just [[ref:/libraries/lex/reference/metalex_chart|METALEX]] if you do not need the additional features of [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] .
|
||||
Class [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , as studied above, relies on a class [[ref:libraries/lex/reference/metalex_chart|METALEX]] . In some cases, you may prefer to use the features of [[ref:libraries/lex/reference/metalex_chart|METALEX]] directly. Since [[ref:libraries/lex/reference/scanning_chart|SCANNING]] inherits from [[ref:libraries/lex/reference/metalex_chart|METALEX]] , anything you do with [[ref:libraries/lex/reference/metalex_chart|METALEX]] can in fact be done with [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , but you may wish to stay with just [[ref:libraries/lex/reference/metalex_chart|METALEX]] if you do not need the additional features of [[ref:libraries/lex/reference/scanning_chart|SCANNING]] .
|
||||
|
||||
===Steps in using METALEX===
|
||||
|
||||
[[ref:/libraries/lex/reference/metalex_chart|METALEX]] has an attribute analyzer which will be attached to a lexical analyzer. This class provides tools for building a lexical analyzer incrementally through explicit feature calls; you can still use a lexical grammar file, but do not have to.
|
||||
[[ref:libraries/lex/reference/metalex_chart|METALEX]] has an attribute analyzer which will be attached to a lexical analyzer. This class provides tools for building a lexical analyzer incrementally through explicit feature calls; you can still use a lexical grammar file, but do not have to.
|
||||
|
||||
The following extract from a typical descendant of [[ref:/libraries/lex/reference/metalex_chart|METALEX]] illustrates the process of building a lexical analyzer in this way:
|
||||
The following extract from a typical descendant of [[ref:libraries/lex/reference/metalex_chart|METALEX]] illustrates the process of building a lexical analyzer in this way:
|
||||
<code>
|
||||
Upper_identifier, Lower_identifier, Decimal_constant, Octal_constant, Word: INTEGER is unique
|
||||
|
||||
@@ -467,13 +467,13 @@ The following extract from a typical descendant of [[ref:/libraries/lex/referenc
|
||||
make_analyzer
|
||||
</code>
|
||||
|
||||
This example follows the general scheme of building a lexical analyzer with the features of [[ref:/libraries/lex/reference/metalex_chart|METALEX]] , in a class that will normally be a descendant of [[ref:libraries/lex/reference/metalex_chart|METALEX]] :
|
||||
This example follows the general scheme of building a lexical analyzer with the features of [[ref:libraries/lex/reference/metalex_chart|METALEX]] , in a class that will normally be a descendant of [[ref:libraries/lex/reference/metalex_chart|METALEX]] :
|
||||
# Set options, such as case sensitivity.
|
||||
# Record regular expressions.
|
||||
# Record keywords (this may be interleaved with step 2.)
|
||||
# "Freeze" the analyzer by a call to <eiffel>make_analyzer</eiffel>.
|
||||
|
||||
To perform steps 2 to 4 in a single shot and generate a lexical analyzer from a lexical grammar file, as with [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] , you may use the procedure
|
||||
To perform steps 2 to 4 in a single shot and generate a lexical analyzer from a lexical grammar file, as with [[ref:libraries/lex/reference/scanning_chart|SCANNING]] , you may use the procedure
|
||||
<code>
|
||||
read_grammar (grammar_file_name: STRING)
|
||||
</code>
|
||||
@@ -492,7 +492,7 @@ Procedure <eiffel>dollar_w</eiffel> corresponds to the '''$W''' syntax for regul
|
||||
put_nameless_expression ( "$W" ,Word )
|
||||
</code>
|
||||
|
||||
Procedure <eiffel>declare_keyword</eiffel> records a keyword. The first argument is a string containing the keyword; the second argument is the regular expression of which the keyword must be a specimen. The example shows that here - in contrast with the rule enforced by [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] - not all keywords need be specimens of the same regular expression.
|
||||
Procedure <eiffel>declare_keyword</eiffel> records a keyword. The first argument is a string containing the keyword; the second argument is the regular expression of which the keyword must be a specimen. The example shows that here - in contrast with the rule enforced by [[ref:libraries/lex/reference/scanning_chart|SCANNING]] - not all keywords need be specimens of the same regular expression.
|
||||
|
||||
The calls seen so far record a number of regular expressions and keywords, but do not give us a lexical analyzer yet. To obtain a usable lexical analyzer, you must call
|
||||
<code>
|
||||
@@ -503,17 +503,17 @@ After that call, you may not record any new regular expression or keyword. The a
|
||||
{{note|for readers knowledgeable in the theory of lexical analysis: one of the most important effects of the call to <eiffel>make_analyzer</eiffel> is to transform the non-deterministic finite automaton resulting from calls such as the ones above into a deterministic finite automaton. }}
|
||||
|
||||
Remember that if you use procedure <eiffel>read_grammar</eiffel>, you need not worry about <eiffel>make_analyzer</eiffel>, as the former procedure calls the latter.
|
||||
Another important feature of class [[ref:/libraries/lex/reference/metalex_chart|METALEX]] is procedure <eiffel>store_analyzer</eiffel>, which stores the analyzer into a file whose name is passed as argument, for use by later lexical analysis sessions. To retrieve the analyzer, simply use procedure <eiffel>retrieve_analyzer</eiffel>, again with a file name as argument.
|
||||
Another important feature of class [[ref:libraries/lex/reference/metalex_chart|METALEX]] is procedure <eiffel>store_analyzer</eiffel>, which stores the analyzer into a file whose name is passed as argument, for use by later lexical analysis sessions. To retrieve the analyzer, simply use procedure <eiffel>retrieve_analyzer</eiffel>, again with a file name as argument.
|
||||
|
||||
==BUILDING A LEXICAL ANALYZER WITH LEX_BUILDER==
|
||||
|
||||
|
||||
|
||||
To have access to the most general set of lexical analysis mechanisms, you may use class [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , which gives you an even finer grain of control than [[ref:/libraries/lex/reference/metalex_chart|METALEX]] . This is not necessary in simple applications.
|
||||
To have access to the most general set of lexical analysis mechanisms, you may use class [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] , which gives you an even finer grain of control than [[ref:libraries/lex/reference/metalex_chart|METALEX]] . This is not necessary in simple applications.
|
||||
|
||||
===Building a lexical analyzer===
|
||||
|
||||
[[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] enables you to build a lexical analyzer by describing successive token types and keywords. This is normally done in a descendant of [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] . For each token type, you call a procedure that builds an object, or '''tool''', representing the associated regular expression.
|
||||
[[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] enables you to build a lexical analyzer by describing successive token types and keywords. This is normally done in a descendant of [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] . For each token type, you call a procedure that builds an object, or '''tool''', representing the associated regular expression.
|
||||
|
||||
For the complete list of available procedures, refer to the flat-short form of the class; there is one procedure for every category of regular expression studied earlier in this chapter. Two typical examples of calls are:
|
||||
<code>
|
||||
@@ -527,7 +527,7 @@ For the complete list of available procedures, refer to the flat-short form of t
|
||||
Every such procedure call also assigns an integer index to the tool it creates; this number is available through the attribute <eiffel>last_created_tool</eiffel>. You will need to record it into an integer entity, for example <eiffel>Identifier</eiffel> or <eiffel>Letter</eiffel>.
|
||||
===An example===
|
||||
|
||||
The following extract from a typical descendant of [[ref:/libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] illustrates how to create a tool representing the identifiers of an Eiffel-like language.
|
||||
The following extract from a typical descendant of [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] illustrates how to create a tool representing the identifiers of an Eiffel-like language.
|
||||
<code>
|
||||
Identifier, Letter, Digit, Underlined, Suffix, Suffix_list: INTEGER
|
||||
|
||||
|
||||
@@ -66,14 +66,14 @@ As noted at the beginning of this chapter, it is possible to build a single synt
|
||||
==LIBRARY CLASSES==
|
||||
|
||||
The EiffelParse library contains a small number of classes which cover common document processing applications. The classes, whose inheritance structure was shown at the beginning of this chapter, are:
|
||||
* [[ref:/libraries/parse/reference/construct_chart|CONSTRUCT]] , describing the general notion of syntactical construct.
|
||||
* [[ref:/libraries/parse/reference/aggregate_chart|AGGREGATE]] , describing constructs of the "aggregate" form.
|
||||
* [[ref:/libraries/parse/reference/choice_chart|CHOICE]] , describing constructs of the "choice" form.
|
||||
* [[ref:/libraries/parse/reference/repetition_chart|REPETITION]] , describing constructs of the "repetition" form.
|
||||
* [[ref:/libraries/parse/reference/terminal_chart|TERMINAL]] , describing "terminal" constructs with no further structure.
|
||||
* [[ref:/libraries/parse/reference/keyword_chart|KEYWORD]] , describing how to handle keywords.
|
||||
* [[ref:/libraries/parse/reference/l_interface_chart|L_INTERFACE]] , providing a simple interface with the lexical analysis process and the Lex library.
|
||||
* [[ref:/libraries/parse/reference/input_chart|INPUT]] , describing how to handle the input document.
|
||||
* [[ref:libraries/parse/reference/construct_chart|CONSTRUCT]] , describing the general notion of syntactical construct.
|
||||
* [[ref:libraries/parse/reference/aggregate_chart|AGGREGATE]] , describing constructs of the "aggregate" form.
|
||||
* [[ref:libraries/parse/reference/choice_chart|CHOICE]] , describing constructs of the "choice" form.
|
||||
* [[ref:libraries/parse/reference/repetition_chart|REPETITION]] , describing constructs of the "repetition" form.
|
||||
* [[ref:libraries/parse/reference/terminal_chart|TERMINAL]] , describing "terminal" constructs with no further structure.
|
||||
* [[ref:libraries/parse/reference/keyword_chart|KEYWORD]] , describing how to handle keywords.
|
||||
* [[ref:libraries/parse/reference/l_interface_chart|L_INTERFACE]] , providing a simple interface with the lexical analysis process and the Lex library.
|
||||
* [[ref:libraries/parse/reference/input_chart|INPUT]] , describing how to handle the input document.
|
||||
|
||||
==EXAMPLES==
|
||||
The EiffelStudio delivery includes (in the examples/library/parse subdirectory) a simple example using the EiffelParse Library classes. The example is a processor for "documents" which describe computations involving polynomials with variables. The corresponding processor is a system which obtains polynomial specifications and variable values from a user, and computes the corresponding polynomials.
|
||||
@@ -100,7 +100,7 @@ Although some notations for syntax descriptions such as BNF allow more than one
|
||||
* A terminal construct has no defining production. This means that it must be defined outside of the syntactical grammar. Terminals indeed come from the '''lexical grammar'''. Every terminal construct corresponds to a token type (regular expression or keyword) of the lexical grammar, for which the parsing duty will be delegated to lexical mechanisms, assumed in the rest of this chapter to be provided by the Lex library although others may be substituted if appropriate.
|
||||
|
||||
|
||||
All specimens of terminal constructs are instances of class [[ref:/libraries/parse/reference/terminal_chart|TERMINAL]] . A special case is that of keyword constructs, which have a single specimen corresponding to a keyword of the language. For example, <code>if</code> is a keyword of Eiffel. Keywords are described by class [[ref:/libraries/parse/reference/keyword_chart|KEYWORD]] , an heir of [[ref:/libraries/parse/reference/terminal_chart|TERMINAL]] .
|
||||
All specimens of terminal constructs are instances of class [[ref:libraries/parse/reference/terminal_chart|TERMINAL]] . A special case is that of keyword constructs, which have a single specimen corresponding to a keyword of the language. For example, <code>if</code> is a keyword of Eiffel. Keywords are described by class [[ref:libraries/parse/reference/keyword_chart|KEYWORD]] , an heir of [[ref:libraries/parse/reference/terminal_chart|TERMINAL]] .
|
||||
|
||||
The rest of this section concentrates on the parsing-specific part: non-terminal constructs and productions. Terminals will be studied in the discussion of how to interface parsing with lexical analysis.
|
||||
|
||||
@@ -158,9 +158,9 @@ The EiffelParse library supports a parsing mechanism based on the concepts of ob
|
||||
|
||||
===Class CONSTRUCT===
|
||||
|
||||
The deferred class [[ref:/libraries/parse/reference/construct_chart|CONSTRUCT]] describes the general notion of construct; instances of this class and its descendants are specimens of the constructs of a grammar.
|
||||
The deferred class [[ref:libraries/parse/reference/construct_chart|CONSTRUCT]] describes the general notion of construct; instances of this class and its descendants are specimens of the constructs of a grammar.
|
||||
|
||||
Deferred though it may be, [[ref:/libraries/parse/reference/construct_chart|CONSTRUCT]] defines some useful general patterns; for example, its procedure process appears as: <br/>
|
||||
Deferred though it may be, [[ref:libraries/parse/reference/construct_chart|CONSTRUCT]] defines some useful general patterns; for example, its procedure process appears as: <br/>
|
||||
<code>
|
||||
parse
|
||||
if parsed then
|
||||
@@ -170,11 +170,11 @@ Deferred though it may be, [[ref:/libraries/parse/reference/construct_chart|CONS
|
||||
<br/>
|
||||
where procedures <eiffel>parse</eiffel> and <eiffel>semantics</eiffel> are expressed in terms of some more specific procedures, which are deferred. This defines a general scheme while leaving the details to descendants of the class.
|
||||
|
||||
Such descendants, given in the library, are classes [[ref:/libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:/libraries/parse/reference/choice_chart|CHOICE]] , [[ref:/libraries/parse/reference/repetition_chart|REPETITION]] and [[ref:/libraries/parse/reference/terminal_chart|TERMINAL]] . They describe the corresponding types of construct, with features providing the operations for parsing their specimens and applying the associated semantic actions.
|
||||
Such descendants, given in the library, are classes [[ref:libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:libraries/parse/reference/choice_chart|CHOICE]] , [[ref:libraries/parse/reference/repetition_chart|REPETITION]] and [[ref:libraries/parse/reference/terminal_chart|TERMINAL]] . They describe the corresponding types of construct, with features providing the operations for parsing their specimens and applying the associated semantic actions.
|
||||
|
||||
===Building a processor===
|
||||
|
||||
To build a processor for a given grammar, you write a class, called a '''construct class''', for every construct of the grammar, terminal or non-terminal. The class should inherit from [[ref:/libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:/libraries/parse/reference/choice_chart|CHOICE]] , [[ref:/libraries/parse/reference/repetition_chart|REPETITION]] or [[ref:/libraries/parse/reference/terminal_chart|TERMINAL]] depending on the nature of the construct. It describes the production for the construct and any associated semantic actions.
|
||||
To build a processor for a given grammar, you write a class, called a '''construct class''', for every construct of the grammar, terminal or non-terminal. The class should inherit from [[ref:libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:libraries/parse/reference/choice_chart|CHOICE]] , [[ref:libraries/parse/reference/repetition_chart|REPETITION]] or [[ref:libraries/parse/reference/terminal_chart|TERMINAL]] depending on the nature of the construct. It describes the production for the construct and any associated semantic actions.
|
||||
|
||||
To complete the processor, you must choose a "top construct" for that particular processor, and write a root class. In accordance with the object-oriented method, which implies that "roots" and "tops" should be chosen last, these steps are explained at the end of this chapter.
|
||||
|
||||
@@ -186,9 +186,9 @@ The effect of processing a document with a processor built from a combination of
|
||||
|
||||
The syntax tree is said to be abstract because it only includes important structural information and does not retain the concrete information such as keywords and separators. Such concrete information, sometimes called "syntactic sugar", serves only external purposes but is of no use for semantic processing.
|
||||
|
||||
The combination of Eiffel techniques and libraries yields a very simple approach to building and processing abstract syntax trees. Class [[ref:/libraries/parse/reference/construct_chart|CONSTRUCT]] is a descendant of the Data Structure Library class [[ref:/libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] , describing a versatile implementation of trees; so, as a consequence, are [[ref:/libraries/parse/reference/construct_chart|CONSTRUCT's]] own descendants. The effect of parsing any specimen of a construct is therefore to create an instance of the corresponding construct class. This instance is (among other things) a tree node, and is automatically inserted at its right place in the abstract syntax tree.
|
||||
The combination of Eiffel techniques and libraries yields a very simple approach to building and processing abstract syntax trees. Class [[ref:libraries/parse/reference/construct_chart|CONSTRUCT]] is a descendant of the Data Structure Library class [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] , describing a versatile implementation of trees; so, as a consequence, are [[ref:libraries/parse/reference/construct_chart|CONSTRUCT's]] own descendants. The effect of parsing any specimen of a construct is therefore to create an instance of the corresponding construct class. This instance is (among other things) a tree node, and is automatically inserted at its right place in the abstract syntax tree.
|
||||
|
||||
As noted in the discussion of trees, class [[ref:/libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] makes no formal distinction between the notions of tree and tree node. So you may identify the abstract syntax tree with the object (instance of [[ref:/libraries/parse/reference/construct_chart|CONSTRUCT]] ) representing the topmost construct specimen in the structure of the document being analyzed.
|
||||
As noted in the discussion of trees, class [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] makes no formal distinction between the notions of tree and tree node. So you may identify the abstract syntax tree with the object (instance of [[ref:libraries/parse/reference/construct_chart|CONSTRUCT]] ) representing the topmost construct specimen in the structure of the document being analyzed.
|
||||
|
||||
===The production function===
|
||||
|
||||
@@ -200,9 +200,9 @@ A construct class describes the syntax of a given construct through a function c
|
||||
end
|
||||
</code>
|
||||
|
||||
Function production remains deferred in classes [[ref:/libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:/libraries/parse/reference/choice_chart|CHOICE]] and [[ref:/libraries/parse/reference/repetition_chart|REPETITION]] . Every effective construct class that you write must provide an effecting of that function. It is important for the efficiency of the parsing process that every effective version of production be a <eiffel>once</eiffel> function. Several examples of such effectings are given below.
|
||||
Function production remains deferred in classes [[ref:libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:libraries/parse/reference/choice_chart|CHOICE]] and [[ref:libraries/parse/reference/repetition_chart|REPETITION]] . Every effective construct class that you write must provide an effecting of that function. It is important for the efficiency of the parsing process that every effective version of production be a <eiffel>once</eiffel> function. Several examples of such effectings are given below.
|
||||
|
||||
Classes [[ref:/libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:/libraries/parse/reference/choice_chart|CHOICE]] , [[ref:/libraries/parse/reference/repetition_chart|REPETITION]] and [[ref:/libraries/parse/reference/terminal_chart|TERMINAL]] also have a deferred function <eiffel>construct_name</eiffel> of type STRING, useful for tracing and debugging. This function should be effected in every construct class to return the string name of the construct, such as "INSTRUCTION" or "CLASS" for construct classes in a grammar of Eiffel. For efficiency reasons, the <eiffel>construct_name</eiffel> function should also be a <eiffel>once</eiffel> function. The form of such a function will always be the same, as illustrated by the following example which may appear in the construct class <eiffel>INSTRUCTION</eiffel> in a processor for Eiffel:
|
||||
Classes [[ref:libraries/parse/reference/aggregate_chart|AGGREGATE]] , [[ref:libraries/parse/reference/choice_chart|CHOICE]] , [[ref:libraries/parse/reference/repetition_chart|REPETITION]] and [[ref:libraries/parse/reference/terminal_chart|TERMINAL]] also have a deferred function <eiffel>construct_name</eiffel> of type STRING, useful for tracing and debugging. This function should be effected in every construct class to return the string name of the construct, such as "INSTRUCTION" or "CLASS" for construct classes in a grammar of Eiffel. For efficiency reasons, the <eiffel>construct_name</eiffel> function should also be a <eiffel>once</eiffel> function. The form of such a function will always be the same, as illustrated by the following example which may appear in the construct class <eiffel>INSTRUCTION</eiffel> in a processor for Eiffel:
|
||||
<code>
|
||||
construct_name: STRING
|
||||
-- Symbolic name of the construct
|
||||
@@ -217,7 +217,7 @@ The examples of the next few sections, which explain how to write construct clas
|
||||
|
||||
Having studied the EiffelParse library principles, let us see how to write grammar productions for various kinds of construct. The main task is to write the production function for each construct class.
|
||||
|
||||
The production function for a descendant of [[ref:/libraries/parse/reference/aggregate_chart|AGGREGATE]] will describe how to build a specimen of the corresponding function from a sequence of specimens of each of the constituent constructs. Writing this function from the corresponding production is straightforward.
|
||||
The production function for a descendant of [[ref:libraries/parse/reference/aggregate_chart|AGGREGATE]] will describe how to build a specimen of the corresponding function from a sequence of specimens of each of the constituent constructs. Writing this function from the corresponding production is straightforward.
|
||||
|
||||
As an example, consider the production function of class LINE for the Polynomial example language. The corresponding production is <br/>
|
||||
<code>
|
||||
@@ -321,7 +321,7 @@ Then for each alternative component represented by a local entity component (in
|
||||
|
||||
===Repetitions===
|
||||
|
||||
The <eiffel>production</eiffel> function for a descendant of [[ref:/libraries/parse/reference/repetition_chart|REPETITION]] will describe how to build a specimen of the corresponding function as a sequence or zero or more (or, depending on the grammar, one or more) specimens of the base construct. The class must also effect a feature <eiffel>separator</eiffel> of type <eiffel>STRING</eiffel>, usually as a constant attribute. (This feature is introduced as deferred in class [[ref:/libraries/parse/reference/repetition_chart|REPETITION]] .)
|
||||
The <eiffel>production</eiffel> function for a descendant of [[ref:libraries/parse/reference/repetition_chart|REPETITION]] will describe how to build a specimen of the corresponding function as a sequence or zero or more (or, depending on the grammar, one or more) specimens of the base construct. The class must also effect a feature <eiffel>separator</eiffel> of type <eiffel>STRING</eiffel>, usually as a constant attribute. (This feature is introduced as deferred in class [[ref:libraries/parse/reference/repetition_chart|REPETITION]] .)
|
||||
|
||||
As an example, consider the construct Variables in the Polynomial example language. The right-hand side of the corresponding production is <br/>
|
||||
<code>
|
||||
@@ -363,7 +363,7 @@ Lexical interface classes usually follow a common pattern. To take advantage of
|
||||
L_INTERFACE is a simple deferred class, with a deferred procedure <eiffel>obtain_analyzer</eiffel>. It is an heir of METALEX.
|
||||
===Obtaining a lexical analyzer===
|
||||
|
||||
An effective descendant of [[ref:/libraries/parse/reference/l_interface_chart|L_INTERFACE]] must define procedure <eiffel>obtain_analyzer</eiffel> so that it records into the lexical analyzer the regular expressions and keywords of the language at hand. In writing <eiffel>obtain_analyzer</eiffel> you may use any one of three different techniques, each of which may be the most convenient depending on the precise context, to obtain the required lexical analyzer:
|
||||
An effective descendant of [[ref:libraries/parse/reference/l_interface_chart|L_INTERFACE]] must define procedure <eiffel>obtain_analyzer</eiffel> so that it records into the lexical analyzer the regular expressions and keywords of the language at hand. In writing <eiffel>obtain_analyzer</eiffel> you may use any one of three different techniques, each of which may be the most convenient depending on the precise context, to obtain the required lexical analyzer:
|
||||
* You may build the lexical analyzer by defining its regular expressions one by one, using the procedures described in the presentation of METALEX, in particular <eiffel>put_expression</eiffel> and <eiffel>put_keyword</eiffel>.
|
||||
* You may use use procedure <eiffel>retrieve_analyzer</eiffel> from METALEX to retrieve an analyzer which a previous session saved into a file.
|
||||
* Finally, you may write a lexical grammar file (or reuse an existing one) and process it on the spot by using procedure <eiffel>read_grammar</eiffel> from METALEX.
|
||||
@@ -670,7 +670,7 @@ The call build <code> ( </code>document takes care of steps [[#step_e1|1]] and
|
||||
<br/>
|
||||
where set_input_file, from class <eiffel>INPUT</eiffel>, has a self-explanatory effect.
|
||||
|
||||
Finally, step [[#step_e4|4]] (processing the document) is simply a call to procedure process, obtained from [[ref:/libraries/parse/reference/construct_chart|CONSTRUCT]] . Recall that this procedure simply executes <br/>
|
||||
Finally, step [[#step_e4|4]] (processing the document) is simply a call to procedure process, obtained from [[ref:libraries/parse/reference/construct_chart|CONSTRUCT]] . Recall that this procedure simply executes <br/>
|
||||
<code>
|
||||
parse
|
||||
if parsed then
|
||||
|
||||
@@ -42,7 +42,7 @@ The information the server sends back may be confidential. Follow these steps to
|
||||
|
||||
===Complex Headers===
|
||||
|
||||
The Eiffel-Web application has the possibility to send a selection of different HTTP headers. They can be found in class <eiffel>CGI_RESPONSE_HEADER</eiffel>. In particular, it is advised to generate a status for each request, the value of the most common ones may be found in class [[ref:/libraries/web/reference/cgi_common_status_types_chart|CGI_COMMON_STATUS_TYPES]] .
|
||||
The Eiffel-Web application has the possibility to send a selection of different HTTP headers. They can be found in class <eiffel>CGI_RESPONSE_HEADER</eiffel>. In particular, it is advised to generate a status for each request, the value of the most common ones may be found in class [[ref:libraries/web/reference/cgi_common_status_types_chart|CGI_COMMON_STATUS_TYPES]] .
|
||||
|
||||
===Debugging facilities===
|
||||
|
||||
|
||||
Reference in New Issue
Block a user