previous next contents
ExampleSkipExcl =
{ ('%%' | any); !c#1; }
-> SOURCETEXT.
ExampleSkipIncl =
c:= 2;
{!c#1; ('%%' | any) }
-> SOURCETEXT.
ExampleSkipExcl
stops in front of the keyword, ExampleSkipIncl
skips
the keyword, too.ExampleSkipExcl =
{ ('REPEAT' $ | ident | any); !c#1; }
-> SOURCETEXT.
Otherwards it would be possible that the parser stops already on something like NOREPEAT.
A call to Skip
in front of large alternative may also speed up the parser if it is likely
to have to skip many characters at this point.
Skip()
before entering the respective rule.
idcp = ident -> SOURCETEXT.
withhd = idcp -> idcp_.
withouthd = Skip(); idcp -> idcp_.
Then withhd
will translate " alfa
" into
" alfa
",
while withouthd
produces just "alfa
".
IMPORTS Dp4Streams, Dp4Chars, Dp4DocFiles;
ExampleTwoPasses =
ExampleFirstPass;
(* write 1st target of ExampleFirstPass on file: *)
Dp4Streams.Tar2Strm(ExampleFirstPass_, Dp4DocFiles.New("Temp1File"));
(* make this file the source for further processing: *)
From(Dp4DocFiles.IFile("Temp1File"));
ExampleSecndPass;
-> ExampleSecndPass_.
ExampleFirstPass = ident -> ident_ '1st'.
ExampleSecndPass = ident -> '2nd Pass:' ident_.
ident4root
.
Test your productions by putting their name in front of the source.TestRoot=
GLOBVAR DCL globvar1, globvar2,....; (* declarations *)
globvar1:= ... (* initializations - if needed *)
ident4root (* calls the wanted production *)
-> ident4root_ . (* gives the result *)
Lets say, you want to test your rule MyExpr
, then select TestRoot
as root and write as source
MyExpr a+(B*Pi)/128
and the result will be quite similar to selecting MyExpr
as root in a simple grammar
without global variables.
Instead of
one should better use
('keyword1' $ ... |'keyword2' $ ... |'keyword3' $... )
This avoids touching the source repeatedly. ident
(!ident_0='keyword1'...|!ident_0='keyword2'...|!ident_0='keyword3'...)
(Do not expect too much. More often than not this tuning will not result in sensible speed-ups. If there is
really a big number of keywords, i.e. >20...40, and the selection is touched really frequently, one should
think about using an imported hash table. Thus, replace the second line by
(/My.hash(Ident_0)/ ...|...|...)
)
One can achieve a nominal speed-up by placing a Skip()
in front of alternatives.
But be careful, this may interact with suppression of skipping (<...>
constructs).
line
terminal.
makeComment = { line[i] }
-> {'// ' line_[i] }.
This rule describes a translation which converts any text in a C++ comment format.
END(*LOOP*);
"
while another likes "END;(*LOOP*)
".However, with Depot4 there are two ways to tackle this problem:
PascalComment=
('(*'c:= 2; { !c#1;('*)'|any)}
|'{' c:= 2; {!c#1;('}'|any)})
-> SOURCETEXT.
and (one comment may be followed by another)
Comment= {PascalComment[i]} -> {PascalComment_[i]}
To suppress the default comment definition call
DefCom('$-$', '');
.Comment
must be inserted (and handled!) in the grammar at every
point where a comment is allowed. By this, the size of the grammar will easily be doubled - at least.
Skip();
in
front of alternatives, options and before the end of iterations. (Note, that cannot be done in
general because it prevents the correct operation of skipping suppression
<...>.)
The following example code illustrates this approach. You can experience the mentioned problem
by deleting the Skip();
in the last but one line.
ExampleKeepCom=
GLOBVAR USE coms: FLEX OF TXT; USE nrOfComs: INT;
DefCom('[*', '*] '); (* accept nested comments but do not
call ExampleKeepCom recursively *)
{ExampleKeepC1; INC(nrOfComs); coms[nrOfComs]:= ExampleKeepC1_; }
DefCom('$1-:ExampleKeepCom$[*', '*] '); (* re-activate ExampleKeepCom *).
ExampleKeepC1= {('*]' | any)!c#1; } !N>0;
-> '(* ' SOURCETEXT ' *)\n'.
ExampleKeepInsert= (* call this whenever you want to insert cumulated comments *)
GLOBVAR USE coms: FLEX OF TXT; USE nrOfComs: INT;
VAR nr: INT;
nr:= nrOfComs; nrOfComs:= 0;
->
{/..nr/ coms[i] }.
(*-------------------------------- DEMO ---------------------------------------*)
ExampleKeepComDemo= (* --- root of the demo --- *)
GLOBVAR DCL coms: FLEX OF TXT; DCL nrOfComs: INT;
nrOfComs:= 0;
DefCom('$1-:ExampleKeepCom$[*', '*] ');
'(*' { ExampleKeepComDemoElems[i] ExampleKeepInsert[i]}'*)'
-> { ExampleKeepComDemoElems_[i] ExampleKeepInsert_[i]}.
ExampleKeepComDemoElems=
Skip(); (* this is important to avoid multiplied comment texts - try it *)
(//e:id | e:str | e:num) -> e_ ':'.
In general, comments are handled by the second method, but at these fixed points the first one
is applied.
statementWithComment= statement <{' '} Comment>
-> statement_ '--' Comment_ '\n'.
Insert a call to statementWithComment
wherever you expect a comment of
this type.Comment
.)
IMPORTS Dp4StrBuf, Dp4Streams;
KeepCom=
GLOBVAR USE coms: FLEX OF TXT; USE nrOfComs: INT;
VAR bs: Dp4Streams.Stream;
DefCom('(*', '*) '); (* as above *)
KeepC1;
bs:= Dp4StrBuf.New('tmpstr'); (* make input stream *)
Dp4Streams.Tar2Strm(KeepC1_, bs); (* from accepted *)
From(Dp4Streams.StrmSrc(bs)); (* comment text *)
KeepC2 Back(); (* and process it *)
INC(nrOfComs); coms[nrOfComs]:= KeepC2_;
DefCom('$1-:KeepCom$(*', '*) '); (* re-activate KeepCom *).
KeepC1= {('*)' | any)!c#1; } !N>0;
-> SOURCETEXT .
KeepC2= {line[i]} (* prefix each line *)
-> '\n' {'//' line_[i] }.
Remarks:
Dp4StrBuf
any other extension of Dp4Streams
(
Files, Texts etc.) could be used.
(* don't use */ here *)
" ).
Dp4Tools.translate
is possible too.
MODULE ExampleRoot
IMPORTS Dp4Messages;
ExampleRoot= ( ExampleActualRoot (* This will cause an error as it is not implemented *)
| ERROR('exp.general'); )
-> ( ExampleActualRoot_
| 'Sorry, nothing generated'
).
INIT
Dp4Messages.setErrorTxt('exp.general', 'Unspecified error');
Dp4Messages.setErrorTxt('exp.typ', 'Type mismatch');
Dp4Messages.setErrorTxt('exp.unKwn', 'Unknown/undeclared identifier');
END ExampleRoot
Using the above as a translator will produce a log like:
*Loading ExampleActualRoot failed
"" pos 0 error: Unspecified error
OK
previous next contents