Author:halw

Date:2008-10-06T18:21:47.000000Z


git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@70 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
halw
2008-10-06 18:21:47 +00:00
parent 6af5a29e65
commit 74a519a844
10 changed files with 130 additions and 100 deletions

View File

@@ -2,8 +2,6 @@
[[Property:link_title|Overview and Prerequisites]]
[[Property:weight|-15]]
[[Property:uuid|acf5433b-14e9-1d21-c8cf-997db7821550]]
[[Help reading the EiffelStudio Guided Tour|Help reading this manual]]
EiffelStudio is the central tool of Eiffel Software's implementation of Eiffel, letting you design, develop, debug, document, measure, maintain, revise and expand systems using the full power of object technology and Design by Contract <span>TM</span>.
This presentation introduces the essential properties of EiffelStudio. It will take you through a tour of the environment, using a pre-existing example system.

View File

@@ -2,18 +2,5 @@
[[Property:link_title|Release Notes]]
[[Property:weight|-15]]
[[Property:uuid|f4dc1f42-8285-ab1a-7c9e-becf6553fcc0]]
* [[Release notes for EiffelStudio 6.2|EiffelStudio 6.2]]
* [[Release notes for EiffelStudio 6.1|EiffelStudio 6.1]]
* [[Release notes for EiffelStudio 6.0|EiffelStudio 6.0]]
* [[Release notes for EiffelStudio 5.7|EiffelStudio 5.7]]
* [[Release notes for EiffelStudio 5.6|EiffelStudio 5.6]]
* [[Release notes for EiffelStudio 5.5|EiffelStudio 5.5]]
* [[Release notes for EiffelStudio 5.4|EiffelStudio 5.4]]
* [[Release notes for EiffelStudio 5.3|EiffelStudio 5.3]]
* [[Release notes for EiffelStudio 5.2|EiffelStudio 5.2]]
* [[Release notes for EiffelStudio 5.1|EiffelStudio 5.1]]
* [[Release notes for EiffelStudio 5.0|EiffelStudio 5.0]]

View File

@@ -27,7 +27,7 @@ Name: smith
Password: mypass
</code>
{{note|Name'' and ''Password'' are no required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit '''Return''' when prompted ''.'' }}
{{note|''Name'' and ''Password'' are not required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit ''Return'' when prompted. }}
* For Oracle:
<code>
@@ -36,7 +36,7 @@ Name: smith@HANDSON
Password: mypass
</code>
{{note|you have to specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
{{note|You must specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
Then you can enter standard SQL queries to interact with your database, for instance:
@@ -46,7 +46,7 @@ John Smith
SQL>
</code>
{{note|enter ''exit'' to quit the application. }}
{{note|Enter ''exit'' to quit the application. }}
==Under the Hood==

View File

@@ -31,7 +31,7 @@ Name: smith
Password: mypass
</code>
{{note|Name'' and ''Password'' are no required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit '''Return''' when prompted ''.'' }}
{{note|''Name'' and ''Password'' are not required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit '''Return''' when prompted ''.'' }}
* For Oracle:
<code>
@@ -42,7 +42,7 @@ Name: smith@HANDSON
Password: mypass
</code>
{{note|you have to specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
{{note|You must specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
Then you can insert a book in the database, for instance:
@@ -64,7 +64,7 @@ Double value? 12.675
Object inserted
</code>
{{note|if your database does not contain a <eiffel>DB_BOOK</eiffel> table, this example will create it. }}
{{note|If your database does not contain a <eiffel>DB_BOOK</eiffel> table, this example will create it. }}
==Under the Hood==

View File

@@ -27,7 +27,7 @@ With ODBC:
''ln data.sql.odbc data.sql''
{{warning| '''Caution:''' the ''data.sql'' file must be available in the sample application current directory. If you run the sample from EiffelStudio, this directory should be the ''EIFGENs/target/W_CODE/'' directory of your project (where target is one of the installed DBMS). }}
{{caution|The ''data.sql'' file must be available in the sample application current directory. If you run the sample from EiffelStudio, this directory should be the ''EIFGENs/target/W_CODE/'' directory of your project (where target is one of the installed DBMS). }}
This sample lets you interact with your database through a console.
@@ -40,7 +40,7 @@ Name: smith
Password: mypass
</code>
{{note|Name'' and ''Password'' are no required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit '''Return''' when prompted. }}
{{note|''Name'' and ''Password'' are not required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit ''Return'' when prompted. }}
* For Oracle:
<code>
@@ -49,7 +49,7 @@ Name: smith@HANDSON
Password: mypass
</code>
{{note|you have to specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
{{note|You must specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
Then you can select rows from this table with author's name, for instance:
@@ -77,7 +77,7 @@ First publication:07/01/1992 12:00:00.0 AM
Author? ('exit' to terminate):
</code>
{{note|enter ''exit'' to quit the application. }}
{{note|Enter ''exit'' to quit the application. }}
==Under the Hood==

View File

@@ -2,7 +2,7 @@
[[Property:link_title|EiffelPreferences Tutorial]]
[[Property:weight|0]]
[[Property:uuid|0c717db7-fb53-80b3-e32f-cc8356afa5f8]]
The preference library is a platform independent library that can be used to add preference and configuration settings to your application. Briefly, the library provides support for creating fully configurable preference values, on per application or per user basis. It also provides a graphical interface for manipulation of these values, and a easily extendible design for you to add your own custom preference types.
The preference library is a platform independent library that can be used to add preference and configuration settings to your application. Briefly, the library provides support for creating fully configurable preference values, on a per application or per user basis. It also provides a graphical interface for manipulation of these values, and a easily extendible design for you to add your own custom preference types.

View File

@@ -10,7 +10,10 @@ 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.
[[Image:figure1]]
[[Image:figure1]]
Figure 1: Lexical classes
==AIMS AND SCOPE OF THE LEX LIBRARY==
@@ -36,7 +39,9 @@ For the user of the Lex libraries, the classes of most direct interest are [[ref
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:
<code> analyzer.get_token</code>
<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.
@@ -108,7 +113,7 @@ Token_type_2 Regular_expression_2
Token_type_m Regular_expression_m
'''-- Keywords'''
-- Keywords
Keyword_1
Keyword_2
@@ -151,15 +156,21 @@ Let us look more precisely at how we can use a lexical analyzer to analyze an in
Procedure analyze 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 analyzer.
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 analyzer, although it does not need to be the attribute from [[ref:/libraries/lex/reference/scanning_chart|SCANNING]] . You can apply to that analyzer the various exported features features of class [[ref:/libraries/lex/reference/lexical_chart|LEXICAL]] , explained below. All the calls described below should use analyzer as their target, as in
<code> analyzer.set_file ("my_file_name")</code>
<code>
analyzer.set_file ("my_file_name")
</code>
===Creating, retrieving and storing an analyzer===
To create a new analyzer, use
<code> create analyzer.make_new</code>
<code>
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
<code> analyzer ?= retrieved</code>
<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 make of [[ref:libraries/lex/reference/lexical_chart|LEXICAL]] , not to be confused with make_new above:
<code>
@@ -215,7 +226,9 @@ The Lex library supports a powerful set of construction mechanisms for describin
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/>
<code> '0'..'9'</code>
<code>
'0'..'9'
</code>
<br/>
denotes a set of ten tokens, each consisting of a single digit.
@@ -265,7 +278,7 @@ A parenthesized expression, written ( ''exp'') where ''exp'' is a regular expres
A difference, written ''interval - char'', where ''interval'' is an interval expression and ''char'' is a character expression, describes the set of tokens which are in ''exp'' but not in ''char''. For example, the difference '''0'..'9' - '4''' describes all single-decimal-digit tokens except those made of the digit 4.
{{warning| '''Caution''': a difference may only apply to an interval and a single character. }}
{{caution|A difference may only apply to an interval and a single character. }}
===Iterations===
@@ -303,7 +316,7 @@ The following non-elementary forms are abbreviations for commonly needed regular
| Role
|-
| '''$L'''
| '''\n'''
| '' '\n' ''
| New-line character
|-
| '''$N'''
@@ -311,15 +324,15 @@ The following non-elementary forms are abbreviations for commonly needed regular
| Natural integer constants
|-
| '''$R'''
| ''['+'|'-'] +('0'..'9') '.' *('0'..'9')['e'|'E' ['+'|'-'] +('0'..'9')]''
| '' <nowiki>['+'|'-'] +('0'..'9') '.' *('0'..'9')['e'|'E' ['+'|'-'] +('0'..'9')]</nowiki> ''
| Floating point constants
|-
| '''$W'''
| +( '''$P''' - ' ' - '\t' - '\n' - '\r')
| '' +( '''$P''' - ' ' - '\t' - '\n' - '\r') ''
| Words
|-
| '''$Z'''
| ''['+'|'-'] +('0'..'9')''
| '' <nowiki>['+'|'-'] +('0'..'9')</nowiki> ''
| Possibly signed integer constants
|}
@@ -331,7 +344,7 @@ One more form of regular expression, case-sensitive expressions, using the ~ sym
You may freely combine the various construction mechanisms to describe complex regular expressions. Below are a few examples.
{| border="1"
|-
| '''a'..'z' - 'c' - 'e'''
| '' 'a'..'z' - 'c' - 'e' ''
| Single-lower-case-letter tokens, except ''c'' and ''e''.
|-
| ''$? - '\007'''
@@ -340,7 +353,7 @@ You may freely combine the various construction mechanisms to describe complex r
| ''+('a'..'z')''
| One or more lower-case letters.
|-
| ''['+'|'-'] '1'..'9' *('0'..'9')''
| '' <nowiki>['+'|'-'] '1'..'9' *('0'..'9')</nowiki> ''
| Integer constants, optional sign, no leading zero.
|-
| ''->"*/"''
@@ -353,8 +366,8 @@ You may freely combine the various construction mechanisms to describe complex r
===Dealing with keywords===
Many languages to be analyzed have keywords - or, more generally, "reserved words". Eiffel, for example, has reserved words such as <code> class </code> and <code> Result </code>.
{{note|in Eiffel terminology reserved words include keywords; a keyword is a marker playing a purely syntactical role, such as <code> class </code>. Predefined entities and expressions such as <code> Result </code> and <code> Current </code>, which have an associated value, are considered reserved words but not keywords. The present discussion uses the term "keyword" although it can be applied to all reserved words. }}
Many languages to be analyzed have keywords - or, more generally, "reserved words". Eiffel, for example, has reserved words such as <code>class</code> and <code>Result</code>.
{{note|in Eiffel terminology reserved words include keywords; a keyword is a marker playing a purely syntactical role, such as <code>class</code>. Predefined entities and expressions such as <code>Result</code> and <code>Current</code>, which have an associated value, are considered reserved words but not keywords. The present discussion uses the term "keyword" although it can be applied to all reserved words. }}
In principle, keywords could be handled just as other token types. In Eiffel, for example, one might treat each reserved words as a token type with only one specimen; these token types would have names such as Class or Then and would be defined in the lexical grammar file:
@@ -372,21 +385,20 @@ For example the final part of the example Eiffel lexical grammar file appears as
<code>
... Other token type definitions ...
Identifier ~('a'..'z') *(~('a'..'z') | '_' | ('0'..'9'))
'''
-- Keywords
alias
all
and
as
'''
BIT
BOOLEAN
... Other reserved words ...
</code>
{{warning| '''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. }}
{{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===
@@ -397,18 +409,26 @@ The regular expression syntax introduced above offers a special notation to spec
You may change this default behavior through a set of procedures introduced in class [[ref:libraries/lex/reference/lex_builder_chart|LEX_BUILDER]] and hence available in its descendants [[ref:libraries/lex/reference/metalex_chart|METALEX ]] and [[ref:libraries/lex/reference/scanning_chart|SCANNING]] .
To make subsequent regular expressions case-sensitive, call the procedure
<code> distinguish_case</code>
<code>
distinguish_case
</code>
To revert to the default mode where case is not significant, call the procedure
<code> ignore_case</code>
<code>
ignore_case
</code>
Each of these procedures remains in effect until the other one is called, so that you only need one call to define the desired behavior.
For keywords, the policy is less tolerant. A single rule is applied to the entire grammar: keywords are either all case-sensitive or all case-insensitive. To make all keywords case-sensitive, call
<code> keywords_distinguish_case</code>
<code>
keywords_distinguish_case
</code>
The inverse call, corresponding to the default rule, is
<code> keywords_ignore_case</code>
<code>
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.
@@ -431,6 +451,8 @@ The following extract from a typical descendant of [[ref:/libraries/lex/referenc
put_expression("+('0'..'7'"), Octal_constant, "Octal")
put_expression ("'a'..'z' *('a'..'z'|'0'..'9'|'_')", Lower_identifier, "Lower")
put_expression ("'A'..'Z' *('A'..'Z'|'0'..'9'|'_' )", Upper_identifier, "Upper")
dollar_w (Word)
...
put_keyword ("begin", Lower_identifier)
@@ -447,9 +469,11 @@ This example follows the general scheme of building a lexical analyzer with the
# "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
<code> read_grammar (grammar_file_name: STRING)</code>
<code>
read_grammar (grammar_file_name: STRING)
</code>
In this case all the expressions and keywords are taken from the file of name <code> grammar_file_name </code> rather than passed explicitly as arguments to the procedures of the class. You do not need to call make_analyzer, since read_grammar includes such a call.
In this case all the expressions and keywords are taken from the file of name <code>grammar_file_name</code> rather than passed explicitly as arguments to the procedures of the class. You do not need to call make_analyzer, since read_grammar includes such a call.
The rest of this discussion assumes that the four steps are executed individually as shown above, rather than as a whole using read_grammar.
===Recording token types and regular expressions===
@@ -459,12 +483,16 @@ As shown by the example, each token type, defined by a regular expression, must
Procedure put_expression records a regular expression. The first argument is the expression itself, given as a string built according to the rules seen earlier in this chapter. The second argument is the integer code for the expression. The third argument is a string which gives a name identifying the expression. This is useful mostly for debugging purposes; there is also a procedure put_nameless_expression which does not have this argument and is otherwise identical to put_expression.
Procedure dollar_w corresponds to the '''$W''' syntax for regular expressions. Here an equivalent call would have been
<code> put_nameless_expression ( "$W" ,Word ) </code>
<code>
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.
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> make_analyzer</code>
<code>
make_analyzer
</code>
After that call, you may not record any new regular expression or keyword. The analyzer is usable through attribute analyzer.
{{note|for readers knowledgeable in the theory of lexical analysis: one of the most important effects of the call to make_analyzer is to transform the non-deterministic finite automaton resulting from calls such as the ones above into a deterministic finite automaton. }}
@@ -474,6 +502,8 @@ Another important feature of class [[ref:/libraries/lex/reference/metalex_chart|
==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.
===Building a lexical analyzer===

View File

@@ -12,7 +12,9 @@ This chapter describes the Parse library, which you can use to process documents
Because it concentrates on the higher-level structure, the Parse library requires auxiliary mechanisms for identifying a document's lexical components: words, numbers and other such elementary units. To address this need it is recommended, although not required, to complement Parse with the Lex library studied in the previous chapter.
Figure 1 shows the inheritance structure of the classes discussed in this chapter.
[[Image:figure1]]
[[Image:figure1]]
Figure 1: Parse class structure
==WHY USE THE PARSE LIBRARY==
@@ -53,7 +55,7 @@ Parsing is seldom an end in itself; rather, it serves as an intermediate step fo
Parsing takes care of one of the basic tasks of a document processor: reconstructing the logical organization of a document, which must conform to a certain '''syntax''' (or structure), defined by a '''grammar'''.
{{note|the more complete name '''syntactic grammar''' avoids any confusion with the ''lexical'' grammars discussed in the [[EiffelLex Tutorial]]. By default, "grammar" with no further qualification will always denote a syntactic grammar. A syntactic grammar normally relies on a lexical grammar, which gives the form of the most elementary components - the tokens - appearing in the syntactic structure. }}
{{note|The more complete name '''syntactic grammar''' avoids any confusion with the ''lexical'' grammars discussed in the [[EiffelLex Tutorial]]. By default, "grammar" with no further qualification will always denote a syntactic grammar. A syntactic grammar normally relies on a lexical grammar, which gives the form of the most elementary components - the tokens - appearing in the syntactic structure. }}
Once parsing has reconstructed the structure of a document, the document processor will perform various operations on the basis of that structure. For example a compiler will generate target code corresponding to the original text; a command language interpreter will execute the operations requested in the commands; and a documentation tool such as the short and flat-short commands for Eiffel will produce some information on the parsed document. Such operations are called '''semantic actions'''. One of the principal requirements on a good parsing mechanism is that it should make it easy to graft semantics onto syntax, by adding semantic actions of many possible kinds to the grammar.
@@ -105,19 +107,25 @@ The rest of this section concentrates on the parsing-specific part: non-terminal
===Varieties of non-terminal constructs and productions===
An aggregate production defines a construct whose specimens are obtained by concatenating ("aggregating") specimens of a list of specified constructs, some of which may be optional. For example, the production for construct Conditional in an Eiffel grammar may read:
<code>Conditional [=] if Then_part_list [Else_part] end</code>
<code>
Conditional [=] if Then_part_list [Else_part] end
</code>
This means that a specimen of Conditional (a conditional instruction) is made of the keyword <code> if </code>, followed by a specimen of Then_part_list, followed by zero or one specimen of Else_part (the square brackets represent an optional component), followed by the keyword <code> end </code>.
This means that a specimen of Conditional (a conditional instruction) is made of the keyword <code>if</code>, followed by a specimen of Then_part_list, followed by zero or one specimen of Else_part (the square brackets represent an optional component), followed by the keyword <code>end</code>.
{{note|this notation for productions uses conventions similar to those of the book Eiffel: The Language. Keywords are written in '''boldface italics''' and stand for themselves. Special symbols, such as the semicolon, are written in double quotes, as in ";". The [=] symbol means "is defined as" and is more accurate mathematically than plain =, which, however, is often used for this purpose (see "Introduction to the Theory of Programming Languages", Prentice Hall, 1991, for a more complete discussion of this issue). }}
{{note|This notation for productions uses conventions similar to those of the book Eiffel: The Language. Keywords are written in '''boldface italics''' and stand for themselves. Special symbols, such as the semicolon, are written in double quotes, as in ";". The <nowiki>[=]</nowiki> symbol means "is defined as" and is more accurate mathematically than plain <nowiki>=</nowiki>, which, however, is often used for this purpose (see "Introduction to the Theory of Programming Languages", Prentice Hall, 1991, for a more complete discussion of this issue). }}
A choice production defines a construct whose specimens are specimens of one among a number of specified constructs. For example, the production for construct Type in an Eiffel grammar may read:
<code>Type [=] Class_type | Class_type_expanded | Formal_generic_name | Anchored | Bit_type</code>
<code>
Type [=] Class_type | Class_type_expanded | Formal_generic_name | Anchored | Bit_type
</code>
This means that a specimen of Type is either a specimen of Class_type, or a specimen of Class_type_expanded etc.
Finally, a repetition production defines a construct whose specimens are sequences of zero or more specimens of a given construct (called the '''base''' of the repetition construct), separated from each other by a '''separator'''. For example, the production for construct Compound in an Eiffel grammar may read
<code>Compound [=] {Instruction ";" ...}</code>
<code>
Compound [=] {Instruction ";" ...}
</code>
This means that a specimen of Compound is made of zero or more specimens of Instruction, each separated from the next (if any) by a semicolon.
@@ -133,13 +141,13 @@ The beginning of the line, separated from the rest by a colon, is the list of va
Using the conventions defined above, the grammar may be written as:
<code>
Line [=] Variables ":" Sum
Line [=] Variables ":" Sum
Variables [=] {Identifier ";" ...}
Sum [=] {Diff "+" ...}
Diff [=] {Product "-" ...}
Product [=] {Term " * " ...}
Term [=] Simple_var Int_constant Nested
Nested [=] "(" Sum ")"
Sum [=] {Diff "+" ...}
Diff [=] {Product "-" ...}
Product [=] {Term " * " ...}
Term [=] Simple_var Int_constant Nested
Nested [=] "(" Sum ")"
</code>
This grammar assumes a terminal Identifier, which must be defined as a token type in the lexical grammar. The other terminals are keywords, shown as strings appearing in double quotes, for example "+".
@@ -253,7 +261,7 @@ For any keyword of associated string ''symbol'', such as the colon ":" in the ex
keyword (symbol)
</code>
The order of the various calls to put (for non-keywords) and keyword (for keywords) must be the order of the components in the production. Also, every <code> create </code> <code> component </code> <code> . </code>make instruction must occur before the corresponding call to put <code> ( </code> <code> symbol </code> <code> ) </code>.
The order of the various calls to put (for non-keywords) and keyword (for keywords) must be the order of the components in the production. Also, every <code>create</code> <code>component</code> <code>. </code>make instruction must occur before the corresponding call to put <code> ( </code> <code>symbol</code> <code> ) </code>.
All components in the above example are required. In the general case an aggregate production may have optional components. To signal that a component component of the right-hand side is optional, include a call of the form
<code>
@@ -272,7 +280,9 @@ This call may appear anywhere after the corresponding <code> create </code> <cod
The production function for a descendant of <eiffel>CHOICE</eiffel> will describe how to build a specimen of the corresponding function as a specimen of one of the alternative constructs.
As an example, consider the production function of class <eiffel>TERM</eiffel> for the Polynomial example language. The corresponding production is
<code>Term [=] Simple_var Poly_integer Nested</code>
<code>
Term [=] Simple_var Poly_integer Nested
</code>
<br/>
where Simple_var, Poly_integer and Nested are other constructs. This means that every specimen of Term consists of one specimen of any one of these three constructs. Here is the corresponding production function as it appears in class <eiffel>TERM</eiffel>:
<code>
@@ -293,7 +303,7 @@ where Simple_var, Poly_integer and Nested are other constructs. This means that
end
</code>
As shown by this example, the production function for a choice construct class must declare a local entity - here <code> id </code>, <code> val </code> and <code> nest </code> - for each alternative component of the right-hand side. The type of each entity is the corresponding construct class - here <eiffel>SIMPLE_VAR</eiffel>, <eiffel>POLY_INTEGER</eiffel> and <eiffel>NESTED</eiffel>.
As shown by this example, the production function for a choice construct class must declare a local entity - here <code>id</code>, <code>val</code> and <code>nest</code> - for each alternative component of the right-hand side. The type of each entity is the corresponding construct class - here <eiffel>SIMPLE_VAR</eiffel>, <eiffel>POLY_INTEGER</eiffel> and <eiffel>NESTED</eiffel>.
The body of the function must begin by
<code>
@@ -301,20 +311,22 @@ The body of the function must begin by
Result.forth
</code>
Then for each alternative component represented by a local entity component (in the example this applies to <code> id </code>, <code> val </code> and <code> nest </code>) there should be two instructions of the form
Then for each alternative component represented by a local entity component (in the example this applies to <code>id</code>, <code>val</code> and <code>nest</code>) there should be two instructions of the form
<code>
create component.make
put (component)
</code>
{{note| '''Caution''': the order of the various calls to put is irrelevant in principle. When a document is parsed, however, the choices will be tried in the order given; so if you know that certain choices occur more frequently than others it is preferable to list them first to speed up the parsing process. }}
{{caution|The order of the various calls to put is irrelevant in principle. When a document is parsed, however, the choices will be tried in the order given; so if you know that certain choices occur more frequently than others it is preferable to list them first to speed up the parsing process. }}
===Repetitions===
The production 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 separator 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>Variables [=] {Identifier ";" ...}</code>
<code>
Variables [=] {Identifier ";" ...}
</code>
<br/>
where Identifier is another construct, and the semicolon ";" is a terminal. This means that every specimen of Variables consists of zero or more specimens of Identifier, separated from each other (if more than one) by semicolons.
@@ -469,11 +481,11 @@ For <eiffel>TERMINAL</eiffel>, only one semantic action makes sense. To avoid an
Often, the semantic procedures need to compute various elements of information. These may be recorded using appropriate attributes of the corresponding construct classes.
{{note|readers familiar with the theory of parsing and compiling will see that this scheme, using the attributes of Eiffel classes, provides a direct implementation of the "attribute grammar" mechanism. }}
{{note|Readers familiar with the theory of parsing and compiling will see that this scheme, using the attributes of Eiffel classes, provides a direct implementation of the "attribute grammar" mechanism. }}
===Polynomial semantics===
As an example let us examine the semantics of the Product construct for the polynomial language. It is a repetition construct, with Term as the base construct; in other words a specimen of Product is a sequence of one or more terms, representing the product term <code>1</code> * term <code>2</code> ... * term <code>n</code>. Here is the post_action procedure in the corresponding class <eiffel>PRODUCT</eiffel>:
As an example let us examine the semantics of the Product construct for the polynomial language. It is a repetition construct, with Term as the base construct; in other words a specimen of Product is a sequence of one or more terms, representing the product term<code>1</code> * term<code>2</code> ... * term<code>n</code>. Here is the post_action procedure in the corresponding class <eiffel>PRODUCT</eiffel>:
<code>
post_action is
local
@@ -499,7 +511,7 @@ As an example let us examine the semantics of the Product construct for the poly
Here each relevant construct class has an attribute info used to record the semantic information associated with polynomials and their components, such as child_value, an <eiffel>INTEGER</eiffel>. The post_action takes care of computing the product of all child_values for the children. First, of course, post_action must recursively be applied to each child, to compute its own child_value.
{{note|recall that an instance of <eiffel>CONSTRUCT</eiffel> is also a node of the abstract syntax tree, so that all the <eiffel>TWO_WAY_TREE</eiffel> features such as child_value, child_start, child_after and many others are automatically available to access the syntactical structure. }}
{{note|Recall that an instance of <eiffel>CONSTRUCT</eiffel> is also a node of the abstract syntax tree, so that all the <eiffel>TWO_WAY_TREE</eiffel> features such as child_value, child_start, child_after and many others are automatically available to access the syntactical structure. }}
===Keeping syntax and semantics separate===
@@ -533,10 +545,13 @@ If a choice is attempted and fails (because it encounters input that does not co
===Left recursion===
Recursive descent implies the danger of infinite looping when parsing is attempted for left-recursive productions of the form <br/>
<code>A [=] A ...</code>
<code>
A [=] A ...
</code>
<br/>
or, more generally, cases in which the left recursion is indirect, as in <br/>
<code> A [=] B ...
<code>
A [=] B ...
B [=] C ...
...
L [=] A ...
@@ -554,12 +569,8 @@ Another potential problem may arise from too much backtracking. In contrast with
Two techniques are available to minimize backtracking. One, mentioned above, is to organize the production functions for choice construct classes so that they list the most frequent cases first. The other is to use the commit procedure in the production functions for aggregate constructs.
A call to commit in an aggregate A is a hint to the parser, which means:
<code>"If you get to this point in trying to recognize a specimen of A
as one among several possible choices for a choice construct C,
and you later fail to obtain an A, then forget about other choices
for C: you won't be able to find a C here. You may go back to the
next higher-level choice before C - or admit failure if there is
no such choice left." </code>
:''If you get to this point in trying to recognize a specimen of A as one among several possible choices for a choice construct C, and you later fail to obtain an A, then forget about other choices for C: you won't be able to find a C here. You may go back to the next higher-level choice before C - or admit failure if there is no such choice left.''
Such a hint is useful when you want to let the parser benefit from some higher-level knowledge about the grammar, which is not directly deducible from the way the productions have been written.
@@ -583,15 +594,13 @@ where ''s'' is a specimen of <eiffel>SUM</eiffel>, is written as
</code>
The commit after the recognition of the keyword "(" is there to use the following piece of higher-level knowledge:
<code>No choice production of the grammar that has NESTED
:''No choice production of the grammar that has NESTED as one of its alternatives has another alternative construct whose specimens could begin with an opening parenthesis "(".''
as one of its alternatives has another alternative construct whose
specimens could begin with an opening parenthesis "(".</code>
Because of this property, if the parser goes so far as to recognize an opening parenthesis as part of parsing any construct <eiffel>C</eiffel> for which NESTED is an alternative, but further tokens do not match the structure of <eiffel>NESTED</eiffel> specimens, then we will have failed to recognize not only a <eiffel>NESTED</eiffel> but also a <eiffel>C</eiffel>.
{{note|some readers will have recognized commit as being close to the Prolog "cut" mechanism. }}
{{note|Some readers will have recognized commit as being close to the Prolog "cut" mechanism. }}
In this example, <eiffel>NESTED</eiffel> is used in only one right-hand side production: the choice production for TERM, for which the other alternatives are <eiffel>SIMPLE_VAR</eiffel> and <eiffel>POLY_INTEGER</eiffel>, none of whose specimens can include an opening parenthesis.
@@ -605,13 +614,13 @@ We are ready now to put together the various elements required to build a docume
The documents to be processed will be specimens of a certain construct. This construct is called the '''top construct''' for that particular processing.
{{warning| '''Caution''': be sure to note that with the Parse library there is no room for a concept of top construct of a '''grammar''': the top construct is only defined with respect to a particular processor for that grammar. <br/>
{{caution|Be sure to note that with the Parse library there is no room for a concept of top construct of a '''grammar''': the top construct is only defined with respect to a particular processor for that grammar. <br/>
Attempting to define the top of a grammar would be contrary to the object-oriented approach, which de-emphasizes any notion of top component of a system. <br/>
Different processors for the same grammar may use different top constructs. }}
A document processor will be a particular system made of construct classes, complemented by semantic classes, and usually by other auxiliary classes. One of the construct classes corresponds to the top construct and is called the '''top construct class'''.
{{note|this notion of top construct class has a natural connection to the notion of root class of a system, as needed to get executable software. The top construct class could indeed be used as root of the processor system. In line with the previous discussion, however, it appears preferable to keep the top construct class (which only depends on the syntax and remains independent of any particular processor) separate from the system's root class. With this approach the root class will often be a descendant of the top construct class. <br/>
{{note|This notion of top construct class has a natural connection to the notion of root class of a system, as needed to get executable software. The top construct class could indeed be used as root of the processor system. In line with the previous discussion, however, it appears preferable to keep the top construct class (which only depends on the syntax and remains independent of any particular processor) separate from the system's root class. With this approach the root class will often be a descendant of the top construct class. <br/>
This policy was adopted for the Polynomial language example as it appears in the delivery: the processor defined for this example uses <eiffel>LINE</eiffel> as the top construct class; the root of the processor system is a class <eiffel>PROCESS</eiffel>, which inherits from <eiffel>LINE</eiffel>. }}
===Steps in the execution of a document processor===
@@ -707,9 +716,9 @@ Many languages include an expression construct having the properties of traditio
It is of course possible to apply the Parse library in its current state to support expressions, as illustrated by this extract from the Polynomial grammar given in full above:
<code>
Variables [=] {Identifier ";" ...}
Sum [=] {Diff "+" ...}
Diff [=] {Product "-" ...}
Product [=] {Term "*" ...}
Sum [=] {Diff "+" ...}
Diff [=] {Product "-" ...}
Product [=] {Term "*" ...}
</code>
The problem then is not expressiveness but efficiency. For such expressions the recursive descent technique, however well adapted to the higher-level structures of a language, takes too much time and generates too many tree nodes. Efficient bottom-up parsing techniques are available for this case.
@@ -721,7 +730,9 @@ Beyond the addition of an <eiffel>EXPRESSION</eiffel> class, some changes in the
===Yooc===
To describe the syntax of a language, it is convenient to use a textual format such as the one that has served in this chapter to illustrate the various forms of production. The correspondence between such a format and the construct classes is straightforward; for example, as explained above, the production <br/>
<code>Line [=] Variables ":" Sum</code>
<code>
Line [=] Variables ":" Sum
</code>
<br/>
will yield the class
<code>

View File

@@ -2,7 +2,9 @@
[[Property:weight|0]]
[[Property:uuid|63f0e737-4ad7-c574-3bbc-05e005815785]]
In the directory '''$ISE_EIFFEL/examples/parse''' you will find a system that implements a processor for a grammar describing a simple language for expressin polynomials. A typical document in this language is the line
<code>x;y: x * (y + 8 - (2 * x))</code>
<code>
x;y: x * (y + 8 - (2 * x))
</code>
The beginning of the line, separated from the rest by a colon, is the list of variables used in the polynomial, separated by semicolons. The rest of the line is the expression defining the polynomial. The grammar can be described with the following grammar:
<code>
LINE = VARIABLES ":" SUM

View File

@@ -3,7 +3,10 @@
[[Property:uuid|da8f72cb-0ecd-464a-a558-cbf7d24301e3]]
This sample shows how to retrieve and display information from a basic form on a web page.
{{note|This sample requires a web server supporting CGI in order to be run. Both the Internet Information Services web server from Microsoft and the GNU Apache server may be used.
{{note|This sample requires a web server supporting CGI in order to be run. Both the Internet Information Services web server from Microsoft and the GNU Apache server may be used. }}
==Compiling==
To compile the example:
@@ -20,7 +23,7 @@ You should copy the file ''web_demo.exe'' in the ''cgi_bin'' directory of your w
==Running==
To run the example, access the page ''sample.html'' that you copied on the web server with a web browser (typically '' http://localhost/sample.html''). Fill in the text field with a username and click ''Submit''. You should see a page displaying the name you just entered. Although not earth-shattering, this sample shows the basis for building more complex forms processing in Eiffel.
To run the example, access the page ''sample.html'' that you copied on the web server with a web browser (typically <nowiki>''http://localhost/sample.html''</nowiki>). Fill in the text field with a username and click ''Submit''. You should see a page displaying the name you just entered. Although not earth-shattering, this sample shows the basis for building more complex forms processing in Eiffel.
==Under the Hood==
@@ -28,9 +31,8 @@ This basic sample has just one class <eiffel>SAMPLE</eiffel> which inherits from
See the reference for the class interfaces.
}}
See the EiffelWeb class reference for the class interfaces.