From 27f268078040160265a91bcd2389bbf614b084f2 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Thu, 2 Jan 2014 15:26:21 +0100 Subject: [PATCH] Initial commit. --- README.1st | 31 + README.md | 9 + cpp.hlx | 167 +++ ctounix.hlx | 149 +++ examples/cpp.htm | 85 ++ examples/hilex.htm | 116 ++ examples/pascal.htm | 136 +++ examples/prolog.htm | 180 +++ hilex.exe | Bin 0 -> 104224 bytes hilex.hlx | 98 ++ hilex.prj | Bin 0 -> 9419 bytes hlx/cpp.hlx | 167 +++ hlx/ctounix.hlx | 150 +++ hlx/hilex.hlx | 98 ++ hlx/html.hlx | 131 +++ hlx/java.hlx | 190 ++++ hlx/pascal.hlx | 145 +++ hlx/prolog.hlx | 124 ++ html.hlx | 130 +++ java.hlx | 190 ++++ main/main.cpp | 388 +++++++ pascal.hlx | 145 +++ prolog.hlx | 124 ++ source/box.cpp | 125 +++ source/box.h | 86 ++ source/buffer.cpp | 627 +++++++++++ source/buffer.h | 59 + source/cocon.cpp | 360 ++++++ source/cocon.h | 72 ++ source/dynauto.cpp | 2187 ++++++++++++++++++++++++++++++++++++ source/dynauto.h | 151 +++ source/hierrors.h | 10 + source/hililex.cpp | 441 ++++++++ source/hililex.h | 53 + source/hilisem.cpp | 2624 +++++++++++++++++++++++++++++++++++++++++++ source/hilisem.h | 243 ++++ source/hilist.cpp | 282 +++++ source/hilist.h | 56 + source/hilisyn.cpp | 564 ++++++++++ source/hilisyn.h | 81 ++ source/hitypes.h | 176 +++ source/prefix.cpp | 480 ++++++++ source/prefix.h | 33 + source/regtree.cpp | 777 +++++++++++++ source/regtree.h | 102 ++ source/static.cpp | 635 +++++++++++ source/static.h | 118 ++ source/support.cpp | 35 + source/support.h | 11 + source/synode.cpp | 359 ++++++ source/synode.h | 143 +++ toexplor.hlx | 52 + tolite.hlx | 53 + 53 files changed, 13948 insertions(+) create mode 100644 README.1st create mode 100644 cpp.hlx create mode 100644 ctounix.hlx create mode 100644 examples/cpp.htm create mode 100644 examples/hilex.htm create mode 100644 examples/pascal.htm create mode 100644 examples/prolog.htm create mode 100644 hilex.exe create mode 100644 hilex.hlx create mode 100644 hilex.prj create mode 100644 hlx/cpp.hlx create mode 100644 hlx/ctounix.hlx create mode 100644 hlx/hilex.hlx create mode 100644 hlx/html.hlx create mode 100644 hlx/java.hlx create mode 100644 hlx/pascal.hlx create mode 100644 hlx/prolog.hlx create mode 100644 html.hlx create mode 100644 java.hlx create mode 100644 main/main.cpp create mode 100644 pascal.hlx create mode 100644 prolog.hlx create mode 100644 source/box.cpp create mode 100644 source/box.h create mode 100644 source/buffer.cpp create mode 100644 source/buffer.h create mode 100644 source/cocon.cpp create mode 100644 source/cocon.h create mode 100644 source/dynauto.cpp create mode 100644 source/dynauto.h create mode 100644 source/hierrors.h create mode 100644 source/hililex.cpp create mode 100644 source/hililex.h create mode 100644 source/hilisem.cpp create mode 100644 source/hilisem.h create mode 100644 source/hilist.cpp create mode 100644 source/hilist.h create mode 100644 source/hilisyn.cpp create mode 100644 source/hilisyn.h create mode 100644 source/hitypes.h create mode 100644 source/prefix.cpp create mode 100644 source/prefix.h create mode 100644 source/regtree.cpp create mode 100644 source/regtree.h create mode 100644 source/static.cpp create mode 100644 source/static.h create mode 100644 source/support.cpp create mode 100644 source/support.h create mode 100644 source/synode.cpp create mode 100644 source/synode.h create mode 100644 toexplor.hlx create mode 100644 tolite.hlx diff --git a/README.1st b/README.1st new file mode 100644 index 0000000..a4b0012 --- /dev/null +++ b/README.1st @@ -0,0 +1,31 @@ + + +Obsah adresare: + +/DOC + - dokumentace k programu v HTML - ctete prosim jako prvni. + Obsahuje technicke poznamky, uzivatelskou i programatorkou DOC. + +/SOURCE + - zdrojaky + +/MAIN + - main projektu + +hilex.prj + - project file Borland C++ 3.1 + +/HLX + - zaloha HLX souboru + +*.hlx + - HLX soubory ( viz. dokumentace ) + +/EXE + - prelozeny program - NEPOUZIVEJTE ( mel jsem ho pouze na transport ) + + + Martin Dvorak + ultradvorka@post.cz + + diff --git a/README.md b/README.md index 57e38d4..2c57fb0 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,12 @@ hilex ===== Source code syntax highlighting: C/C++/Prolog/... -- HLX --> HTML. + + +DESCRIPTION +=========== + +Hilex is an utility that converts a source code to HTML with syntax highlighting. +Hilex is configured using HLX files that are formed by a set of regular expression +based rules. These rules are used for matching and colorization of source code tokens. + \ No newline at end of file diff --git a/cpp.hlx b/cpp.hlx new file mode 100644 index 0000000..148b2c7 --- /dev/null +++ b/cpp.hlx @@ -0,0 +1,167 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Languague: C++ +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION" ) +{ + Output ="HTML_PAGE"; # HTML_PAGE or NO_ENCAPS or HTML_TABLE + + CRLF ="FALSE"; # add CRs to output ( Unix LF, Dos CRLF ) + HtmlOutput="TRUE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_Font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#FFFF00"; + BaseSize ="+1"; + BgColor ="#000080"; + Width ="555"; # used when HTML_TABLE in other cases is ignored +} + +#--------------------------------------------------------------------------------- + +Element( "KEYWORDS" ) +{ + Descr="(asm)|(auto)|(break)|(case)|(cdecl)|(char)|(class)|(const)|"; + Descr="(continue)|(_cs)|(default)|(delete)|(do)|(double)|(_ds)|(else)|"; + Descr="(enum)|(_es)|(_export)|(extern)|(far)|(float)|(for)|(friend)|"; + Descr="(goto)|(huge)|(if)|(inline)|(int)|(interrupt)|(_loadds)|(long)|"; + Descr="(near)|(new)|(operator)|(pascal)|(private)|(protected)|(public)|"; + Descr="(register)|(return)|(_saveregs)|(_seg)|(short)|(signed)|(sizeof)|"; + Descr="(ss)|(static)|(struct)|(switch)|(template)|(this)|(typedef)|"; + Descr="(union)|(unsigned)|(virtual)|(void)|(volatile)|(while)"; + + Color="#FFFFFF"; + Bold="TRUE"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "IDENTIFIER" ) +{ + Descr ="[A-Za-z_][A-Za-z_0-9]*"; + + Color="#FFFF00"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "SYMBOL" ) +{ + Descr ="\.|;|,|:|-|=|^|&|\?|<|>|%|!|~|\+|/|\*|\[|\]|\{|\}|\||\(|\)"; + + Raw_beg=""; + Raw_end=""; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "PREPROCESOR" ) +{ + Descr="#([^\n]|(\\\n))*\n"; + + Color="#00FF00"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "C COMMENTS" ) +{ + Descr="/\*((\*+[^/])|([^\*]))*\*+/"; + + Color="#C0C0C0"; + Italic="TRUE"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "C++ COMMENTS" ) +{ + Descr="//[^\n]*\n"; + + Color="#C0C0C0"; + Italic="TRUE"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING" ) +{ + Descr="\"(([^\"])|(\\"))*\""; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "CHARACTER CONSTANT" ) +{ + Descr="'(.)|(\\.)'"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "DECIMAL CONSTANT" ) +{ + Descr="[0-9]+[Uu]?[Ll]?"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "HEXA CONSTANT" ) +{ + Descr="0[xX][0-9A-Fa-f]+[Uu]?[Ll]?"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "FLOAT CONSTANT" ) +{ + Descr="([0-9]+\.[0-9]*[fF]?[Ll]?)|([0-9]+[fF]?[Ll]?)|"; + Descr="([0-9]+\.[0-9]*[Ee]-?\+?[0-9]+[fF]?[Ll]?)"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + + + diff --git a/ctounix.hlx b/ctounix.hlx new file mode 100644 index 0000000..b924a52 --- /dev/null +++ b/ctounix.hlx @@ -0,0 +1,149 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Usage: File for porting CPP files from DOS to UNIX +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION" ) +{ + Output ="NO_ENCAPS"; # HTML_PAGE or NO_ENCAPS or HTML_TABLE + + CRLF ="FALSE"; # add CRs to output ( Unix LF, Dos CRLF ) + HtmlOutput="FALSE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Element( "farmalloc -> malloc" ) +{ + Descr="farmalloc"; + + Action="REPLACE"; + + Raw="malloc"; +} + +#--------------------------------------------------------------------------------- + +Element( "FAR away" ) +{ + Descr="far"; + + Action="REMOVE"; +} + +#--------------------------------------------------------------------------------- + +Element( "KEYWORDS" ) +{ + Descr="(asm)|(auto)|(break)|(case)|(cdecl)|(char)|(class)|(const)|"; + Descr="(continue)|(_cs)|(default)|(delete)|(do)|(double)|(_ds)|(else)|"; + Descr="(enum)|(_es)|(_export)|(extern)|(far)|(float)|(for)|(friend)|"; + Descr="(goto)|(huge)|(if)|(inline)|(int)|(interrupt)|(_loadds)|(long)|"; + Descr="(near)|(new)|(operator)|(pascal)|(private)|(protected)|(public)|"; + Descr="(register)|(return)|(_saveregs)|(_seg)|(short)|(signed)|(sizeof)|"; + Descr="(ss)|(static)|(struct)|(switch)|(template)|(this)|(typedef)|"; + Descr="(union)|(unsigned)|(virtual)|(void)|(volatile)|(while)"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "IDENTIFIER" ) +{ + Descr ="[A-Za-z_][A-Za-z_0-9]*"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "SYMBOL" ) +{ + Descr ="\.|;|,|:|-|=|^|&|\?|<|>|%|!|~|\+|/|\*|\[|\]|\{|\}|\||\(|\)"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "PREPROCESOR" ) +{ + Descr="#([^\n]|(\\\n))*\n"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "C COMMENTS" ) +{ + Descr="/\*((\*+[^/])|([^\*]))*\*+/"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "C++ COMMENTS" ) +{ + Descr="//[^\n]*\n"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING" ) +{ + Descr="\"(([^\"])|(\\"))*\""; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "CHARACTER CONSTANT" ) +{ + Descr="'(.)|(\\.)'"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "DECIMAL CONSTANT" ) +{ + Descr="[0-9]+[Uu]?[Ll]?"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "HEXA CONSTANT" ) +{ + Descr="0[xX][0-9A-Fa-f]+[Uu]?[Ll]?"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "FLOAT CONSTANT" ) +{ + Descr="([0-9]+\.[0-9]*[fF]?[Ll]?)|([0-9]+[fF]?[Ll]?)|"; + Descr="([0-9]+\.[0-9]*[Ee]-?\+?[0-9]+[fF]?[Ll]?)"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + + + diff --git a/examples/cpp.htm b/examples/cpp.htm new file mode 100644 index 0000000..06d3305 --- /dev/null +++ b/examples/cpp.htm @@ -0,0 +1,85 @@ + + + + + + + "HILEX translated source" + + + +
+ 
+//-----------------------------------------------------------------------------
+//                        UU comp., bit parity, Dec/Hex ..
+//                                   Dvorka
+//                                    1996
+//-----------------------------------------------------------------------------
+
+#include "bit.h"
+
+typedef unsigned char byte;
+typedef unsigned int  word;
+typedef unsigned long dword;
+
+static union { word   w; struct x { byte lo:8; byte hi:8; }b;} Wrd;
+static byte *tab,
+            invtab[256],               // initialized by InitTab();
+            hex[]={'0','1','2','3','4','5','6','7',
+                   '8','9','A','B','C','D','E','F'};
+
+word ByteToHex( byte in )
+{ Wrd.b.lo=hex[in>>4];Wrd.b.hi=hex[in&0xF];return (Wrd.w); }
+
+
+byte HexToByte( word in )
+{
+ return (((in&0x00FF)>'9'? ((in&0x00FF)-'A'+10)<<4: ((in&0x00FF)-'0')<<4)|
+         ((in&0xFF00)>'9'<<8? (in>>8)-'A'+10 :(in>>8)-'0'));
+}
+
+
+dword dw3Todw4( dword in )
+{
+ return ( (in&0x700ul)>>4|(in&0x3F800ul)>>3|
+          (in&0x1FC0000ul)>>2|(in&0xFE000000ul)>>1 );
+}
+
+
+dword dw4Todw3( dword in )
+{
+ return ((in&0x7F000000ul)<<1|(in&0x7F0000ul)<<2|(in&0x7F00)<<3|(in&0x70)<<4);
+}
+
+
+void InitTab( byte *ntab )
+{
+ byte i; tab=ntab; for( i=0; i<=63; i++ ) invtab[tab[i]]=i; // create inv. tab
+}
+
+
+dword dw3Tabdw4( dword in )
+{
+
+ dword i=(in&0xFC000000ul)>>2|(in&0x03F00000ul)>>4|
+         (in&0x000FC000ul)>>6|(in&0x00003F00ul)>>8;
+       in=tab[*(((char*)&i)+3)]<<8 | tab[*(((char*)&i)+2)];
+       in<<=16;
+ return ( in | tab[*(((char*)&i)+1)]<<8 | tab[*((char*)&i)] );
+}
+
+
+dword dw4Tabdw3( dword in )
+{
+ dword i=invtab[(in&0xFF000000ul)>>24]<<8 | invtab[(in&0xFF0000ul)>>16] ;
+       i<<=16;
+       i|=invtab[(in&0xFF00)>>8]<<8 | invtab[in&0xFF];
+ return ( (i&0x3F000000ul)<<2 | (i&0x003F0000ul)<<4 |
+          (i&0x00003F00ul)<<6 | (i&0x0000003Ful)<<8 );
+}
+
+
+ 
+ + + diff --git a/examples/hilex.htm b/examples/hilex.htm new file mode 100644 index 0000000..e8d4869 --- /dev/null +++ b/examples/hilex.htm @@ -0,0 +1,116 @@ + + + + + + + "HILEX translated source" + + + +
+ 
+#---------------------------------------------------------------------------------
+#
+#                       Configuration file for HILEX
+#
+#                    Languague: HILEX configuration file
+#
+#                                  by Dvorka
+#
+#---------------------------------------------------------------------------------
+
+Setup( "TRANSLATION")
+{
+ Output         ="HTML_PAGE";   # HTML_PAGE or HTML_TABLE or NO_ENCAPS
+
+ CRLF           ="FALSE";       # add CRs to output ( Unix hates them )
+ HtmlOutput     ="TRUE";        # convert < to &lt; ...
+}
+
+#---------------------------------------------------------------------------------
+
+Setup( "ENCAPSULATION" )
+{
+ Face_font ="COURIER NEW";
+ Title     ="HILEX translated source";
+ BaseColor ="#000080";
+ BaseSize  ="+1";
+ BgColor   ="#606060";
+}
+
+#---------------------------------------------------------------------------------
+
+Element( "KEYWORDS" )
+{
+ Descr="([Dd][Ee][Ss][Cc][Rr])|([Oo][Uu][Tt][Pp][Uu][Tt])|";
+ Descr="([Ff][Aa][Cc][Ee]_[Ff][Oo][Nn][Tt])|([Tt][Ii][Tt][Ll][Ee])|";
+ Descr="([Bb][Aa][Ss][Ee][Cc][Oo][Ll][Oo][Rr])|";
+ Descr="([Bb][Aa][Ss][Ee][Ss][Ii][Zz][Ee])|([Bb][Gg][Cc][Oo][Ll][Oo][Rr])|";
+ Descr="([Rr][Aa][Ww]_[Bb][Ee][Gg])|([Rr][Aa][Ww]_[Ee][Nn][Dd])|";
+ Descr="([Cc][Oo][Ll][Oo][Rr])|([Ff][Oo][Nn][Tt])|([Ss][Ii][Zz][Ee])|";
+ Descr="([Bb][Oo][Ll][Dd])|([Uu][Nn][Dd][Ee][Rr][Ss][Cc][Oo][Rr][Ee])|";
+ Descr="([Ii][Tt][Aa][Ll][Ii][Cc])|([Bb][Aa][Cc][Kk][Gg][Rr][Oo][Uu][Nn][Dd])|";
+ Descr="([Ww][Ii][Dd][Tt][Hh])|([Cc][Rr][Ll][Ff])|";
+ Descr="([Hh][Tt][Mm][Ll][Oo][Uu][Tt][Pp][Uu][Tt])|";
+ Descr="([Aa][Cc][Tt][Ii][Oo][Nn])";
+
+ Action="ENCAPSULATE";
+
+ Color="#FFFF00";
+}
+
+#---------------------------------------------------------------------------------
+
+Element( "SYMBOL" )
+{
+ Descr="=|\{|\}|\(|\)|;";
+
+ Action="ENCAPSULATE";
+
+ Raw_beg="<FONT COLOR=\"#FFFFFF\">";
+ Raw_end="</FONT>";
+}
+
+#---------------------------------------------------------------------------------
+
+Element( "COMMENTS" )
+{
+ Descr="#[^\n]*\n";
+
+ Action="ENCAPSULATE";
+
+ COLOR="#C0C0C0";
+ ITALIC="TRUE";
+}
+
+#---------------------------------------------------------------------------------
+
+Element( "BLOCK IDF" )
+{
+ Descr="([Ee][Ll][Ee][Mm][Ee][Nn][Tt])|([Ss][Ee][Tt][Uu][Pp])";
+
+ Action="ENCAPSULATE";
+
+ Color="BLACK";
+ Underscore="TRUE";
+}
+
+#---------------------------------------------------------------------------------
+
+Element( "STRING" )
+{
+ Descr  ="\"(([^\"])|(\\\"))*\"";
+
+ Action="ENCAPSULATE";
+
+ # string uses default text color
+ Bold ="TRUE";
+}
+
+#---------------------------------------------------------------------------------
+
+ 
+ 
+ + diff --git a/examples/pascal.htm b/examples/pascal.htm new file mode 100644 index 0000000..0f57a2b --- /dev/null +++ b/examples/pascal.htm @@ -0,0 +1,136 @@ + + + + + + + "HILEX translated source" + + + +
+ 
+program Hashing;
+
+type
+{----------------------------------------------------------------------------}
+   PClen = ^Clen; { clen tridene struktury }
+   Clen = record
+           {
+             struktura recordu ... }
+             klic : integer;
+            {
+             ...
+             ...
+             ...
+            }
+          end;
+{----------------------------------------------------------------------------}
+   PTabTyp = ^TabTyp;
+   TabTyp = record
+             pravy      : PTabTyp;
+             zaznam     : PClen
+            end;
+{----------------------------------------------------------------------------}
+   PHash = ^Hash;
+   Hash = object
+           velikost_tabulky : integer;
+           vlozeno : integer;
+           prehesuj_pri : byte;
+           constructor Init( ivelikost_tabulky : integer;iprehesuj_pri : byte );
+           procedure Zatrid( Zaznam : PClen ); virtual;
+           procedure Vyndej( Min : PClen ); virtual;
+           procedure Smaz( Co : PClen ); virtual;
+           function Zaplneno : byte; virtual; { vraci v procentech 0 - 100 ) }
+           procedure Prehesuj( velikost : integer ); virtual;
+           destructor Done;
+          end;
+{----------------------------------------------------------------------------}
+var tabulka : array [ 1..8000 ] of TabTyp;
+{----------------------------------------------------------------------------}
+{ metody : }
+{----------------------------------------------------------------------------}
+constructor Hash.Init( ivelikost_tabulky : integer;iprehesuj_pri : byte );
+ begin
+  velikost_tabulky := ivelikost_tabulky;
+  prehesuj_pri := iprehesuj_pri;
+  vlozeno := 0;
+ end;
+{----------------------------------------------------------------------------}
+procedure Hash.Zatrid( Zaznam : PClen );
+var klic        : integer;
+    pomoc,uzel  : PTabTyp;
+ begin
+  { zvolil jsem hasovaci funkci index = f(klic) = klic mod sirka_tabulky }
+  klic :=  Zaznam^.Klic mod velikost_tabulky;
+  inc( vlozeno );
+
+  if tabulka[ klic ].zaznam = nil then
+   begin
+    tabulka[ klic ].zaznam := Zaznam;
+    tabulka[ klic ].pravy := nil;
+   end
+  else
+   begin
+    { musim najit misto kam zapojit - tridim od nejmensiho k nejvetsimu }
+    if ( Zaznam^.klic < tabulka[ klic ].zaznam^.klic) then
+     begin
+      { vse posunout }
+      new( pomoc );
+      pomoc^ := tabulka[ klic ];
+      tabulka[ klic ].zaznam := Zaznam;
+      tabulka[ klic ].pravy := pomoc;
+     end
+    else
+     begin
+      pomoc := tabulka[ klic ].pravy;
+      while ( pomoc^.pravy <> nil ) and
+            ( Zaznam^.klic < pomoc^.zaznam^.klic ) do
+        pomoc := pomoc^.pravy;{ a jsem na konci seznamku }
+
+      new( uzel );
+      uzel^ := pomoc^;
+      pomoc^.pravy := uzel;
+      pomoc^.zaznam := Zaznam;
+     end
+   end;
+
+  if Zaplneno > prehesuj_pri then Prehesuj( ( velikost_tabulky + 1000 ) );
+
+ end;
+{----------------------------------------------------------------------------}
+procedure Hash.Vyndej( Min : PClen );
+ begin
+  { najde nejmensi prvek a vrati na nej pointer }
+ end;
+{----------------------------------------------------------------------------}
+procedure Hash.Smaz( Co : PClen ); virtual;
+var index : integer;
+ begin
+  { vymaze prvek z tabulky na nejz mame pointer }
+ end;
+{----------------------------------------------------------------------------}
+function Hash.Zaplneno : byte;
+var pomoc : real;
+ begin
+  inc( vlozeno );
+  Zaplneno := round(( vlozeno / velikost_tabulky ) * 100 );
+ end;
+{----------------------------------------------------------------------------}
+procedure Hash.Prehesuj( velikost : integer );
+ begin
+  { prehesuje stavajici tabulku do vetsi tabulky }
+ end;
+{----------------------------------------------------------------------------}
+destructor Hash.Done;
+ begin
+  { zruseni objektu }
+ end;
+{----------------------------------------------------------------------------}
+begin
+
+end.
+ 
+ + + diff --git a/examples/prolog.htm b/examples/prolog.htm new file mode 100644 index 0000000..d59e883 --- /dev/null +++ b/examples/prolog.htm @@ -0,0 +1,180 @@ + + + + + + + "HILEX translated source" + + + +
+ 
+%----------------------------------------------------------------------------
+%                               program NIM 
+%                             Martin Dvorak I5
+%                    Vyhledavanim strategickych pozic ...
+%----------------------------------------------------------------------------
+% sude(+Cislo),liche(+Cislo)
+sude(A):-V is (2*( A // 2)),A=V.
+liche(A):-not(sude(A)).
+%----------------------------------------------------------------------------
+% min(+Cislo1,+Cislo2,-Minimum)
+min(A,B,V):-A=<B,V is A.
+min(A,B,V):-A>B,V is B.
+%----------------------------------------------------------------------------
+% strategy(+Stav,Pocet_k*(min+max)+min+s,+P,+R,-Je_vyhr)
+strategy([],C,_,_,V):-((sude(C),V=1);
+                      (liche(C),V=0)).
+strategy([H|T],C2,P,R,V):-H<P,strategy(T,C2,P,R,V).
+
+strategy([H|T],C2,P,R,V):-H>=P,
+                          C is (H mod (P+R)),C =< (P-1),
+                          strategy(T,C2,P,R,V).
+strategy([H|T],C2,P,R,V):-H>=P,C is (H mod (P+R)),
+                          C =< (P+P-1),C >= P,
+                          C2O is C2+1,
+                          strategy(T,C2O,P,R,V).
+strategy([H|_],_,P,R,0):-H>=P,C is (H mod (P+R)),
+                         C > (P+P-1).
+%----------------------------------------------------------------------------
+% uber(+Stav,+Kde,+Kolik,-Uspech,-Vysl,Pozice) , uspech 1 , neuspech 0
+uber([H|T],C,P,1,[OH|T],InC):-InC = C,H >= P,          % uspesne da 1
+                              OH is H - P. 
+uber([H|_],C,P,0,_,InC ):-InC = C,H<P.                 % neuspesne da 0
+uber([H|T],C,P,U,[H|OT],InC):-InC < C,MInC is InC+1,   % posun na dalsi
+                              uber(T,C,P,U,OT,MInC).
+%----------------------------------------------------------------------------%
+% udela seznam vsech moznych tahu
+% moznosti(+Stav,+K,+P,+R,-Moznosti)
+moznosti(Sez,K,SP,R,Vysl):-P is SP-1,                         % SP - pravne P
+                           moznosti(Sez,1,K,P,SP,R,[],Vysl).
+moznosti(_,MK,K,MR,_,R,V,V):-MR=R,MK=K.
+moznosti(Sez,MK,K,MR,P,R,MV,V):-MR=R,MK<K,
+                                NK is MK+1,NR is P,           % dalsi hrom
+                                uber(Sez,NK,NR,OK,OSez,1),
+                                ((OK=0,!,moznosti(Sez,NK,K,NR,P,R,MV,V));
+                                 (OK=1,!,
+                                  moznosti(Sez,NK,K,NR,P,R,[OSez|MV],V))).
+moznosti(Sez,MK,K,MR,P,R,MV,V):-MR<R,MK=<K,
+                                NR is MR+1,                   % dalsi sirka
+                                uber(Sez,MK,NR,OK,OSez,1),
+                                ((OK=0,!,moznosti(Sez,MK,K,NR,P,R,MV,V));
+                                 (OK=1,!,
+                                  moznosti(Sez,MK,K,NR,P,R,[OSez|MV],V))).
+%----------------------------------------------------------------------------%
+% zkontroluje zda nektera z mych moznosti jak tahnout vede dle strategie 
+% na vyhru ve hre.
+% check(+Moznosti,+P,+R,-Opt.Pos)
+check([],_,_,[]).
+check([H|T],P,R,V):-strategy(H,0,P,R,C),
+                    ((C=0,!,check(T,P,R,V));
+                     (C=1,!,V=H)).
+%----------------------------------------------------------------------------%
+% vybere ze seznamu stav , z ktereho nejde hrat na vyhravajici pozici
+% vyber(+Stavy,K,P,R,-Tah)
+vyber([],_,_,_,[]).
+vyber([H|T],K,P,R,V):-moznosti(H,K,P,R,Moz),
+                      check(Moz,P,R,Out),
+                      ((Out=[],V=H);          % z H nejde hrat na strategii
+                       (Out\=[],vyber(T,K,P,R,V))).
+%----------------------------------------------------------------------------%
+% byla nalezena vyhr. pozice , vzda uzivatel ?
+% vzdej(-OK)
+vzdej(OK):-nl,write(' Nalezl jsem pozici vedouci na vitezstvi!'),
+           nl,write(' Chcete pokracovat ve hre (a/n) :'),read(Volba),
+           ((Volba=a,OK=1);(Volba\=a,OK=0,write(' Vyhral jsem !'))).
+%----------------------------------------------------------------------------
+% nachazi optimalni tah ze stavu stav
+% tah(+Stav,+K,+P,+R,-Opt,-Konec)
+tah(Sez,K,P,R,OptTah,OK):-moznosti(Sez,K,P,R,Moz),
+                          check(Moz,P,R,Opt),       % muzu tahnout na o.p. ?
+                          ((Opt=[],OK1 is 1,vyber(Moz,K,P,R,V), % nemohu
+                                   ((V=[],[A|_]=Moz,OptTah=A);
+                                    (V\=[],OptTah=V))
+                           );
+                           (Opt\=[],vzdej(OK1),OptTah=Opt)),    % mohu
+                          nl,write(' MUJ TAH:  '),write(OptTah),
+                          konec(OptTah,P,R,ja,OK2), % neni tah , vyhravam
+                          min(OK1,OK2,OK).          % priznak konce hry
+%----------------------------------------------------------------------------%
+% ohodnot(+Stav,+P,+R,-Vyhodnost) ,1/-1,0 znamena ze nejde ohodnotit.
+ohodn([],_,_,0,Hodn):-Hodn is -1.                % soucet 0 - prohravam
+ohodn([],_,_,1,Hodn):-Hodn is 1.                 % soucet 1 - vyhravam
+ohodn([],_,_,MH,Hodn):-MH\=0,MH\=1,Hodn is 0.    % soucet vetsi - nelze
+ohodn([H|_],_,R,_,Hodn):-H > R,Hodn is 0.        % mimo obor - nelze
+ohodn([H|T],P,R,MH,Hodn):-H < P,H < R,           % nemohou brat => posun
+                          ohodn(T,P,R,MH,Hodn).
+ohodn([H|T],P,R,MH,Hodn):-H >= P,H =< R,           % mohu dobrat hromadku
+                          MOH is MH + 1,           % pridam do souctu
+                          ohodn(T,P,R,MOH,Hodn).
+%----------------------------------------------------------------------------%
+% test konce hry,chyby : konec(+Stav,+P,+R,+Odkud_volam,-Priznak)
+konec(Tah,P,R,ja,0):-ohodn(Tah,P,R,0,Hodn),Hodn = -1,
+                     nl,write(' Vyhral jsem ! '),!.
+konec(Tah,P,R,on,0):-ohodn(Tah,P,R,0,Hodn),Hodn = -1,
+                     nl,write(' Gratuluji , vyhral jste !'),!. 
+konec(Tah,P,R,test,0):-ohodn(Tah,P,R,0,Hodn),Hodn = -1,
+                     nl,write(' Nesmyslne zadani !'),!.
+konec(_,_,_,_,1).
+%----------------------------------------------------------------------------%
+% kdo vyhraje pri predem rozhodnute hre : kdo(+Stav,+P,C)
+kdo([],_,C):-((liche(C),nl,write(' Vyhral by jste !'));
+              (sude(C),nl,write(' Prohral by jsem !'))).
+kdo([H|T],P,C):-CO is (C+(H//P)),kdo(T,P,CO).
+%----------------------------------------------------------------------------
+% test zda je hra predem rozhodnuta: smysl(+Stav,+P,+R,-Priznak)
+smysl(Sez,P,R,OK):-((P=R,nl,write(' Toto je predem rozhodnuta hra .'),
+                     kdo(Sez,P,0),OK = 0);
+                    (P\=R,OK = 1)). 
+%----------------------------------------------------------------------------
+% testuje koreknost zadani : test_zac(+Stav,+P,+R)
+test_zac(Sez,P,R):-((lst(Sez),length(Sez,K),K>0,P=<R,integer(P),integer(R));
+                    (nl,write(' Nesmyslne zadani! Vlozte prosim nove.'),fail)).
+%----------------------------------------------------------------------------
+% vstup zadani : zacatek(-Stav,-K,-P,-R,-Priznak)
+zacatek(Sez,K,P,R,OK):- repeat,
+                        nl,write(' Vlozte pocatecni stav: '),read(Sez),
+                        write(' Odebrat minimalne: '),read(P),
+                        write(' Odebrat maximalne: '),read(R),
+                        test_zac(Sez,P,R),length(Sez,K),
+                        konec(Sez,P,R,test,OK),!.
+%----------------------------------------------------------------------------%
+% test korektnosti pri odebirani: test_vstup(+K,+P,+R,+Hrom,+Sir)
+test_vstup(K,P,R,Hrom,Sir):-((integer(Hrom),integer(Sir),Hrom=<K,Sir>=P,
+                            Sir=<R);
+                           (nl,write(' Nesmyslne zadani! Vlozte prosim nove.'),
+                            fail)).
+%----------------------------------------------------------------------------
+% tah soupere : vstup(+Stav,+K,+P,+R,-Jeho_tah,-Priznak)
+vstup(Sez,K,P,R,OSez,OOK):- repeat,
+                        nl,write('   Vlozte cislo hromadky :'),read(Hrom),
+                        write('   Pocet odebiranych sirek :'),read(Sirky),
+                        test_vstup(K,P,R,Hrom,Sirky),                      
+                        uber(Sez,Hrom,Sirky,OK,OSez,1),nonvar(OK),OK=1, 
+                        !,
+                        write(' VAS TAH:  '),write(OSez),
+                        konec(OSez,P,R,on,OOK).
+%----------------------------------------------------------------------------%
+% pokud neuspeje OK = 1 hra konci.
+%----------------------------------------------------------------------------
+% tah_hrace(+Stav,+K,+P,+R)
+tah_hrace(Sez,K,P,R):-vstup(Sez,K,P,R,OSez,OK),nonvar(OK),OK = 1,
+                      tah_programu(OSez,K,P,R).
+%----------------------------------------------------------------------------%
+% tah_programu(+Stav,+K,+P,+R)
+tah_programu(Sez,K,P,R):-tah(Sez,K,P,R,OSez,OK),nonvar(OK),OK = 1,
+                         tah_hrace(OSez,K,P,R).
+%----------------------------------------------------------------------------%
+% spusteni hry
+nim:-nl,nl,nl,nl,nl,tab(32),write('NIM'),nl,
+     tab(19),write(' Prohrava hrac , ktery nema tah .'),nl,
+     zacatek(Sez,K,P,R,OK1),smysl(Sez,P,R,OK2),         % kor. a smysl zadani
+     min(OK1,OK2,OK),nonvar(OK),OK=1,
+     tah_hrace(Sez,K,P,R).
+%--------------------------- Konec programu ---------------------------------%
+
+ 
+ + + diff --git a/hilex.exe b/hilex.exe new file mode 100644 index 0000000000000000000000000000000000000000..5894175183cd8927a2da9d2873c90ea1742ac188 GIT binary patch literal 104224 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 Urhi{jk&=G-TztRq7li}=AHNggjQ{`u literal 0 HcmV?d00001 diff --git a/hilex.hlx b/hilex.hlx new file mode 100644 index 0000000..b5865a9 --- /dev/null +++ b/hilex.hlx @@ -0,0 +1,98 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Languague: HILEX configuration file +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION") +{ + Output ="HTML_PAGE"; # HTML_PAGE or HTML_TABLE or NO_ENCAPS + + CRLF ="FALSE"; # add CRs to output ( Unix hates them ) + HtmlOutput ="TRUE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#000080"; + BaseSize ="+1"; + BgColor ="#606060"; +} + +#--------------------------------------------------------------------------------- + +Element( "KEYWORDS" ) +{ + Descr="([Dd][Ee][Ss][Cc][Rr])|([Oo][Uu][Tt][Pp][Uu][Tt])|"; + Descr="([Ff][Aa][Cc][Ee]_[Ff][Oo][Nn][Tt])|([Tt][Ii][Tt][Ll][Ee])|"; + Descr="([Bb][Aa][Ss][Ee][Cc][Oo][Ll][Oo][Rr])|"; + Descr="([Bb][Aa][Ss][Ee][Ss][Ii][Zz][Ee])|([Bb][Gg][Cc][Oo][Ll][Oo][Rr])|"; + Descr="([Rr][Aa][Ww]_[Bb][Ee][Gg])|([Rr][Aa][Ww]_[Ee][Nn][Dd])|"; + Descr="([Cc][Oo][Ll][Oo][Rr])|([Ff][Oo][Nn][Tt])|([Ss][Ii][Zz][Ee])|"; + Descr="([Bb][Oo][Ll][Dd])|([Uu][Nn][Dd][Ee][Rr][Ss][Cc][Oo][Rr][Ee])|"; + Descr="([Ii][Tt][Aa][Ll][Ii][Cc])|([Bb][Aa][Cc][Kk][Gg][Rr][Oo][Uu][Nn][Dd])|"; + Descr="([Ww][Ii][Dd][Tt][Hh])|([Cc][Rr][Ll][Ff])|"; + Descr="([Hh][Tt][Mm][Ll][Oo][Uu][Tt][Pp][Uu][Tt])"; + + Action="ENCAPSULATE"; + + Color="#FFFF00"; +} + +#--------------------------------------------------------------------------------- + +Element( "SYMBOL" ) +{ + Descr="=|\{|\}|\(|\)|;"; + + Action="ENCAPSULATE"; + + Raw_beg=""; + Raw_end=""; +} + +#--------------------------------------------------------------------------------- + +Element( "COMMENTS" ) +{ + Descr="#[^\n]*\n"; + + Action="ENCAPSULATE"; + + COLOR="#C0C0C0"; + ITALIC="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "BLOCK IDF" ) +{ + Descr="([Ee][Ll][Ee][Mm][Ee][Nn][Tt])|([Ss][Ee][Tt][Uu][Pp])"; + + Action="ENCAPSULATE"; + + Color="BLACK"; + Underscore="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING" ) +{ + Descr ="\"(([^\"])|(\\\"))*\""; + + Action="ENCAPSULATE"; + + # string uses default text color + Bold ="TRUE"; +} + +#--------------------------------------------------------------------------------- diff --git a/hilex.prj b/hilex.prj new file mode 100644 index 0000000000000000000000000000000000000000..5a61f92fc2c66e716f686b9ee608ba897fcc532b GIT binary patch literal 9419 zcmeI2d2mz58Nk11$&xJFV2*IxUO?iue1L6m+z2DfL^HOeN^*liz{s|2gk{O-aBL?r zgewq20!c_`m}Dj-hDQS|XP0Q=|y?wF{ zTef6eI_>lse%{@;yWg?j9&f=F4YdcEiP=NJ-QJD}Yx4QMYyk*`Gv^BUOI-yH&D)Rz z0=$C+cvnilC-I_G^1hUQJ)hqGSmGNJe}WX?lJxeM5w z*RYN783O)7_?)s|Q0hxi0_+3$D`mbS{EhH;YQ@egkvV^sdbpgA#a9R)N_u=m$&WEv z1iwZq;cII5@^tL@ADB}96QQ_HWg-Cte1Q)L3Ir$#xdauJsS)!vh|W9&(;^_BP(Ua| z2-67D2}M*kgYYCu%Q=I9rwC6I&Jvy>JWF_v@I2u>;R50NgdY&TLwEt9I7g`$2`>@8 zOZXn)6~Ye*GfCtu!fb?a3t$&}`WRCO7eBKNT3B zYpVb%g`Z5O*jnr^rZZut#kqL}X;+1bmHk0qCtGFcU>QreITha(g<+R;kZTBsy}j*zZz!E$ zSA(-9-Mh(@m$z(TE>BSKj;>Sc6en+GYLWuNXjVZM3f5nCGi-Kd=8xBT89bRS%_V%UsqQf+W z{==?xQ{Cazs+VzZKgYGu(%TmdMOd@1J>&`bJb^TgEiLvbJ?84By2CVj|GSHSA<`cG z|L2B0unzi#LT#{<)m9r=zc)1GE!5_1?ezvctS8tR?DqtG%;sR5Y+G8TYU?+|t678n zgYrpMdRJLl6Mq??mtDb7uP4Ij#EUC!l-F9jHeM^rdZQ693j}*uB*>6qFYEAoJ)!7s zFAGP4eXPsx>1I8hgF`IZ;~Ao2R4wdnM?K4KV*zhZFyQS746=^F9)C2PT8VjBe>f8D zqkaS4zTmFGcI={1Tc}-4==Au*J~oub+(K<-buGHX*Xa#Jd|kdCPb3%`Wc?%dP_Ln2 ze;^oTBXy#?eXPS5_IrD=C2Ba-J{Um-(HhdgAM|u$4U%0AE*0Je!P9uWY%K(E;H5_d z?>hJ)*uAN>smbh+4y5M9OxB~l43@(Rn2zmcNV1}G4?6rU%W}5b?KX!?66Q|KWGieX zetWKlY1r%*IE!{Ygci~V`a-;ck!9U(X|_1ID6=~uldULN17&!vfsTWDlB|5Kc&WHZ^gRT%T}OtzBn_8aGM zK3?zx)JmWBRXA3!V5l5ISuG6~tD7L1l$6O{5Vp{R4wlk&|2{jEvLfn(m9kQU0dujR zi^grn>vh|W7bo?@jCNzl7&PuSdW{{%h_TLC1J|{5g|ad46YVAK%i71Z1KO?HdhKFu zj`nKan|WvRR^`pgJEi$r^Lx$Pnqtkc#-}-~R%x!OFR2UE0reL3Y1LP%Kd9c!-LLYi z?oiFkeKGe*rI7on@;8bj%8*j2cuR3!u_@=%oXa_WVNK4woB?PP>IG38AoE~7oW>E% zg^lyynWvJdmRKk;U*a^08zd^hVJ+2bq;#G{t;7O})8WeF_4*?CSzCc#2g|!l^^4)m ziJAJj(D1@S{Q~I9E7mWRYL>tUTZ{F2&}=W&m%$!iiGCFvi(@f@6ZQI8 z@R_SvKU=C_1AjVQuNTGC`XVWAFu3tg{HojSvb2~Dw}VKwB}WPE3DuB`TJj#bu3Q6d z3HJiGoLk6kOSFXhE74QjN8J8&b|(6cdxzUBievjlB$MUI%jXc9M5-s1(Ipt|s#S35 zwR+iey!TA(;r8?KxpAvv_D~dvG=wQj59&`!rj&9E7C|{Y`g)xl0i*RAKRUVRx%|Y@ z96f@WkB%r(?2fK4QivwnfD1TUM#`s@#>Qq1e0j89j`N#8Dx+gfqzRXxEA4P-0V$bM z$}K2>m7unj%5!vbVR28cAtWf}55j)JN0g9D}e9!UOl^DZ(mEtQ| z;{4?LXRQTDH-j?8(C095f{S5^?JIrRwk>8 zuBJs~DWx&V^I;o0g3tKzC3BfPs*)vt^IOLo$KI8k zE{DasnGC1(URFW=(7{3yom?1GYYx2hqdIvL9bc`n6pC-{(hQVE$RBekm-kffrsHFoPdYmK{yT%z%jTV Q?u34bf}cV)!-oR=U!evyeE"; + Raw_end=""; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "PREPROCESOR" ) +{ + Descr="#([^\n]|(\\\n))*\n"; + + Color="#00FF00"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "C COMMENTS" ) +{ + Descr="/\*((\*+[^/])|([^\*]))*\*+/"; + + Color="#C0C0C0"; + Italic="TRUE"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "C++ COMMENTS" ) +{ + Descr="//[^\n]*\n"; + + Color="#C0C0C0"; + Italic="TRUE"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING" ) +{ + Descr="\"(([^\"])|(\\"))*\""; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "CHARACTER CONSTANT" ) +{ + Descr="'(.)|(\\.)'"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "DECIMAL CONSTANT" ) +{ + Descr="[0-9]+[Uu]?[Ll]?"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "HEXA CONSTANT" ) +{ + Descr="0[xX][0-9A-Fa-f]+[Uu]?[Ll]?"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + +Element( "FLOAT CONSTANT" ) +{ + Descr="([0-9]+\.[0-9]*[fF]?[Ll]?)|([0-9]+[fF]?[Ll]?)|"; + Descr="([0-9]+\.[0-9]*[Ee]-?\+?[0-9]+[fF]?[Ll]?)"; + + Color="#00FFFF"; + + Action="ENCAPSULATE"; +} + +#--------------------------------------------------------------------------------- + + + diff --git a/hlx/ctounix.hlx b/hlx/ctounix.hlx new file mode 100644 index 0000000..0a636ef --- /dev/null +++ b/hlx/ctounix.hlx @@ -0,0 +1,150 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Usage: File for porting CPP files from DOS to UNIX +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION" ) +{ + Output ="NO_ENCAPS"; # HTML_PAGE or NO_ENCAPS or HTML_TABLE + + CRLF ="FALSE"; # add CRs to output ( Unix LF, Dos CRLF ) + HtmlOutput="FALSE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Element( "farmalloc -> malloc" ) +{ +# Descr="farmalloc"; + Descr="("; + + Action="REPLACE"; + + Raw="malloc"; +} + +#--------------------------------------------------------------------------------- + +Element( "FAR away" ) +{ + Descr="far"; + + Action="REMOVE"; +} + +#--------------------------------------------------------------------------------- + +Element( "KEYWORDS" ) +{ + Descr="(asm)|(auto)|(break)|(case)|(cdecl)|(char)|(class)|(const)|"; + Descr="(continue)|(_cs)|(default)|(delete)|(do)|(double)|(_ds)|(else)|"; + Descr="(enum)|(_es)|(_export)|(extern)|(far)|(float)|(for)|(friend)|"; + Descr="(goto)|(huge)|(if)|(inline)|(int)|(interrupt)|(_loadds)|(long)|"; + Descr="(near)|(new)|(operator)|(pascal)|(private)|(protected)|(public)|"; + Descr="(register)|(return)|(_saveregs)|(_seg)|(short)|(signed)|(sizeof)|"; + Descr="(ss)|(static)|(struct)|(switch)|(template)|(this)|(typedef)|"; + Descr="(union)|(unsigned)|(virtual)|(void)|(volatile)|(while)"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "IDENTIFIER" ) +{ + Descr ="[A-Za-z_][A-Za-z_0-9]*"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "SYMBOL" ) +{ + Descr ="\.|;|,|:|-|=|^|&|\?|<|>|%|!|~|\+|/|\*|\[|\]|\{|\}|\||\(|\)"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "PREPROCESOR" ) +{ + Descr="#([^\n]|(\\\n))*\n"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "C COMMENTS" ) +{ + Descr="/\*((\*+[^/])|([^\*]))*\*+/"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "C++ COMMENTS" ) +{ + Descr="//[^\n]*\n"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING" ) +{ + Descr="\"(([^\"])|(\\"))*\""; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "CHARACTER CONSTANT" ) +{ + Descr="'(.)|(\\.)'"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "DECIMAL CONSTANT" ) +{ + Descr="[0-9]+[Uu]?[Ll]?"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "HEXA CONSTANT" ) +{ + Descr="0[xX][0-9A-Fa-f]+[Uu]?[Ll]?"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + +Element( "FLOAT CONSTANT" ) +{ + Descr="([0-9]+\.[0-9]*[fF]?[Ll]?)|([0-9]+[fF]?[Ll]?)|"; + Descr="([0-9]+\.[0-9]*[Ee]-?\+?[0-9]+[fF]?[Ll]?)"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- + + + diff --git a/hlx/hilex.hlx b/hlx/hilex.hlx new file mode 100644 index 0000000..b5865a9 --- /dev/null +++ b/hlx/hilex.hlx @@ -0,0 +1,98 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Languague: HILEX configuration file +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION") +{ + Output ="HTML_PAGE"; # HTML_PAGE or HTML_TABLE or NO_ENCAPS + + CRLF ="FALSE"; # add CRs to output ( Unix hates them ) + HtmlOutput ="TRUE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#000080"; + BaseSize ="+1"; + BgColor ="#606060"; +} + +#--------------------------------------------------------------------------------- + +Element( "KEYWORDS" ) +{ + Descr="([Dd][Ee][Ss][Cc][Rr])|([Oo][Uu][Tt][Pp][Uu][Tt])|"; + Descr="([Ff][Aa][Cc][Ee]_[Ff][Oo][Nn][Tt])|([Tt][Ii][Tt][Ll][Ee])|"; + Descr="([Bb][Aa][Ss][Ee][Cc][Oo][Ll][Oo][Rr])|"; + Descr="([Bb][Aa][Ss][Ee][Ss][Ii][Zz][Ee])|([Bb][Gg][Cc][Oo][Ll][Oo][Rr])|"; + Descr="([Rr][Aa][Ww]_[Bb][Ee][Gg])|([Rr][Aa][Ww]_[Ee][Nn][Dd])|"; + Descr="([Cc][Oo][Ll][Oo][Rr])|([Ff][Oo][Nn][Tt])|([Ss][Ii][Zz][Ee])|"; + Descr="([Bb][Oo][Ll][Dd])|([Uu][Nn][Dd][Ee][Rr][Ss][Cc][Oo][Rr][Ee])|"; + Descr="([Ii][Tt][Aa][Ll][Ii][Cc])|([Bb][Aa][Cc][Kk][Gg][Rr][Oo][Uu][Nn][Dd])|"; + Descr="([Ww][Ii][Dd][Tt][Hh])|([Cc][Rr][Ll][Ff])|"; + Descr="([Hh][Tt][Mm][Ll][Oo][Uu][Tt][Pp][Uu][Tt])"; + + Action="ENCAPSULATE"; + + Color="#FFFF00"; +} + +#--------------------------------------------------------------------------------- + +Element( "SYMBOL" ) +{ + Descr="=|\{|\}|\(|\)|;"; + + Action="ENCAPSULATE"; + + Raw_beg=""; + Raw_end=""; +} + +#--------------------------------------------------------------------------------- + +Element( "COMMENTS" ) +{ + Descr="#[^\n]*\n"; + + Action="ENCAPSULATE"; + + COLOR="#C0C0C0"; + ITALIC="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "BLOCK IDF" ) +{ + Descr="([Ee][Ll][Ee][Mm][Ee][Nn][Tt])|([Ss][Ee][Tt][Uu][Pp])"; + + Action="ENCAPSULATE"; + + Color="BLACK"; + Underscore="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING" ) +{ + Descr ="\"(([^\"])|(\\\"))*\""; + + Action="ENCAPSULATE"; + + # string uses default text color + Bold ="TRUE"; +} + +#--------------------------------------------------------------------------------- diff --git a/hlx/html.hlx b/hlx/html.hlx new file mode 100644 index 0000000..35bbcf5 --- /dev/null +++ b/hlx/html.hlx @@ -0,0 +1,131 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Languague: HTML +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION" ) +{ + Output ="HTML_PAGE"; # HTML_PAGE or NO_ENCAPS or HTML_TABLE + + CRLF ="FALSE"; # add CRs to output ( Unix LF, Dos CRLF ) + HtmlOutput="TRUE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_Font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#FFFF00"; + BaseSize ="+1"; + BgColor ="#000080"; + Width ="555"; # used when HTML_TABLE in other cases is ignored +} + +#--------------------------------------------------------------------------------- + +Element( "COMMENTS" ) +{ + Descr=" Version 1.0173 compiled at %s, %s" + "\n EMail: UltraDvorka@post.cz" + "\n Command line help:" + "\n hilex <-[c|h|H|?|t|a][o][v]> " + "\n Usage:" + "\n hilex -h or hilex -H or hilex -?" + "\n ... for help" + "\n hilex -c <*.HLX>" + "\n ... compiles HLX file to BCA (binary form)" + "\n hilex -t <*.BCA> " + "\n ... translates infile to outfile using binary BCA" + "\n hilex -a <*.HLX> " + "\n ... compiles HLX file to BCA and then translates as in -t" + "\n hilex -cv <*.HLX>" + "\n ... add \'v\' to switch to run program in \"off verbose\" mode" + "\n ( example for -c )" + "\n hilex -ot <*.BCA> " + "\n ... add \'o\' to a/t in switch to redirect output to STDOUT" + "\n specify ONLY input file, verbose off is set by default" + "\n ( example for -t )" + "\n" + , + __DATE__, + __TIME__ + ); + + return 0; + #endif + + //---------------------------------------------------------------- + + + + + + #ifdef DEBUG + printf("\n\n Memory statistic:"); + + if( FarFreeMemoryAtStart!=((unsigned long) farcoreleft())) + { + printf("\n Deallocation ERROR:"); + Beep(); Beep(); Beep(); + } + else + Beep(); + + printf( + "\n Far free at start: %lu" + "\n and now : %lu" + "\n" + , + FarFreeMemoryAtStart, + ((unsigned long) farcoreleft()) + ); + + printf("\n Bye! \n\n"); + + return 0; + #endif + +} + +//- EOF ----------------------------------------------------------------------- + diff --git a/pascal.hlx b/pascal.hlx new file mode 100644 index 0000000..c874935 --- /dev/null +++ b/pascal.hlx @@ -0,0 +1,145 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Languague: PASCAL +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION" ) +{ + Output ="HTML_PAGE"; # HTML_PAGE or NO_ENCAPS or HTML_TABLE + + CRLF ="FALSE"; # add CRs to output ( Unix LF, Dos CRLF ) + HtmlOutput="TRUE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_Font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#FFFF00"; + BaseSize ="+1"; + BgColor ="#000080"; +} + +#--------------------------------------------------------------------------------- + +Element( "KEYWORDS" ) +{ + Descr="([aA][nN][dD])|([aA][sS][mM])|([aA][rR][rR][aA][yY])|"; + Descr="([bB][eE][gG][iI][nN])|([cC][aA][sS][eE])|([cC][oO][nN][sS][tT])|"; + Descr="([cC][oO][nN][sS][tT][rR][uU][cC][tT][oO][rR])|"; + Descr="([dD][eE][sS][tT][rR][uU][cC][tT][oO][rR])|([dD][iI][vV])|([dD][oO])|"; + Descr="([dD][oO][wW][nN][tT][oO])|([eE][lL][sS][eE])|([eE][nN][dD])|"; + Descr="([eE][xX][pP][oO][rR][tT][sS])|([fF][iI][lL][eE])|([fF][oO][rR])|"; + Descr="([fF][uU][nN][cC][tT][iI][oO][nN])|([gG][oO][tT][oO])|([iI][fF])|"; + Descr="([iI][mM][pP][lL][eE][mM][eE][nN][tT][aA][tT][iI][oO][nN])|"; + Descr="([iI][nN])|([iI][nN][hH][eE][rR][iI][tT][eE][dD])|"; + Descr="([iI][nN][lL][iI][nN][eE])|([iI][nN][tT][eE][rR][fF][aA][cC][eE])|"; + Descr="([lL][aA][bB][eE][lL])|([lL][iI][bB][rR][aA][rR][yY])|"; + Descr="([mM][oO][dD])|([nN][iI][lL])|([nN][oO][tT])|"; + Descr="([oO][bB][jJ][eE][cC][tT])|([oO][fF])|([oO][rR])|"; + Descr="([pP][aA][cC][kK][eE][dD])|([pP][rR][oO][cC][eE][dD][uU][rR][eE])|"; + Descr="([pP][rR][oO][gG][rR][aA][mM])|([rR][eE][cC][oO][rR][dD])|"; + Descr="([rR][eE][pP][eE][aA][tT])|([sS][eE][tT])|([sS][hH][lL])|"; + Descr="([sS][hH][rR])|([sS][tT][rR][iI][nN][gG])|([tT][hH][eE][nN])|"; + Descr="([tT][oO])|([tT][yY][pP][eE])|([uU][nN][iI][tT])|"; + Descr="([uU][nN][tT][iI][lL])|([uU][sS][eE][sS])|([vV][aA][rR])|"; + Descr="([wW][hH][iI][lL][eE])|([wW][iI][tT][hH])|([xX][oO][rR])"; + + Action="ENCAPSULATE"; + + Color="#FFFFFF"; + Bold="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "IDENTIFIER" ) +{ + Descr ="[A-Za-z_][A-Za-z_0-9]*"; + + Action="NO"; + + # no options -> not encapsulated -> has the color of the default text + # leave it yellow +} + +#--------------------------------------------------------------------------------- + +Element( "SYMBOL" ) +{ + Descr ="\.|;|,|:|\[|\]|\{|\}|\(|\)|$|^"; + + Action="NO"; + + # leave it yellow +} + +#--------------------------------------------------------------------------------- + +Element( "OPERATOR" ) +{ + Descr ="<|>|(<>)|=|(<=)|(>=)|(:=)|@|\+|-|\*|/"; + + Action="NO"; + + # leave it yellow +} + +#--------------------------------------------------------------------------------- + +Element( "COMMENTS" ) +{ + Descr="\{[^\}]*\}"; + + Action="ENCAPSULATE"; + + COLOR="#C0C0C0"; + ITALIC="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING" ) +{ + Descr="\'(([^\'])|(\\'))*\'"; + + Action="NO"; + + # and again yellow +} + +#--------------------------------------------------------------------------------- + +Element( "INTEGER OR CHAR CONSTANT" ) +{ + Descr="#?[0-9]+)"; + + Action="NO"; + + # yellow +} + +#--------------------------------------------------------------------------------- + +Element( "REAL CONSTANT" ) +{ + Descr="[0-9]+\.([0-9]*[Ee]-?\+?[0-9]+)?"; + + Action="NO"; + + # yellow +} + +#--------------------------------------------------------------------------------- + + + + + diff --git a/prolog.hlx b/prolog.hlx new file mode 100644 index 0000000..8dfff30 --- /dev/null +++ b/prolog.hlx @@ -0,0 +1,124 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for HILEX +# +# Languague: Prolog ( not complete ) +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION" ) +{ + Output ="HTML_PAGE"; # HTML_PAGE or NO_ENCAPS or HTML_TABLE + + CRLF ="FALSE"; # add CRs to output ( Unix LF, Dos CRLF ) + HtmlOutput="TRUE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_Font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#FFFF00"; + BaseSize ="+1"; + BgColor ="#009900"; +} + +#--------------------------------------------------------------------------------- + +Element( "KEYWORDS" ) +{ + Descr="(fail)|(is)|(length)|(nl)|(not)|(read)|(write)|"; + Descr="(name)|(append)|(dos)|(consult)|(edit_file)"; + + Action="ENCAPSULATE"; + + Color="#FFFFFF"; + Bold ="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "IDENTIFIER" ) +{ + Descr ="[A-Za-z_][A-Za-z_0-9]*"; + + Action="NO"; + + # default color +} + +#--------------------------------------------------------------------------------- + +Element( "PROLOG CUT" ) +{ + Descr ="!"; + + Action="ENCAPSULATE"; + + Color ="RED"; + Bold ="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "SYMBOL" ) +{ + Descr ="\\|\.|;|,|:|-|=|^|&|\?|<|>|%|~|\+|/|\*|\[|\]|\{|\}|\||\(|\)"; + + Action="ENCAPSULATE"; + + Raw_beg=""; + Raw_end=""; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING 1" ) +{ + Descr="\'(([^\'])|(\\'))*\'"; + + Action="ENCAPSULATE"; + + Color="#00FFFF"; +} + +#--------------------------------------------------------------------------------- + +Element( "STRING 2" ) +{ + Descr="\"(([^\"])|(\\"))*\""; + + Action="ENCAPSULATE"; + + Color="#00FFFF"; +} + +#--------------------------------------------------------------------------------- + +Element( "COMMENTS" ) +{ + Descr="%[^\n]*\n"; + + Action="ENCAPSULATE"; + + Color="BLACK"; + Italic="TRUE"; +} + +#--------------------------------------------------------------------------------- + +Element( "NUMBER" ) +{ + Descr="[0-9]+)"; + + Action="ENCAPSULATE"; + + Color="#00FFFF"; +} + +#--------------------------------------------------------------------------------- + diff --git a/source/box.cpp b/source/box.cpp new file mode 100644 index 0000000..c47d2f5 --- /dev/null +++ b/source/box.cpp @@ -0,0 +1,125 @@ +#include "source\box.h" + +// print info when hunting bugs +//#define DEBUG + +//- class BoxListItem methods ----------------------------------------------------------------------------- + +void BoxListItem::Print( void ) +{ + #ifdef DEBUG + printf("\n Sign %d target %Fp", List, Target ); + #endif +} + +//- class RegularBox methods ----------------------------------------------------------------------------- + +RegularBox::RegularBox( ItemType iType, BoxStructure far *Boxes ) +{ + IN=new List; + OK=new List; + NOK=new List; if( !IN || !OK || !NOK ) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + Type=iType; + + // register itself + Boxes->Register( this ); + + #ifdef DEBUG + printf("\n RegularBox 0x%Fp created, type %d", this, Type ); + #endif +} + +//------------------------------------------------------------------------------ + +void RegularBox::Print( void ) +{ + #ifdef DEBUG + + ListItem far *Item; + + printf("\n BOX PROFILE: %Fp type is %d", this, Type ); + printf("\n IN list:"); + Item=IN->GetHead(); + while( Item ) + { + ((BoxListItem far *)Item)->Print(); + Item=IN->Next(Item); + } + + printf("\n OK list:"); + Item=OK->GetHead(); + while( Item ) + { + ((BoxListItem far *)Item)->Print(); + Item=OK->Next(Item); + } + + printf("\n NOK list:"); + Item=NOK->GetHead(); + while( Item ) + { + ((BoxListItem far *)Item)->Print(); + Item=NOK->Next(Item); + } + + #endif +} + +//------------------------------------------------------------------------------ + +RegularBox::~RegularBox() +{ + delete IN; + delete OK; + delete NOK; +} + +//- class BoxStructure methods----------------------------------------------------------------------------- + +BoxStructure::BoxStructure( void ) +{ + Registry=new List; if(!Registry) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } +} + +//------------------------------------------------------------------------------ + +void BoxStructure::Register( RegularBox far *Box ) +{ + RegistryItem far *Item=new RegistryItem; if(!Item) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + Item->Box=Box; + + Registry->Insert( Item ); +} + +//------------------------------------------------------------------------------ + +BoxStructure::~BoxStructure( void ) +{ + // first delete boxes which are in registry + ListItem far *Item; + + Item=Registry->GetHead(); + + while( Item ) + { + #ifdef DEBUG + printf("\n DeletingBox 0x%Fp type %d", ((RegistryItem far *)Item)->Box, ((RegistryItem far *)Item)->Box->Type ); + ((RegistryItem far *)Item)->Box->Print(); + #endif + + delete ((RegistryItem far *)Item)->Box; + + #ifdef DEBUG + printf("\n Box 0x%Fp deleted", ((RegistryItem far *)Item)->Box); + #endif + + Item=Registry->Next(Item); + } + + // then delete registry + delete Registry; +} + +//- EOF ----------------------------------------------------------------------------- diff --git a/source/box.h b/source/box.h new file mode 100644 index 0000000..6d0811d --- /dev/null +++ b/source/box.h @@ -0,0 +1,86 @@ +#ifndef __BOX_H + #define __BOX_H + + #include "source\hierrors.h" + #include "source\hilist.h" + #include "source\hitypes.h" + + class far _BoxStructure; + + typedef _BoxStructure BoxStructure; + + //- class BoxListItem -------------------------------------------------------- + + class far _BoxListItem : public ListItem + { + public: + + ListSignature List; + void far *Target; // points to box or auto item + + _BoxListItem( void ) { Target=NULL; } + + public: + void Print( void ); + + }; + + typedef _BoxListItem BoxListItem; + + //- class RegularBox -------------------------------------------------------- + + class far _RegularBox + { + public: + + List *IN, // in SWITCH box it is list of pointers to AutoItemID, + // in other cases points to IN List of another box + // it's list because of NDET + *OK, // ... I am jump out of box when ACCEPT + // points to IN List of another box + *NOK; // ... I am jump out of box when END + // points to IN List of another box + + + + ItemType Type; // type of box + + public: + + _RegularBox( ItemType iType, BoxStructure far *Boxes ); + void Print( void ); + ~_RegularBox(); + + }; + + typedef _RegularBox RegularBox; + + //- class RegistryItem -------------------------------------------------------- + + struct far _RegistryItem : public ListItem + { + RegularBox far *Box; + }; + + typedef _RegistryItem RegistryItem; + + //- class BoxStructure -------------------------------------------------------- + + class far _BoxStructure + { + private: + List far *Registry; // for easy delete of box structure + + public: + + _BoxStructure( void ); + ListItem far *GetHead( void ) { return Registry->GetHead(); }; + ListItem far *Next( ListItem far *Item ) { return Registry->Next( Item ); }; + void Register( RegularBox far *Box ); + ~_BoxStructure(); + + }; + + +#endif + diff --git a/source/buffer.cpp b/source/buffer.cpp new file mode 100644 index 0000000..88d0d68 --- /dev/null +++ b/source/buffer.cpp @@ -0,0 +1,627 @@ +#include "source\buffer.h" + +// print info when hunting bugs +// #define DEBUG + +extern bool Verbose; +extern bool OutToStd; +extern bool HTMLOutput; +extern bool CRLF; + +//- class Bufffer methods --------------------------------------------------------------------------------- + +#define ERROR_WHEN_READING \ + { \ + printf("\n ERROR reported from %s line %d:" \ + "\n Error reading from the file...", __FILE__, __LINE__ );\ + exit(0); \ + } + +Buffer::Buffer( char *InputFileName, char *OutputFileName, word BufferSize, bool iUnix ) +{ + + // alloc inner buffers + if( InputFileName!=NULL ) + { + InBuffer=(char far *)farmalloc(BufferSize); + if(!InBuffer) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + } + else + InBuffer=NULL; + + if( OutputFileName!=NULL ) + { + OutBuffer=(char far *)farmalloc(BufferSize); + if(!OutBuffer) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + } + else + OutBuffer=NULL; + + // open file in + // --------------- + // - BINARY MODE - + // --------------- + // so 0xD 0xA => 0xA translation is done + + if( InputFileName!=NULL ) + { + if((InHandle = open( InputFileName, O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1) + { + printf("\n ERROR reported from %s line %d:" + "\n Error opening input file %s...", __FILE__, __LINE__, InputFileName ); + exit(0); + } + } + + // open file in + // --------------- + // - BINARY MODE - + // --------------- + // so 0xD 0xA => 0xA translation is done + + if( OutputFileName!=NULL ) + { + if((OutHandle = open( OutputFileName, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IWRITE | S_IREAD)) == -1) + { + printf("\n ERROR reported from %s line %d:" + "\n Error opening output file %s...", __FILE__, __LINE__, OutputFileName ); + exit(0); + } + } + + Unix=iUnix; + + InBeg + =InPos + =InBufPos + =0; + + BufSize =BufferSize; + InputLng =filelength( InHandle ); + InEnd =BufferSize-1; + + if( (InBufEnd = read( InHandle, InBuffer, BufSize )) == 0xFFFF ) ERROR_WHEN_READING + else + { + if( Verbose ) printf("-"); + } + + #ifdef DEBUG + printf("\n Buffer: loaded interval <%lu,%lu> buf <0,%u>\n", InBeg, InEnd, InBufEnd ); + #endif + + // pointers for output buffer + OutBufPos = 0; + +} + +//-------------------------------------------------------------------------------- + +dword Buffer::GetChar( char &C ) +// - returns 0 if end of file else +// returns how many positions moved in input ( if 0xD0xA returns 2 else 1 ) +// +// - BufPos point to not returned ( counted from 0 ! ) +// - BufSize size of buffer in bytes +// - BufEnd nr of bytes in buffer +{ + + #ifdef DEBUG + printf("\n Buffer: G profile before int <%lu,%lu> buf <0,%u> bufpos %u pos %lu\n", InBeg, InEnd, InBufEnd, InBufPos, InPos ); + #endif + + if( InBufPos >= InBufEnd && InEnd > InputLng ) return FALSE; + + // --- Fault --- + if( InBufPos >= InBufEnd ) // + { + InBeg+=BufSize; + InEnd+=BufSize; + + // InPos =InPos-InBufEnd+BufSize; was changed to ++InPos; + + ++InPos; // move in input file + + if((InBufEnd=read( InHandle, InBuffer, BufSize )) == 0xFFFF ) + return FALSE; // end of file + else + { + if( Verbose ) printf("-"); + } + + #ifdef DEBUG + printf("\n Buffer: G loaded interval <%lu,%lu> buf <0,%u> pos %lu\n", InBeg, InEnd, InBufEnd, InPos ); + #endif + + InBufPos=0; + + C=InBuffer[InBufPos++]; + + if( C==0xD ) // get the second char 0xA->0xD 0xA + { + return GetChar( C )+1lu; // probably 0xA + } + else + return 1lu; + } + else + { + C=InBuffer[InBufPos]; + + InBufPos++; // move to the not returned position in buffer + + if( ++InPos >= InputLng+1 ) return FALSE; // move in file + + if( C==0xD ) // get the second char 0xA->0xD 0xA + { + return GetChar( C )+1lu; // probably 0xA + } + else + return 1lu; + } +} + +//-------------------------------------------------------------------------------- + +void Buffer::PutChar( char C ) +// is used to put whitespaces to output +{ + char CrLf[]={ 13, 10 }; + + + + if( C==0xD && CRLF==FALSE ) // CR, if not wanted jump across, else put ( will not be duplicated ) + return; + + if( CRLF && C==0xA ) + Save( CrLf, 2u ); + else + Save( &C, 1u ); + + +/* + word k; + + OutBuffer[OutBufPos++] = C; + + // check fault of output buffer + if( OutBufPos >= BufSize ) + { + if( OutToStd ) + { + for( k=0; k=To ) // is interval in memory + { + + // alloc memory for element + Ptr = new char[Lenght+1]; + if(!Ptr) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // set pointers + lBegin = From%(dword)BufSize; + Begin = (word)lBegin; + + // copy it to buffer + for( i=Begin, j=0; j load it from file ( leave everything in original pos ) + + // remember position in file to set it after load to original pos + long TellPos=tell( InHandle ); + + // seek to beginning of element in file + lseek( InHandle, (long)From, SEEK_SET); + + // alloc memory for element + Ptr = new char[Lenght+1]; + if(!Ptr) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + if( read( InHandle, Ptr, Lenght ) == -1 ) + { + printf("\n ERROR reported from %s line %d:" + "\n Buffer: fail to load element in interval <%lu,%lu>", __FILE__, __LINE__, From, To ); + exit(0); + } + else + { + if( Verbose ) printf("-"); + } + + // finish string with NULL + Ptr[j]='\0'; + + // set position in file to original position + lseek( InHandle, TellPos, SEEK_SET); + + return HI_OK; + } +} + +//-------------------------------------------------------------------------------- + +word Buffer::Copy( dword From, dword To ) +// copy copies strings from input buffer to output buffer, +// it is input file, in input file I must transform < and others +// to html: < -> < ( if wanted ) +{ + word Lenght = (word)To-(word)From+1, + Begin, + i, + j; + dword lBegin; + char CrLf[]={ 13, 10 }; + + if( InBeg<=From && InEnd>=To ) // is interval in memory + { + // copy it from input buffer to output buffer + + // set pointers + lBegin = From%(dword)BufSize; + Begin = (word)lBegin; + + // copy it to output buffer + for( i=Begin, j=0; j': + Save( ">", 4u ); + break; + case '&': + Save( "&", 5u ); + break; + case '"': + Save( """, 6u ); + break; + default: + if( CRLF && InBuffer[i]==10 ) + Save( CrLf, 2u ); + else + Save( InBuffer+i, 1u ); + break; + } + } + else + { + if( CRLF && InBuffer[i]==10 ) + Save( CrLf, 2u ); + else + Save( InBuffer+i, 1u ); + } + + } + + return HI_OK; + } + else // interval must be loaded + { + // remember position in file to set it after load to original pos + long TellPos=tell( InHandle ); + + // seek to beginning of element in file + lseek( InHandle, (long)From, SEEK_SET); + + + + word FreeInBuffer, + HlpLenght; + + char far *HelpBuffer=(char far *)farmalloc(BufSize); + if(!HelpBuffer) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + + while( Lenght ) + { + FreeInBuffer = BufSize; + + if( Lenght > FreeInBuffer ) + HlpLenght = FreeInBuffer; + else + HlpLenght = Lenght; + + if( read( InHandle, HelpBuffer, HlpLenght ) == -1 ) + { + printf("\n ERROR reported from %s line %d:" + "\n Buffer: fail to load element in interval <%lu,%lu>", __FILE__, __LINE__, From, To ); + exit(0); + } + else + { + if( Verbose ) printf("-"); + } + + + Lenght -= HlpLenght; + + // copy it to output buffer + for( i=0, j=0; j': + Save( ">", 4u ); + break; + case '&': + Save( "&", 5u ); + break; + case '"': + Save( """, 6u ); + break; + default: + if( CRLF && HelpBuffer[i]==10 ) + Save( CrLf, 2u ); + else + Save( HelpBuffer+i, 1u ); + break; + } + } + else + { + if( CRLF && HelpBuffer[i]==10 ) + Save( CrLf, 2u ); + else + Save( HelpBuffer+i, 1u ); + } + } + } // while + + farfree(HelpBuffer); + + + + // set position in file to original position + lseek( InHandle, TellPos, SEEK_SET); + + return HI_OK; + + } // else + +} + +//-------------------------------------------------------------------------------- + +word Buffer::Save( char far *Ptr, word Size ) +// is used to copy inner strings to output +{ + word j, + k; + + if( Ptr==NULL ) return HI_OK; + + // copy it to buffer + for( j=0; j= BufSize ) + { + if( OutToStd ) + { + for( k=0; k InputLng + || + InBufPos >=InBufEnd + ) + { + InPos=InputLng; + return FALSE; + } + + #ifdef DEBUG + printf("\n Buffer: Seek iPos %lu Pos %lu already loaded <%lu,%lu> buf <0,%u> bufpos %u\n", iPos, InPos, InBeg, InEnd, InBufEnd, InBufPos ); + #endif + } + else // else interval must be loaded + { + Where=(iPos/((dword)BufSize))*((dword)BufSize); + + lseek( InHandle, Where, SEEK_SET); + + InBeg =Where; + InPos =iPos; + InBufPos=(word)(iPos%((dword)BufSize)); + InEnd =InBeg+BufSize-1; + + if( (InBufEnd = read( InHandle, InBuffer, BufSize )) == 0xFFFF ) + { + // end of file + InPos=InputLng; + + return FALSE; + } + else + { + if( Verbose ) printf("-"); + } + + + if( InPos > InputLng ) { InputLng=InPos; return FALSE; } + + #ifdef DEBUG + printf("\n Buffer: Seek iPos %lu Pos %lu <%lu,%lu> buf <0,%u> bufpos %u\n", iPos, InPos, InBeg, InEnd, InBufEnd, InBufPos ); + #endif + } + + return TRUE; +} + +//-------------------------------------------------------------------------------- + +dword Buffer::GetPos( void ) +// - Pos points to not returned => return dec +// - position in input file +{ + return InPos-1ul; +} + +//-------------------------------------------------------------------------------- + +Buffer::~Buffer( void ) +{ + word k; + + if( InBuffer ) + { + close( InHandle ); + farfree( InBuffer ); + } + + if( OutBuffer ) + { + // what's inside buffer and not written must be written + if( OutBufPos != 0 ) + { + if( OutToStd ) + { + for( k=0; k 0xA->0xD 0xA to OutBuffer + word Load( dword From, dword To, char far *&Ptr ); + word Copy( dword From, dword To ); // from input buffer to output buffer + word Save( char far *Ptr, word Size ); // copy string to output buffer + bool Seek( dword iPos ); // seek in input file + dword GetPos( void ); + + word Append( dword From, dword To ); // not buffered output + + ~Buffer(); + + private: + char far *InBuffer; + char far *OutBuffer; + + int InHandle, // handle of corresponding file + OutHandle; // handle of output file + + long InputLng; // lng of input file in bytes + + word BufSize; // size of buffer in bytes + + // --- INPUT --- + dword InPos, // Pos in file, points to not returned + InBeg, // begin of interval in file + InEnd; // end of interval in file + + word InBufPos, // position in buffer + InBufEnd; // bytes read to buffer + + // --- OUTPUT --- + word OutBufPos, // position in output buffer + OutBufEnd; // bytes read to buffer + + bool Unix; + }; + +#endif diff --git a/source/cocon.cpp b/source/cocon.cpp new file mode 100644 index 0000000..2da304f --- /dev/null +++ b/source/cocon.cpp @@ -0,0 +1,360 @@ +#include "source/cocon.h" + +// print info when hunting bugs +// #define DEBUG + +#define EXIT_PROGRAM exit(0); + +extern bool HTMLOutput; +extern bool CRLF; + +//- struct StaticTableItem -------------------------------------------------------------------------- + +#define ERROR_WHEN_READING \ + { \ + printf("\n ERROR reported from %s line %d:" \ + "\n Error reading from the file with handle %u...", __FILE__, __LINE__, Handle );\ + EXIT_PROGRAM; \ + } + +void StaticTableItem::Load( int Handle ) +{ + word Lng; + + // DO NOT save ID - its index + + // load Action + if( read( Handle, &Action, 2u ) != 2u ) ERROR_WHEN_READING + + // load RawBeg + if( read( Handle, &Lng, 2u ) != 2u ) ERROR_WHEN_READING + + if( Lng == 0 ) + { + RawBeg = NULL; + } + else + { + RawBeg = new char[Lng]; // space for NULL already included + if(!RawBeg) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + if( read( Handle, RawBeg, Lng ) != Lng ) ERROR_WHEN_READING + } + + // save RawEnd + if( read( Handle, &Lng, 2u ) != 2u ) ERROR_WHEN_READING + + if( Lng == 0 ) + { + RawEnd = NULL; + } + else + { + RawEnd = new char[Lng]; // space for NULL already included + if(!RawEnd) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + if( read( Handle, RawEnd, Lng ) != Lng ) ERROR_WHEN_READING + } + + return; +} + +//---------------------------------------------------------------------------------- + +StaticTableItem::~StaticTableItem( void ) +{ + #ifdef DEBUG + printf("\n Destructor ~StaticTableItem deleting" + "\n RawBeg : %s" + "\n RawEnd : %s" + , + RawBeg, + RawEnd + ); + #endif + + if( RawBeg ) { delete RawBeg; RawBeg=NULL; } + if( RawEnd ) { delete RawEnd; RawEnd=NULL; } +} + +//- class COCONator methods --------------------------------------------------------------------------------- + +COCONator::COCONator( char *FileName ) +// loads table and automat from *.BCA file +{ + Load( FileName ); +} + +//---------------------------------------------------------------------------------- + +void COCONator::Load( char *FileName ) +{ + char Magic[4]; + + #ifdef DEBUG + printf("\n\n Loading coconator %s...", FileName ); + #endif + + int Handle; + word i; + + if( !strstr( FileName, ".bca") ) + { + printf("\n ERROR reported from %s line %d:" + "\n Only BCA files accepted by Coconator ( %s filename not OK )...", __FILE__, __LINE__, FileName ); + EXIT_PROGRAM; + } + + if((Handle = open( FileName, O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1) + { + printf("\n ERROR reported from %s line %d:" + "\n Error opening file \"%s\"...", __FILE__, __LINE__, FileName ); + EXIT_PROGRAM; + } + + // --- load magic --- + + if( read( Handle, Magic, 3u ) != 3u ) ERROR_WHEN_READING + + Magic[3]=0; + + if( !strstr( Magic, "BCA" ) ) + { + printf("\n ERROR reported from %s line %d:" + "\n Only BCA files accepted by Coconator - %s is not...", __FILE__, __LINE__, FileName ); + EXIT_PROGRAM; + } + + // --- load options for translation --- + + if( read( Handle, &HTMLOutput, 1u ) != 1u ) ERROR_WHEN_READING + + if( read( Handle, &CRLF, 1u ) != 1u ) ERROR_WHEN_READING + + // --- load cocon encapsulate mucus --- + + // number of items in table + if( read( Handle, &NrOfItems, 2u ) != 2u ) ERROR_WHEN_READING + + // alloc an array + CoconMucus = new StaticTableItem[ NrOfItems ]; + if(!CoconMucus) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + // load table items self + for( i=0; iPrint(); + + close( Handle ); + +} + +//---------------------------------------------------------------------------------- + +void COCONator::PrintCoconMucus( void ) +{ + #ifdef DEBUG + + word i; + + for( i=0; iSave( CoconMucus[0].RawBeg, strlen(CoconMucus[0].RawBeg) ); + + + + + while( GetHumanoid() ) + { + ; + + #ifdef DEBUG + printf("\n -------> After GetHumanoid <-------"); + #endif + } + + + + // write tail of page + if( CoconMucus[0].RawEnd ) + Buf->Save( CoconMucus[0].RawEnd, strlen(CoconMucus[0].RawEnd) ); + + + + #ifdef DEBUG + printf("\n - COCONIZE END ------------------------------------------------------\n"); + #endif + + return; +} + +//----------------------------------------------------------------------------- + +bool COCONator::GetHumanoid( void ) +// - takes elements from input file +// - input is buffered +// - when the last item is get, buffer is automaticly deleted +{ + + ElementID EleID; + bool Success; + dword SuccChar; + char C; + + #ifdef DEBUG + printf("\n - HUMAN -"); + #endif + + OldBeg=Beg; + + Success=Coconizer->Accept( Buf, Beg, End, (LexicatorType)EleID ); + + if( Success ) + { + #ifdef DEBUG + printf("\n HUMAN Element: Beg %lu End %lu ElementID %u\n", Beg, End, EleID ); + #endif + + + // element successfuly identified -> do the ACTION with it + switch( CoconMucus[EleID].Action ) + { + case ACTION_NO: // means do nothing with element + + Buf->Copy( Beg, End ); // only copy it to output + + break; + + case ACTION_REMOVE: // removing element -> do not copy it to output + + break; + + case ACTION_REPLACE: // replace element with new thing + + if( CoconMucus[EleID].RawBeg ) // raw beg is used as raw + Buf->Save( CoconMucus[EleID].RawBeg, strlen(CoconMucus[EleID].RawBeg) ); + + break; + + case ACTION_ENCAPSULATE: + + // write encapsulated element to the output file ( through buffer ) + + if( CoconMucus[EleID].RawBeg ) + Buf->Save( CoconMucus[EleID].RawBeg, strlen(CoconMucus[EleID].RawBeg) ); + + Buf->Copy( Beg, End ); + + if( CoconMucus[EleID].RawEnd ) + Buf->Save( CoconMucus[EleID].RawEnd, strlen(CoconMucus[EleID].RawEnd) ); + + break; + } + + + OldBeg=Beg=End+1; // move in input + + return TRUE; + + } + else + { + Beg=OldBeg; + Buf->Seek( Beg ); + + SuccChar=Buf->GetChar( C ); + + if( !SuccChar ) + { + #ifdef DEBUG + printf("\n - HUMAN cleaned, no input -"); + #endif + return FALSE; // end of input + } + + // if( IsWhitespace() ) + if( C==' '||C=='\t'||C=='\n' ) // step cross white space which was no accepted + { + #ifdef DEBUG + printf("\n HUMAN WhiteSpace: \'%d\'\n",C); + #endif + + // write whitespace to file + + Buf->PutChar( C ); + + Beg+=SuccChar; // was returned nr of bytes moved across: + // if 10 (\n) inside getchar I jump cross 13 after + + // dive because this is whitespace + return GetHumanoid(); + + } + else + { + #ifdef DEBUG + printf("\n - HUMAN cleaned, not accepted whitespace %c -", C ); + #endif + return FALSE; // end of input + } + } // if success +} + +//- EOF ---------------------------------------------------------------------------- diff --git a/source/cocon.h b/source/cocon.h new file mode 100644 index 0000000..a61a085 --- /dev/null +++ b/source/cocon.h @@ -0,0 +1,72 @@ +#ifndef __COCON_H + #define __COCON_H + + #include "source\hierrors.h" + #include "source\hililex.h" + #include "source\hilist.h" + #include "source\hitypes.h" + #include "source\static.h" + + //- class StaticTableItem -------------------------------------------------------------------------- + + struct far StaticTableItem + { + ActionType Action; + + char far *RawBeg, + *RawEnd; + + public: + + void Load( int Handle ); + ~StaticTableItem( void ); + }; + + //- struct Humanoid -------------------------------------------------------------------------- + + struct far _Humanoid + { + ElementID ID; + dword Beg, + End; + }; + + typedef _Humanoid Humanoid; + + //- class COCONator -------------------------------------------------------------------------- + + class far _COCONator + { + private: + + StaticAutomat far *Coconizer; + + StaticTableItem far *CoconMucus; + + word NrOfItems; + + // for GetHumanoid + Buffer far *Buf; + dword Beg, + End, + OldBeg; + + public: + + _COCONator( char *FileName ); // name of *.BCA file + + void Coconize( char *InFileName, char *OutFileName ); + void PrintCoconMucus( void ); + + ~_COCONator(); + + private: + + void Load( char *FileName ); + bool GetHumanoid( void ); + + }; + + typedef _COCONator COCONator; + +#endif \ No newline at end of file diff --git a/source/dynauto.cpp b/source/dynauto.cpp new file mode 100644 index 0000000..7b6d981 --- /dev/null +++ b/source/dynauto.cpp @@ -0,0 +1,2187 @@ +#include "source\dynauto.h" + +// print info when hunting bugs +// #define DEBUG + +#define EXIT_PROGRAM exit(0); + +#define OPTIMIZE +#define PRINT_OPTIMIZE + +extern bool Verbose; + +//- DynamicJmpTableItem methods --------------------------------------------------- + +void DynaJmpTableItem::Print( void ) +{ + #ifdef DEBUG + + printf("\n DJmpTableItem %Fp: from \'%c\' to \'%c\' jmp %u flags ", this, From, To, JmpTo ); + + // now print flags + if( Flags&JMP_OK ) printf("O"); + if( Flags&JMP_NOK ) printf("N"); + if( Flags&JMP_ACCEPT ) printf("A"); + if( Flags&JMP_END ) printf("E"); + if( Flags&JMP_REST ) printf("R"); + if( Flags&JMP_NOT_SET ) printf("-"); + if( Flags&JMP_ELEMENT_ID ) printf("I"); + if( Flags&JMP_STOP ) printf("S"); + + #endif +} + +//- DynaJmpTable methods --------------------------------------------------- + +DynaJmpTable::DynaJmpTable( char far *Expr ) +{ + Items=new List; if(!Items) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + JumpsAlreadySet=FALSE; // true if jumps already set, + // if true => duplicating corresponding items + + SwitchToDynaJmpTable( Expr ); +} + +//----------------------------------------------------------------------------- + +DynaJmpTable::DynaJmpTable( DynaJmpTableItem far *TableItem ) +// for green ghosts - adds one item from 0 to 255 and JMP_STOP ( already filled ) +{ + Items=new List; if(!Items) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + JumpsAlreadySet=FALSE; // true if jumps already set, + // if true => duplicating corresponding items + + // insert universal item + Items->Insert( TableItem ); +} + +//----------------------------------------------------------------------------- + +word DynaJmpTable::SwitchToDynaJmpTable( char far *Expr ) +// analyze string expression and create JmpTable +// +// accepts and copies switch +// types: +// a 1. +// \a 2. +// \\ 3. +// [...] 4. +// +// wrong input: (a), \\\, ... +{ + DynaJmpTableItem far *TableItem; + word e; + bool FillTo=FALSE, + Neg=FALSE; // false if [...], true if [^...] + + + + switch( Expr[0] ) + { + case '\\': // type 2., type 3. + + /* + input format: + Expr[0]='\\'; + Expr[1]=character; + Expr[2]=0; + */ + + TableItem=new DynaJmpTableItem; if(!TableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + // detect special characters such as \n, \t, ... + switch( Expr[1] ) + { + case 'n': + TableItem->From='\n'; + TableItem->To ='\n'; + break; + case 't': + TableItem->From='\t'; + TableItem->To ='\t'; + break; + default: + TableItem->From=Expr[1]; + TableItem->To =Expr[1]; + break; + } + TableItem->JmpTo=0; + TableItem->Flags= JMP_OK|JMP_NOT_SET; + Items->Insert( TableItem ); + + break; + + case '[': // type 4. ( errors already fixed ) + + /* + input format: + Expr[0]=[; + A-CB-Dghj-z\] + Expr[n]=]; + + so elements have this format: + X + \X + X-X + \X-\X + + -> treat each... + */ + + e=1; // now points behind [ + + // check if it is NEGATION ( type [^...] ) + if( Expr[e]=='^' ) + { + e++; // move behind negation + Neg=TRUE; // set flag + } + else + Neg=FALSE; + + do + { + switch( Expr[e] ) + { + case '\\': // take whats behind + e++; + + if( FillTo ) + { + if( TableItem ) + { + // detect special characters such as \n, \t, ... + switch( Expr[e] ) + { + case 'n': + TableItem->To ='\n'; + break; + case 't': + TableItem->To ='\t'; + break; + default: + TableItem->To =Expr[e]; + + if( TableItem->From > TableItem->To ) + { + printf("\n ERROR reported from %s line %d:" + "\n switch interval %d-%d has no sense ( TO is bigger then FROM )...", __FILE__, __LINE__, TableItem->From, TableItem->To ); + exit(0); + } + + break; + } + FillTo=FALSE; + } + else // TableItem + { + printf("\n ERROR reported from %s line %d:" + "\n Regular switch \"%s\" has not the right format...", __FILE__, __LINE__, Expr ); + EXIT_PROGRAM + } + } + else // FillTo + { + TableItem=new DynaJmpTableItem; if(!TableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + // detect special characters such as \n, \t, ... + switch( Expr[e] ) + { + case 'n': + TableItem->From='\n'; + TableItem->To ='\n'; + break; + case 't': + TableItem->From='\t'; + TableItem->To ='\t'; + break; + default: + TableItem->From=Expr[e]; + TableItem->To =Expr[e]; + + if( TableItem->From > TableItem->To ) + { + printf("\n ERROR reported from %s line %d:" + "\n switch interval %c-%c has no sense ( TO is bigger then FROM )...", __FILE__, __LINE__, TableItem->From, TableItem->To ); + exit(0); + } + break; + } + + TableItem->JmpTo=0; + + if( Neg ) + TableItem->Flags=JMP_NOK|JMP_NOT_SET|JMP_STOP; + else + TableItem->Flags=JMP_OK|JMP_NOT_SET; + + Items->Insert( TableItem ); + } + + break; + + case '-': // valid - ... so fill To of the last TableItem + + FillTo=TRUE; + e++; + + default: + if( FillTo ) + { + if( TableItem ) + { + TableItem->To=Expr[e]; + + if( TableItem->From > TableItem->To ) + { + printf("\n ERROR reported from %s line %d:" + "\n switch interval %c-%c in \"%s\"has no sense ( TO is bigger then FROM )...", __FILE__, __LINE__, TableItem->From, TableItem->To, Expr ); + exit(0); + } + + FillTo=FALSE; + } + else // TableItem + { + printf("\n ERROR reported from %s line %d:" + "\n Regular switch \"%s\" has not the right format...", __FILE__, __LINE__, Expr ); + EXIT_PROGRAM + } + } + else // FillTo + { + TableItem=new DynaJmpTableItem; if(!TableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + TableItem->From =Expr[e]; + TableItem->To =Expr[e]; + TableItem->JmpTo=0; + + if( Neg ) + TableItem->Flags=JMP_NOK|JMP_NOT_SET|JMP_STOP; + else + TableItem->Flags=JMP_OK|JMP_NOT_SET; + + Items->Insert( TableItem ); + } + + break; + + } // switch + } + while( Expr[++e]!=']' ); + + break; + + default: // type 1. + + /* + input format: + Expr[0]=character; + Expr[1]=0; + */ + + TableItem=new DynaJmpTableItem; if(!TableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + // detect special characters such as ., $, ^... + switch( Expr[0] ) + { + case '.': + TableItem->From ='\n'; + TableItem->To ='\n'; + TableItem->Flags=JMP_NOK|JMP_NOT_SET|JMP_STOP; + Neg=TRUE; // rest will be ok + break; + default: + TableItem->From =Expr[0]; + TableItem->To =Expr[0]; + TableItem->Flags= JMP_OK|JMP_NOT_SET; + break; + + } + TableItem->JmpTo=0; + Items->Insert( TableItem ); + + break; + + } // switch + + // fill the last item in table -> REST + TableItem=new DynaJmpTableItem; if(!TableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + TableItem->From=0; + TableItem->To=0; + TableItem->JmpTo=0; + + if( Neg ) + TableItem->Flags= JMP_OK |JMP_REST|JMP_NOT_SET; + else + TableItem->Flags= JMP_NOK|JMP_REST|JMP_NOT_SET|JMP_STOP; + + Items->Insert( TableItem ); + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +void DynaJmpTable::Print( void ) +{ + #ifdef DEBUG + + printf("\n DJmpTable 0x%Fp:", this ); + + ListItem far *Item; + + Item=Items->GetHead(); + + while( Item ) + { + ((DynaJmpTableItem far *)Item)->Print(); + Item=Items->Next(Item); + } + + #endif +} + +//----------------------------------------------------------------------------- + +void DynaJmpTable::Shift( word ShiftNum ) +{ + ListItem far *Item; + + Item=Items->GetHead(); + + while( Item ) + { + if( !(((DynaJmpTableItem far *)Item)->Flags&JMP_ELEMENT_ID) ) + ((DynaJmpTableItem far *)Item)->JmpTo += ShiftNum; + + Item=Items->Next(Item); + } +} + +//----------------------------------------------------------------------------- + +void DynaJmpTable::SetJmpInOKs( AutoItemID ID, ElementID EleID ) +{ + DynaJmpTableItem far *ElementTableItem; + ListItem far *Item; + + Item=Items->GetHead(); + + while( Item ) + { + + if( ((DynaJmpTableItem far *)Item)->Flags & JMP_OK ) + { + // MUST BE SET ACCEPT ---OR--- WHERE TO JUMP ( NEVER BOTH ) + + if( ID==INFINITY ) // set accept + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=0; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags|JMP_ACCEPT; + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->Flags + |= + JMP_ACCEPT; + } + } + else // set where to jump + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=ID; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags; + // ACCEPTED must be cleared ( it would not jump! ) + ElementTableItem->Flags|=JMP_ACCEPT; + ElementTableItem->Flags^=JMP_ACCEPT; + + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->JmpTo + = + ID; + } + } + } + + Item=Items->Next(Item); + } + + // insert items where is element ID if in table is accept + if( ID==INFINITY ) + { + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From=0; + ElementTableItem->To=0; + ElementTableItem->JmpTo=EleID; + ElementTableItem->Flags=JMP_ELEMENT_ID; + Items->InsertBeforeTail( ElementTableItem ); + } + +} + +//----------------------------------------------------------------------------- + +void DynaJmpTable::SetJmpInNOKs( AutoItemID ID ) +{ + DynaJmpTableItem far *ElementTableItem; + ListItem far *Item; + + Item=Items->GetHead(); + + while( Item ) + { + + if( ((DynaJmpTableItem far *)Item)->Flags & JMP_NOK ) + { + // MUST BE SET END ---OR--- WHERE TO JUMP ( NEVER BOTH ) + + if( ID==INFINITY ) // set accept + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=0; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags|JMP_END; + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->Flags + |= + JMP_END; + } + } + else + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=ID; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags; + // ACCEPTED must be cleared ( it would not jump! ) + ElementTableItem->Flags|=JMP_END; + ElementTableItem->Flags^=JMP_END; + + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->JmpTo + = + ID; + } + } + } + + Item=Items->Next(Item); + } +} + +//----------------------------------------------------------------------------- + +void DynaJmpTable::SetJmpInOKsAndMuteToNOKs( AutoItemID ID ) +{ + DynaJmpTableItem far *ElementTableItem; + ListItem far *Item; + + Item=Items->GetHead(); + + while( Item ) + { + + if( ((DynaJmpTableItem far *)Item)->Flags & JMP_OK ) + { + // mute + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_OK; + ((DynaJmpTableItem far *)Item)->Flags |= JMP_NOK; + + // MUST BE SET END ---OR--- WHERE TO JUMP ( NEVER BOTH ) + + if( ID==INFINITY ) // set accept + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=0; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags|JMP_END; + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->Flags + |= + JMP_END; + } + } + else + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=ID; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags; + // ACCEPTED must be cleared ( it would not jump! ) + ElementTableItem->Flags|=JMP_END; + ElementTableItem->Flags^=JMP_END; + + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->JmpTo + = + ID; + } + } + } + + Item=Items->Next(Item); + } +} + +//----------------------------------------------------------------------------- + +void DynaJmpTable::SetJmpInNOKsAndMuteToOKs( AutoItemID ID, ElementID EleID ) +{ + DynaJmpTableItem far *ElementTableItem; + ListItem far *Item; + + Item=Items->GetHead(); + + while( Item ) + { + + if( ((DynaJmpTableItem far *)Item)->Flags & JMP_NOK ) + { + // mute + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOK; + ((DynaJmpTableItem far *)Item)->Flags |= JMP_OK; + + // MUST BE SET ACCEPT ---OR--- WHERE TO JUMP ( NEVER BOTH ) + + if( ID==INFINITY ) // set accept + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=0; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags|JMP_ACCEPT; + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->Flags + |= + JMP_ACCEPT; + } + } + else // set where to jump + { + if( !(((DynaJmpTableItem far *)Item)->Flags & JMP_NOT_SET) ) + { + // if already set duplicate + + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From =((DynaJmpTableItem far *)Item)->From; + ElementTableItem->To =((DynaJmpTableItem far *)Item)->To; + ElementTableItem->JmpTo=ID; + ElementTableItem->Flags=((DynaJmpTableItem far *)Item)->Flags; + // ACCEPTED must be cleared ( it would not jump! ) + ElementTableItem->Flags|=JMP_ACCEPT; + ElementTableItem->Flags^=JMP_ACCEPT; + + Items->InsertAfterHead( ElementTableItem ); + } + else + { + ((DynaJmpTableItem far *)Item)->Flags ^= JMP_NOT_SET; // null + + ((DynaJmpTableItem far *)Item)->JmpTo + = + ID; + } + } + } + + Item=Items->Next(Item); + } + + // insert items where is element ID if in table is accept + // here because of while ( put this item to the end of jmp table ) + if( ID==INFINITY ) + { + ElementTableItem=new DynaJmpTableItem; if(!ElementTableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + ElementTableItem->From=0; + ElementTableItem->To=0; + ElementTableItem->JmpTo=EleID; + ElementTableItem->Flags=JMP_ELEMENT_ID; + Items->InsertBeforeTail( ElementTableItem ); + } + +} + +//----------------------------------------------------------------------------- + +word DynaJmpTable::Save( int Handle, AutoItemID ID ) +{ + ListItem far *Item; + StatJmpTableItem TableItem; + word Step; + + + // save NrOfItems in JmpTable + if( write( Handle, &(Items->NrOfItems), 2u ) != 2u ) + { + printf("\n ERROR reported from %s line %d:" + "\n Error writing to the file...", __FILE__, __LINE__ ); + EXIT_PROGRAM + } + + + + // save JmpTable and shuffle items: + // FROM-TO + // .. + // REST + // .. + // ELEMENT_ID + + // => Go through three times + + for( Step=1; Step<=3; Step++ ) + { + Item=Items->GetHead(); + + while( Item ) + { + + if( + Step==3 + && + (((DynaJmpTableItem far *)Item)->Flags&JMP_ELEMENT_ID) + ) + { + TableItem.From=((DynaJmpTableItem far *)Item)->From; + TableItem.To=((DynaJmpTableItem far *)Item)->To; + TableItem.JmpTo=((DynaJmpTableItem far *)Item)->JmpTo; + TableItem.Flags=((DynaJmpTableItem far *)Item)->Flags; + + if( write( Handle, &TableItem, sizeof(TableItem) ) != sizeof(TableItem) ) + { + printf("\n ERROR reported from %s line %d:" + "\n Error writing to the file...", __FILE__, __LINE__ ); + EXIT_PROGRAM + } + } + else + { + if( + Step==2 + && + (((DynaJmpTableItem far *)Item)->Flags&JMP_REST) + ) + { + TableItem.From=((DynaJmpTableItem far *)Item)->From; + TableItem.To=((DynaJmpTableItem far *)Item)->To; + TableItem.JmpTo=((DynaJmpTableItem far *)Item)->JmpTo; + TableItem.Flags=((DynaJmpTableItem far *)Item)->Flags; + + if( write( Handle, &TableItem, sizeof(TableItem) ) != sizeof(TableItem) ) + { + printf("\n ERROR reported from %s line %d:" + "\n Error writing to the file...", __FILE__, __LINE__ ); + EXIT_PROGRAM + } + } + else + { + if( + Step==1 + && + !(((DynaJmpTableItem far *)Item)->Flags&JMP_REST) + && + !(((DynaJmpTableItem far *)Item)->Flags&JMP_ELEMENT_ID) + ) + { + + TableItem.From=((DynaJmpTableItem far *)Item)->From; + TableItem.To=((DynaJmpTableItem far *)Item)->To; + TableItem.JmpTo=((DynaJmpTableItem far *)Item)->JmpTo; + TableItem.Flags=((DynaJmpTableItem far *)Item)->Flags; + + // OK, STOP and jmp to self has no sense -> loop -> so clear it + if( TableItem.Flags&JMP_OK + && + TableItem.Flags&&JMP_STOP + && + TableItem.JmpTo == ID // jumping to self + ) + { + TableItem.Flags|=JMP_STOP; // clear + TableItem.Flags^=JMP_STOP; + } + + if( write( Handle, &TableItem, sizeof(TableItem) ) != sizeof(TableItem) ) + { + printf("\n ERROR reported from %s line %d:" + "\n Error writing to the file...", __FILE__, __LINE__ ); + EXIT_PROGRAM + } + } + } + } + + + + Item=Items->Next(Item); + } + } // for + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +DynaJmpTable::~DynaJmpTable( void ) +{ + delete Items; +} + +//- DynaAutoItem methods ------------------------------------------------------- + +void DynaAutoItem::Print( void ) +{ + #ifdef DEBUG + printf("\n DAutoItem JmpTable %Fp", JmpTable ); + #endif +} + +//- DynamicAutomat methods ---------------------------------------------------- + +DynamicAutomat::DynamicAutomat( void ) +{ + #ifdef DEBUG + printf("\n\n DynamicAutomat:"); + #endif + + LastID =0; + Items =new List; if(!Items) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Registry =new BoxStructure; if(!Registry) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + InputStates=new List; if(!InputStates) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } +} + +//----------------------------------------------------------------------------- + +DynamicAutomat::~DynamicAutomat( void ) +{ + #ifdef DEBUG + printf("\n ~DynamicAutomat:" + "\n Deleting items and JmpTables" + ); + #endif + + // first delete JmpTables + ListItem far *Item; + + Item=Items->GetHead(); + + while( Item ) + { + #ifdef DEBUG + ((DynaAutoItem far *)Item)->JmpTable->Print(); + #endif + + delete ((DynaAutoItem far *)Item)->JmpTable; + Item=Items->Next(Item); + } + + // then delete Items + delete Items; + + delete InputStates; +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::AddItem( AutoItemID &ID, DynaAutoItem far *&Item ) +{ + Item=new DynaAutoItem; if(!Item) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + ID=Item->ID=LastID++; + + Item->JmpTable=NULL; + + Items->Insert( Item ); + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::StringToDynaAuto( char far *Infix, ElementID ID ) +{ + TempID=ID; + + // convert string in infix to string in prefix + RegularString far *RString=new RegularString( Infix ); if(!RString) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + RString->ToPrefix(); + + // convert string in prefix to tree + RegularTree far *RTree=new RegularTree(); if(!RTree) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + RTree->PrefixToTree( RString->Prefix ); + + delete RString; + + // convert tree to dynamic automat + TreeToDynaAuto( RTree ); + + delete RTree; + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::TreeToDynaAuto( RegularTree far *Tree ) +{ + RegularBox far *ResultInBox=NULL; + + // build box structure together with auto + TreeToDynaAutoLevel( Tree->Root, ResultInBox ); + + // fill "jmp" in jump tables + FillJmpTables( ResultInBox ); + + Print(); + + // delete box structure + delete Registry; + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +void DynamicAutomat::JoinLists( + List far *FromList, + void far *ToBox, + ListSignature ToList + ) +{ + BoxListItem far *BoxItem=new BoxListItem; if(!BoxItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + BoxItem->List =ToList; + BoxItem->Target =ToBox; + + FromList->Insert( BoxItem ); +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::TreeToDynaAutoLevel( RegularNode far *Node, + RegularBox far *&Box + ) +{ + RegularBox far *Box1, + far *Box2, + far *ContinueBox; + + if( Node==NULL ) return NULL; + + // convert self + SubtreeToBox( Node, Box1 ); + Box=Box1; + + // case only node, no continue ( pointer to Box is returned in parameter ) + if( Node->Continue==NULL ) return HI_OK; + + Node=Node->Continue; + + // case two and more nodes + while( Node!=NULL ) + { + SubtreeToBox( Node, Box2 ); + + #ifdef DEBUG + printf("\n\n Tree->Box CONTINUE:"); + #endif + + ContinueBox = new RegularBox( CONTINUE, Registry ); if(!ContinueBox) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // join boxes inside continue box... + // Continue In to Box1 IN + // Box1 OK to Box2 IN + // Box1 NOK to Continue NOK + // Box2 OK to Continue OK + // Box2 NOK to Continue NOK + + JoinLists( ContinueBox->IN, Box1, IN ); + JoinLists( Box1->OK , Box2, IN ); + JoinLists( Box1->NOK , ContinueBox, NOK ); + JoinLists( Box2->OK , ContinueBox, OK ); + JoinLists( Box2->NOK , ContinueBox, NOK ); + + Node=Node->Continue; + Box1=ContinueBox; + } + + Box=ContinueBox; + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::SubtreeToBox( RegularNode far *Node, + RegularBox far *&Box + ) +// first construct son(s) then continue +{ + RegularBox far *LBox, + far *RBox, + far *OldBox, + far *OrBox; + DynaAutoItem far *AutoItem; + AutoItemID ID; + word i; + bool First=TRUE; + + + + if( Node==NULL ) + { + Box=NULL; + return HI_OK; + } + + switch( Node->Type ) + { + case SWITCH: + #ifdef DEBUG + printf("\n\n Tree->Box SWITCH:"); + #endif + + Box = new RegularBox( SWITCH, Registry ); if(!Box) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // add "stav" to automat, + AddItem( ID, AutoItem ); + + // construct jmp table and join it + AutoItem->JmpTable=new DynaJmpTable( Node->Data.Switch.Expr ); if(!(AutoItem->JmpTable)) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // IN point to Item of the automat ( addr of AutoItem ) + JoinLists( Box->IN, AutoItem, NOT_A_LIST ); + + return HI_OK; + + case OR: + #ifdef DEBUG + printf("\n\n Tree->Box OR:"); + #endif + + // first do LSON and RSON, + // then construct OR and continue + OrBox =new RegularBox( OR, Registry ); if(!OrBox) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + TreeToDynaAutoLevel( Node->Data.Or.LeftSon, LBox ); + TreeToDynaAutoLevel( Node->Data.Or.RightSon, RBox ); + + if( LBox==NULL || RBox==NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n OR operation has bad or only one argument...", __FILE__, __LINE__ ); + EXIT_PROGRAM + } + + // join LBox and RBox inside OR box (NDET version)... + // ORBox In to LBox IN (NDET) + // ORBox In to RBox IN (NDET) + // LBox OK to ORBox OK + // LBox NOK stays empty + // RBox OK to ORBox OK + // RBox NOK stays empty + // GREEN ARROW: OrBox IN to OrBox NOK (NDET) + // ( simulates fail inside ) + + JoinLists( OrBox->IN , LBox, IN ); + JoinLists( OrBox->IN , RBox, IN ); + JoinLists( OrBox->IN , OrBox, NOK ); // green arrow + JoinLists( LBox->OK , OrBox, OK ); + JoinLists( RBox->OK , OrBox, OK ); + + Box=OrBox; + + return HI_OK; + + case REPEATER: + #ifdef DEBUG + printf("\n\n Tree->Box REPEATER from %u to %u:", Node->Data.Repeater.From, Node->Data.Repeater.To ); + #endif + + if( Node->Data.Repeater.From == 0 + && + Node->Data.Repeater.From == Node->Data.Repeater.To + ) + { + printf("\n ERROR reported from %s line %d:" + "\n Repeater {0,0} has no sense...", __FILE__, __LINE__ ); + EXIT_PROGRAM + } + + + + // create repeater box + RBox = new RegularBox( REPEATER, Registry ); if(!RBox) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + OldBox=NULL; + + + + // create FROM boxes + for( i=1; i<=Node->Data.Repeater.From; i++ ) + { + TreeToDynaAutoLevel( Node->Data.Repeater.Son, Box ); // create what will be repated + + // fail must point to repeaters NOK not to NULL + JoinLists( Box->NOK , RBox, NOK ); + + if( OldBox ) + { + JoinLists( OldBox->OK , Box, IN ); + } + + OldBox=Box; + + + if( First ) + { + First = FALSE; + JoinLists( RBox->IN, Box, IN ); + } + } // for + + + First=TRUE; // now it means the first inside interval + + + if( Node->Data.Repeater.To==INFINITY ) + { + // create one node and make loop + TreeToDynaAutoLevel( Node->Data.Repeater.Son, Box ); // create what will be repated + + // make loop + JoinLists( Box->OK , Box, IN ); + JoinLists( Box->NOK , RBox, OK ); + + if( OldBox ) // join with previously created boxes + { + JoinLists( OldBox->OK , Box, IN ); + } + else // OldBox==NULL => {0,INF} + { + JoinLists( RBox->IN , Box, IN ); + } + + Box=RBox; + return HI_OK; + } + else // not a loop + { + + // create up to TO boxes + for( ; i<=Node->Data.Repeater.To; i++ ) + { + TreeToDynaAutoLevel( Node->Data.Repeater.Son, Box ); // create what will be repated + + if( OldBox ) + { + JoinLists( OldBox->OK , Box, IN ); + + if( First ) + First=FALSE; + else + JoinLists( OldBox->NOK , RBox, OK ); + } + else // OldBox==NULL + { + // oldbox==NULL => {0,X} + JoinLists( RBox->IN , Box, IN ); + // fail must point to repeaters OK + JoinLists( Box->NOK , RBox, OK ); + } + + OldBox=Box; + } // for + + // now join last box with repeater box + if( OldBox ) + { + JoinLists( OldBox->OK , RBox, OK ); + // if OldBox->NOK is empty => it means END + if( First ) + First=FALSE; + else + JoinLists( OldBox->NOK , RBox, OK ); + + // if {0,X} all NOKs are OK + if( Node->Data.Repeater.From == 0 ) + JoinLists( OldBox->NOK , RBox, OK ); + } + + // if there is more than TO repeatings, the + // rest of automat "to zamitne" + + Box=RBox; + return HI_OK; + } // else not a loop + } + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +struct ResultBagItem : public ListItem +{ + DynaAutoItem far *AutoItem; // pointer to something such as switch + word TypeFlag; + word Flag; +}; + +//----------------------------------------------------------------------------- + +word DynamicAutomat::DiveForSwitch( + BoxListItem far *BLItem, + word &Flag, + word &TypeFlag, + List far *Bag + ) +{ + ResultBagItem far *BagItem; + BoxListItem far *BoxItem; + + + + while( TRUE ) + { + if( BLItem==NULL ) // list is empty => there is any way to continue + { + #ifdef DEBUG + printf("\n IN list empty, result stored and returning ( top )..."); + #endif + + BagItem =new ResultBagItem; if(!BagItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + BagItem->AutoItem= NULL; + BagItem->TypeFlag= TypeFlag; + BagItem->Flag = HI_OK; + Bag->Insert( BagItem ); + + return HI_OK; + } // if + + switch( BLItem->List ) + { + case IN: + BoxItem=(BoxListItem far *)((RegularBox far *)BLItem->Target)->IN->GetHead(); + + if( BoxItem==NULL ) // list empty => there is any way to continue + { + BagItem =new ResultBagItem; if(!BagItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + BagItem->AutoItem= NULL; + BagItem->TypeFlag= TypeFlag; + BagItem->Flag = HI_OK; // OK/NOK podle type flagu + Bag->Insert( BagItem ); + + #ifdef DEBUG + printf("\n IN list empty, result stored and returning..."); + #endif + + return HI_OK; + } + else // work in list + { + #ifdef DEBUG + printf("\n Diving from IN list..."); + #endif + + while( BoxItem ) + { + DiveForSwitch( BoxItem, Flag, TypeFlag, Bag ); // continue in diving + + BoxItem=(BoxListItem far *)((RegularBox far *)BLItem->Target)->IN->Next(BoxItem); + } + } + return HI_OK; + + case NOT_A_LIST: // points to state of automat item => YEA + + // deepest point of recursion => store result to the bag + BagItem =new ResultBagItem; if(!BagItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + BagItem->AutoItem= (DynaAutoItem far *)BLItem->Target; // pointer to automat state + BagItem->TypeFlag= TypeFlag; + BagItem->Flag = HI_OK; + Bag->Insert( BagItem ); + + #ifdef DEBUG + printf("\n Pointing to automat item, result stored as nr. %u and returning...", Bag->NrOfItems ); + #endif + + return HI_OK; + + case OK: + #ifdef DEBUG + printf("\n TypeFlag set to OK and diving..."); + #endif + + TypeFlag=OK; + + BLItem=(BoxListItem far *)((RegularBox far *)BLItem->Target)->OK->GetHead(); + break; + + case NOK: + #ifdef DEBUG + printf("\n TypeFlag set to NOK and diving..."); + #endif + + TypeFlag=NOK; + + BLItem=(BoxListItem far *)((RegularBox far *)BLItem->Target)->NOK->GetHead(); + break; + + default: + printf("\n ERROR reported from %s line %d:" + "\n Diving to unknown list ( not IN, OK, NOK, NOT_A_LIST )...", __FILE__, __LINE__ ); + EXIT_PROGRAM; + + } // switch + } // loop +} + +//----------------------------------------------------------------------------- + +void DynamicAutomat::FinishDiveForOK( BoxListItem far *BLItem, List far *Bag ) +{ + ResultBagItem far *BagItem; + + + + // take each node of Bag + BagItem=(ResultBagItem far *)(Bag->GetHead()); + + while( BagItem ) + { + + if( BagItem->Flag==HI_ACCEPT + || + (BagItem->AutoItem==NULL && BagItem->Flag==HI_OK) + ) + { + + #ifdef DEBUG + printf("\n ->"); + #endif + + // set/mute OKs in jmp table + switch( BagItem->TypeFlag ) + { + case NOK: + #ifdef DEBUG + printf(" mute OKs to NOKs and set END in jmp table"); + #endif + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInOKsAndMuteToNOKs( INFINITY ); + break; + case OK: + #ifdef DEBUG + printf(" set OKs jmps in jmp table to ACCEPT"); + #endif + + // set OK jmps in jmp table to ACCEPT ( does by infinity ) + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInOKs( INFINITY, TempID ); + break; + default: + + // typeflag is initialized to IN, valid values of + // typeflag is OK or NOK, IN means that list is empty + // and because I started from OK list it is accept + + #ifdef DEBUG + printf(" POINTS TO IN -> set OKs in jmp table to ACCEPT"); + #endif + + // set OK jmps in jmp table to ACCEPT ( does by infinity ) + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInOKs( INFINITY, TempID ); + break; + } // switch + } // if + else + { + + #ifdef DEBUG + printf("\n -> OK points to %Fp ID %u", BagItem->AutoItem, BagItem->AutoItem->ID ); + #endif + + // set OKs in jmp table + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInOKs( BagItem->AutoItem->ID ); + + } // else + + BagItem=(ResultBagItem far *)(Bag->Next(BagItem)); + } // while + + +/* + + // take each node of Bag + BagItem=(ResultBagItem far *)(Bag->GetHead()); + + while( BagItem ) + { + + if( BagItem->Flag==HI_ACCEPT + || + (BagItem->AutoItem==NULL && BagItem->Flag==HI_OK) + ) + { + + #ifdef DEBUG + printf("\n -> OK is ACCEPT"); + #endif + + // set ok jmps in jmp table to ACCEPT ( do it by infinity ) + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInOKs( INFINITY, TempID ); + } + else + { + #ifdef DEBUG + printf("\n -> OK points to %Fp ID %u", BagItem->AutoItem, BagItem->AutoItem->ID ); + #endif + + // set OKs in jmp table + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInOKs( BagItem->AutoItem->ID ); + } + + BagItem=(ResultBagItem far *)(Bag->Next(BagItem)); + } // while +*/ + +} + +//----------------------------------------------------------------------------- + +void DynamicAutomat::FinishDiveForNOK( BoxListItem far *BLItem, List far *Bag ) +{ + ResultBagItem far *BagItem; + + + + // take each node of Bag + BagItem=(ResultBagItem far *)(Bag->GetHead()); + + while( BagItem ) + { + + if( BagItem->Flag==HI_ACCEPT + || + (BagItem->AutoItem==NULL && BagItem->Flag==HI_OK) + ) + { + #ifdef DEBUG + printf("\n ->"); + #endif + + // set/mute NOKs in jmp table + switch( BagItem->TypeFlag ) + { + case OK: + #ifdef DEBUG + printf(" mute NOKs to OKs and set ACCEPT in jmp table"); + #endif + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInNOKsAndMuteToOKs( INFINITY, TempID ); + break; + case NOK: + #ifdef DEBUG + printf(" set NOKs jmps in jmp table to END"); + #endif + + // set NOK jmps in jmp table to END ( does by infinity ) + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInNOKs( INFINITY ); + break; + default: + + // typeflag is initialized to IN, valid values of + // typeflag is OK or NOK, IN means that list is empty + // and because I started from NOK list its end + + #ifdef DEBUG + printf(" POINTS TO IN -> set NOKs in jmp table to END"); + #endif + + // set NOK jmps in jmp table to END ( does by infinity ) + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInNOKs( INFINITY ); + break; + } // switch + } // if + else + { + #ifdef DEBUG + printf("\n -> NOK points to %Fp ID %u", BagItem->AutoItem, BagItem->AutoItem->ID ); + #endif + + // set/mute NOKs in jmp table + switch( BagItem->TypeFlag ) + { + case OK: + #ifdef DEBUG + printf(" SET JMP && MUTE (OK)"); + #endif + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInNOKsAndMuteToOKs( BagItem->AutoItem->ID ); + break; + case NOK: + #ifdef DEBUG + printf(" SET JMP (NOK)"); + #endif + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInNOKs( BagItem->AutoItem->ID ); + break; + default: + #ifdef DEBUG + printf(" SET JMP && MUTE (IN)"); + #endif + ((DynaAutoItem far *)(BLItem->Target))->JmpTable->SetJmpInNOKsAndMuteToOKs( BagItem->AutoItem->ID ); + break; + } // switch + } // else + + BagItem=(ResultBagItem far *)(Bag->Next(BagItem)); + } // while +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::ProcessSwitch( RegularBox far *SwitchBox ) +// - TypeFlag contains OK or NOK. Is set by last list I go through +// - flag contains HI_OK ... normal return +// HI_ACCEPT ... nejvnejsnejsi box && a jsem v listu OK +{ + BoxListItem far *BLItem, + far *BoxItem; + List far *Bag=new List; if(!Bag) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + word Flag, + TypeFlag; // type of list OK/NOK i go through last ( IN list ignored ) + + + + if( SwitchBox==NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n Input box is null...", __FILE__, __LINE__ ); + delete Bag; + EXIT_PROGRAM + } + else + BLItem = (BoxListItem far *)(SwitchBox->IN->GetHead()); + + + + // check if it is really switch + if( BLItem->List != NOT_A_LIST ) + { + printf("\n ERROR reported from %s line %d:" + "\n Target is not auto item...", __FILE__, __LINE__ ); + delete Bag; + EXIT_PROGRAM + } + #ifdef DEBUG + else + printf("\n Processing switch with ID %u:", ((DynaAutoItem far *)(BLItem->Target))->ID ); + #endif + + + // --- Dive from OK list --- + #ifdef DEBUG + printf("\n OK LIST will be done..."); + #endif + + #define MAKE_OK_LIST \ + TypeFlag=IN; \ + \ + DiveForSwitch( BoxItem, \ + Flag, \ + TypeFlag, \ + Bag \ + ); \ + \ + FinishDiveForOK( BLItem, Bag ); + + if( (BoxItem = (BoxListItem far *)(SwitchBox->OK->GetHead())) == NULL ) + { + MAKE_OK_LIST + } + else + { + while( BoxItem ) + { + MAKE_OK_LIST + + Bag->Destroy(); + + BoxItem = (BoxListItem far *)(SwitchBox->OK->Next(BoxItem)); + } + } + + + + // --- Dive from NOK list --- + + #ifdef DEBUG + printf("\n NOK LIST will be done..."); + #endif + + // typeflag is initialized to IN, valid values of + // typeflag is OK or NOK, IN means that list is empty ( was set nowhere ) + + #define MAKE_NOK_LIST \ + TypeFlag=IN; \ + \ + DiveForSwitch( BoxItem, \ + Flag, \ + TypeFlag, \ + Bag \ + ); \ + \ + FinishDiveForNOK( BLItem, Bag ); + + if( (BoxItem = (BoxListItem far *)(SwitchBox->NOK->GetHead())) == NULL ) + { + MAKE_NOK_LIST + } + else + { + while( BoxItem ) + { + MAKE_NOK_LIST + + BoxItem = (BoxListItem far *)(SwitchBox->NOK->Next(BoxItem)); + } + } + + delete Bag; + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::FillJmpTables( RegularBox far *Box ) +// Rekurzivni pruchod, cil je propojit vystup ze switche s dalsim switchem, +// tj. dat tam adresu stavu na ktery ukazuje. +// Vezmu tedy stav, najdu kam ukazuje a tak dale... +// Jakmile, zjistim kam ukazuje, uz tam dam primo cislo => tim se budou rusit +// cykly +{ + List far *Bag =new List; if(!Bag) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + word TypeFlag =IN, + Flag =HI_OK; + + #ifdef DEBUG + printf("\n\n FIND INPUT STATES OF AUTOMAT:"); + #endif + + // --- Find input state of automat --- + ResultBagItem far *BagItem; + BoxListItem far *BoxItem; + InputStatesItem far *Input; + + BoxItem=(BoxListItem far *)(Box->IN->GetHead()); + + while( BoxItem ) + { + + DiveForSwitch( BoxItem, + Flag, + TypeFlag, + Bag + ); + + // work on bag + BagItem = (ResultBagItem far *)Bag->GetHead(); + + while( BagItem ) + { + if( BagItem->AutoItem == NULL ) + { + #ifdef DEBUG + printf("\n No switch on the way - GREEN ARROW WORK" ); + #endif + + + } + else + { + // add it to List of input states + Input = new InputStatesItem; if(!Input) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Input->AutoItem =BagItem->AutoItem; + InputStates->Insert( Input ); + + #ifdef DEBUG + printf("\n Input state of automat %Fp, ID is %u ", BagItem->AutoItem, BagItem->AutoItem->ID ); + #endif + } + + BagItem=(ResultBagItem far *)Bag->Next(BagItem); + } + + Bag->Destroy(); + + BoxItem=(BoxListItem far *)(Box->IN->Next(BoxItem)); + } + + delete Bag; + + // --- Now go through registry and fill each Jmp table --- + + #ifdef DEBUG + printf("\n\n FILL JMP TABLES:"); + #endif + + ListItem far *Item; + + Item=Registry->GetHead(); + + while( Item ) + { + #ifdef DEBUG + printf("\n\n Processing Box 0x%Fp type %d", ((RegistryItem far *)Item)->Box, ((RegistryItem far *)Item)->Box->Type ); + #endif + + switch( ((RegistryItem far *)Item)->Box->Type ) + { + case SWITCH: + #ifdef DEBUG + printf(" -> it's SWITCH"); + #endif + + ProcessSwitch( ((RegistryItem far *)Item)->Box ); + + break; + default: + #ifdef DEBUG + printf(" -> it's not interesting"); + #endif + ; + } + + Item=Registry->Next(Item); + } + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::Wampirator( DynamicAutomat &Blood ) +// - vysaje jiny automat +{ + ListItem far *ItHead, + far *ItTail, + far *InHead, + far *InTail; + ListItem far *Item; + word NrOfItems, + ItItems, + InItems; + + + // move items to me and shift jmp tables + Blood.Cut( ItHead, ItTail, ItItems, InHead, InTail, InItems ); + NrOfItems=GetNrOfItems(); + + + + // --- states of automat --- + Item=ItHead; + + while( Item ) + { + ((DynaAutoItem far *)Item)->JmpTable->Shift( NrOfItems ); + ((DynaAutoItem far *)Item)->ID += NrOfItems; + + Item=Item->Next; + } + + Items->Paste( ItHead, ItTail, ItItems ); + + + + // --- move input states to me --- + InputStates->Paste( InHead, InTail, InItems ); + // += not needed because from input list I points directly to Items list + // where IDs were already changed + + // --- change last ID --- + LastID+=Blood.GetNrOfItems(); + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +word DynamicAutomat::Cut( ListItem far *&ItHead, ListItem far *&ItTail, word &ItItems, + ListItem far *&InHead, ListItem far *&InTail, word &InItems ) +{ + ItHead=Items->GetHead(); + ItTail=Items->GetTail(); + ItItems=Items->NrOfItems; + Items->LeaveContent(); + + InHead=InputStates->GetHead(); + InTail=InputStates->GetTail(); + InItems=InputStates->NrOfItems; + InputStates->LeaveContent(); + + // make pointers OK ( used in Wampirator ) + ItHead->Last=ItTail->Next=InHead->Last=InTail->Next = NULL; + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +void DynamicAutomat::Print( void ) +{ + ListItem far *Item; + + #ifdef DEBUG + printf("\n\n - DYNA PRINT ------------------------------------------------------------" + "\n DynamicAutomat profile:" + "\n NrOfStates: %u" + "\n NrOfInputStates: %u" + "\n ListOfInputStates:" + , + LastID, + InputStates->NrOfItems + ); + #endif + + // InputStates + Item=InputStates->GetHead(); + + while( Item ) + { + #ifdef DEBUG + printf(" %u", ((InputStatesItem far *)Item)->AutoItem->ID ); + #endif + + Item=InputStates->Next(Item); + } + + // States + Item=Items->GetHead(); + + while( Item ) + { + #ifdef DEBUG + printf("\n State %u:", ((DynaAutoItem far *)Item)->ID ); + ((DynaAutoItem far *)Item)->JmpTable->Print(); + #endif + Item=Items->Next(Item); + } + + #ifdef DEBUG + printf("\n - DYNA PRINT ------------------------------------------------------------\n"); + #endif +} + +//---------------------------------------------------------------------------------- + +#define ERROR_WHEN_WRITING \ + { \ + printf("\n ERROR reported from %s line %d:" \ + "\n Error writing to the file \"%s\"...", __FILE__, __LINE__, FileName );\ + EXIT_PROGRAM \ + } + +word DynamicAutomat::Save( char *FileName ) +{ + // before save OPTIMIZE AUTOMAT + #ifdef OPTIMIZE + ReduceNrOfInputStates(); + #endif + + + + #ifdef DEBUG + printf("\n\n Saving automat %Fp to file %s...", this, FileName ); + #endif + + ListItem far *Item; + int Handle; + + if((Handle = open( FileName, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, + S_IREAD | S_IWRITE)) == -1) + { + printf("\n ERROR reported from %s line %d:" + "\n Error opening file \"%s\"...", __FILE__, __LINE__, FileName ); + EXIT_PROGRAM + } + + + // NrOfStates + if( write( Handle, &LastID, 2u ) != 2u ) ERROR_WHEN_WRITING + // NrOfStates of input states + if( write( Handle, &(InputStates->NrOfItems), 2u ) != 2u ) ERROR_WHEN_WRITING + // input states self + Item=InputStates->GetHead(); + while( Item ) + { + if( write( Handle, &(((InputStatesItem far *)Item)->AutoItem->ID), 2u ) != 2u ) ERROR_WHEN_WRITING + Item=InputStates->Next(Item); + } + // states self + Item=Items->GetHead(); + while( Item ) + { + // save jmp table + ((DynaAutoItem far *)Item)->JmpTable->Save(Handle, ((DynaAutoItem far *)Item)->ID ); + Item=Items->Next(Item); + } + + close( Handle ); + + return HI_OK; +} + +//---------------------------------------------------------------------------------- + +#define ERROR_WHEN_APPENDING \ + { \ + printf("\n ERROR reported from %s line %d:" \ + "\n Error writing to the file with handle %d...", __FILE__, __LINE__, Handle );\ + EXIT_PROGRAM \ + } + +word DynamicAutomat::Append( int Handle ) +{ + // before save OPTIMIZE AUTOMAT + #ifdef OPTIMIZE + #ifdef PRINT_OPTIMIZE + if( Verbose ) printf("(%u",InputStates->NrOfItems); + #endif + ReduceNrOfInputStates(); + #ifdef PRINT_OPTIMIZE + if( Verbose ) printf("/%u)",InputStates->NrOfItems); + #endif + #endif + + + + #ifdef DEBUG + printf("\n\n Appending automat %Fp to file with handle %d...", this, Handle ); + #endif + + ListItem far *Item; + + // NrOfStates + if( write( Handle, &LastID, 2u ) != 2u ) ERROR_WHEN_APPENDING + // NrOfStates of input states + if( write( Handle, &(InputStates->NrOfItems), 2u ) != 2u ) ERROR_WHEN_APPENDING + // input states self + Item=InputStates->GetHead(); + while( Item ) + { + if( write( Handle, &(((InputStatesItem far *)Item)->AutoItem->ID), 2u ) != 2u ) ERROR_WHEN_APPENDING + Item=InputStates->Next(Item); + } + // states self + Item=Items->GetHead(); + while( Item ) + { + // save jmp table + ((DynaAutoItem far *)Item)->JmpTable->Save(Handle, ((DynaAutoItem far *)Item)->ID ); + Item=Items->Next(Item); + } + + return HI_OK; +} + +//---------------------------------------------------------------------------------- +word DynamicAutomat::RdcAreSame( DynaAutoItem far *State1, + DynaAutoItem far *State2 + ) +// each jmp table: + +// -if has 2 items +// the first item must have only these flags: O +// the second item must have only these flags: NERS +// both tables must have the same from-to in the first item +// => returns 1 +// +// -if has 3 items +// the first item must have only these flags: O +// the second item must have only these flags: O +// the third item must have only these flags: NERS +// both tables must have the same from-to in the first and the second item +// => returns 2 +// +// => if tables not same returns 0 +{ + DynaJmpTableItem far *ItemsState1, + far *ItemsState2; + + + // --- CASE 1 --- + + if( State1->JmpTable->Items->NrOfItems == 2 + && + State2->JmpTable->Items->NrOfItems == 2 + ) + { + byte Item1Flags = JMP_OK, + Item2Flags = JMP_NOK|JMP_END|JMP_REST|JMP_STOP; + + + ItemsState1 = (DynaJmpTableItem far *)(State1->JmpTable->Items->GetHead()); + ItemsState2 = (DynaJmpTableItem far *)(State2->JmpTable->Items->GetHead()); + + if( ItemsState1->Flags == Item1Flags + && + ItemsState2->Flags == Item1Flags + && + ItemsState1->From == ItemsState2->From + && + ItemsState1->To == ItemsState2->To + ) + { + + ItemsState1 = (DynaJmpTableItem far *)State1->JmpTable->Items->Next(ItemsState1); + ItemsState2 = (DynaJmpTableItem far *)State2->JmpTable->Items->Next(ItemsState2); + + if( ItemsState1->Flags == Item2Flags + && + ItemsState2->Flags == Item2Flags + ) + { + #ifdef DEBUG + printf("\n RdcAreSame: states %u and %u are same - case 1...", State1->ID, State2->ID ); + #endif + + return TRUE; + } + } + } + + // --- CASE 2 --- + + if( State1->JmpTable->Items->NrOfItems == 3 + && + State2->JmpTable->Items->NrOfItems == 3 + ) + { + byte Item1Flags = JMP_OK, + Item2Flags = JMP_OK, + Item3Flags = JMP_NOK|JMP_END|JMP_REST|JMP_STOP; + + + ItemsState1 = (DynaJmpTableItem far *)(State1->JmpTable->Items->GetHead()); + ItemsState2 = (DynaJmpTableItem far *)(State2->JmpTable->Items->GetHead()); + + if( ItemsState1->Flags == Item1Flags + && + ItemsState2->Flags == Item1Flags + && + ItemsState1->From == ItemsState2->From + && + ItemsState1->To == ItemsState2->To + ) + { + + ItemsState1 = (DynaJmpTableItem far *)State1->JmpTable->Items->Next(ItemsState1); + ItemsState2 = (DynaJmpTableItem far *)State2->JmpTable->Items->Next(ItemsState2); + + if( ItemsState1->Flags == Item2Flags + && + ItemsState2->Flags == Item2Flags + ) + { + + ItemsState1 = (DynaJmpTableItem far *)State1->JmpTable->Items->Next(ItemsState1); + ItemsState2 = (DynaJmpTableItem far *)State2->JmpTable->Items->Next(ItemsState2); + + if( ItemsState1->Flags == Item3Flags + && + ItemsState2->Flags == Item3Flags + ) + { + #ifdef DEBUG + printf("\n RdcAreSame: states %u and %u are same - case 2...", State1->ID, State2->ID ); + #endif + + return TRUE+TRUE; + } + } + } + } + + return FALSE; +} + +//---------------------------------------------------------------------------------- + +void DynamicAutomat::ReduceNrOfInputStates( void ) +// optimizing automat: +// reducing number of input states +// +// STEP1 +// joins these tables: +// JMP_OK, +// JMP_NOK|JMP_END|JMP_REST|JMP_NOT_SET|JMP_STOP; +{ + #ifdef DEBUG + printf("\n\n - AUTO OPTIMIZER BEFORE ----------------------------------------------------"); + Print(); + #endif + + // InputStates + InputStatesItem far *InputState=(InputStatesItem far *)InputStates->GetHead(); + InputStatesItem far *State, + far *StateBackup; + DynaJmpTableItem far *TableItem; + List far *Brothers=new List; if(!Brothers) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + + while( InputState ) + { + #ifdef DEBUG + printf("\n\n Searching brother for ID %u...", InputState->AutoItem->ID ); + #endif + + + + // search brothers ONLY between input states + State=(InputStatesItem far *)InputStates->GetHead();; + + while( State ) + { + + if( InputState != State ) + { + if( RdcAreSame( InputState->AutoItem, State->AutoItem ) ) + { + // move state from input states list to brothers list + StateBackup=State; + State =(InputStatesItem far *)InputStates->Next(State); + + InputStates->Get( StateBackup ); // taken out of list but not deleted + #ifdef DEBUG + printf("\n RdcInputStates: input state %u removed...", StateBackup->AutoItem->ID ); + #endif + + // move state to brother list + Brothers->Insert( StateBackup ); + + continue; + } + } + + State=(InputStatesItem far *)InputStates->Next(State); + } + + // if there are some brothers + if( !(Brothers->Empty()) ) + { + // join brothers to the first jmp table, delete not used jmp table + // and put there ghost jmp table + + State=(InputStatesItem far *)Brothers->GetHead();; + + while( State ) + { + // take item + TableItem = (DynaJmpTableItem far *)State->AutoItem->JmpTable->Items->GetHead(); + // move table item to the new place ( the rest of table leave as is ) + State->AutoItem->JmpTable->Items->Get(TableItem); + // insert table item to the new position + InputState->AutoItem->JmpTable->Items->InsertAfterHead( TableItem ); + + // if same == TRUE+TRUE do the same thing again ( 2 because I get 1 item in previous lines ) + if( State->AutoItem->JmpTable->Items->NrOfItems == 2 ) + { + // take item + TableItem = (DynaJmpTableItem far *)State->AutoItem->JmpTable->Items->GetHead(); + // move table item to the new place ( the rest of table leave as is ) + State->AutoItem->JmpTable->Items->Get(TableItem); + // insert table item to the new position + InputState->AutoItem->JmpTable->Items->InsertAfterHead( TableItem ); + } + + // take the next state + State=(InputStatesItem far *)Brothers->Next(State);; + } + + // make brothers list empty + Brothers->Destroy(); + + } + + // work on the next input state + InputState=(InputStatesItem far *)InputStates->Next(InputState); + } + + #ifdef DEBUG + printf("\n\n - AUTO OPTIMIZER AFTER ----------------------------------------------------"); + Print(); + #endif + + delete Brothers; +} + +//- EOF ---------------------------------------------------------------------------- + diff --git a/source/dynauto.h b/source/dynauto.h new file mode 100644 index 0000000..ad5d5da --- /dev/null +++ b/source/dynauto.h @@ -0,0 +1,151 @@ +#ifndef __DYNAUTO_H + #define __DYNAUTO_H + + #include "io.h" + #include "fcntl.h" + #include "sys\stat.h" + #include "source\box.h" + #include "source\hierrors.h" + #include "source\hilist.h" + #include "source\hitypes.h" + #include "source\prefix.h" + #include "source\regtree.h" + #include "source\static.h" + + //- struct InBagItem --------------------------------------------------------------- + + struct far InBagItem : public ListItem + { + RegularBox far *Box; + }; + + //- class DynaJmpTableItem -------------------------------------------------------- + + //- JmpTableItemFlags - + #define JMP_OK 1 + #define JMP_NOK 2 + #define JMP_ACCEPT 4 + #define JMP_END 8 + #define JMP_REST 16 + #define JMP_NOT_SET 32 + #define JMP_ELEMENT_ID 64 + #define JMP_STOP 128 + + class far DynaJmpTableItem : public ListItem + { + public: + char From, + To; + + AutoItemID JmpTo; // USED FOR ELEMENT ID IF FLAF IS SET + + byte Flags; + + public: + DynaJmpTableItem(void ) { From=To=JmpTo=Flags=0; }; + void Print( void ); + virtual ~DynaJmpTableItem() {}; + + }; + + //- class DynaJmpTable -------------------------------------------------------- + + class far DynaJmpTable + { + public: + List far *Items; + bool JumpsAlreadySet; + + public: + + DynaJmpTable( char far *Expr ); + DynaJmpTable( DynaJmpTableItem far *TableItem ); // for green ghosts + word AddItem( DynaJmpTableItem far *Item ); + void SetJmpInOKs( AutoItemID ID, ElementID EleID=0 ); + void SetJmpInNOKs( AutoItemID ID ); + void SetJmpInOKsAndMuteToNOKs( AutoItemID ID ); + void SetJmpInNOKsAndMuteToOKs( AutoItemID ID, ElementID EleID=0 ); + void Print( void ); + void Shift( word ShiftNum ); + word Save( int Handle, AutoItemID ID ); + ~DynaJmpTable( void ); + + private: + word SwitchToDynaJmpTable( char far *Expr ); + }; + + //- class DynaAutoItem -------------------------------------------------------- + + class far _DynaAutoItem : public ListItem + { + public: + + DynaJmpTable far *JmpTable; + AutoItemID ID; + + public: + + void Print( void ); + }; + + typedef _DynaAutoItem DynaAutoItem; + + //- class DynamicAutomat -------------------------------------------------------- + + class far _DynamicAutomat + { + private: + + AutoItemID LastID; // points to the first free item + List far *Items; + BoxStructure far *Registry; // for easy delete of box structure + List far *InputStates; // list of inuput states (NDET) + ElementID TempID; + + public: + + _DynamicAutomat( void ); + word AddItem( AutoItemID &ID, DynaAutoItem far *&Item ); + word StringToDynaAuto( char far *Infix, ElementID ID ); + word TreeToDynaAuto( RegularTree far *Tree ); + word GetNrOfItems( void ) { return LastID; }; + word Wampirator( _DynamicAutomat &Blood ); + word Cut( ListItem far *&ItHead, ListItem far *&ItTail, word &ItItems, + ListItem far *&InHead, ListItem far *&InTail, word &InItems ); + void Print( void ); + word Save( char *FileName ); + word Append( int Handle ); + ~_DynamicAutomat(); + + private: + + void JoinLists( List far *FromList, void far *ToBox, ListSignature ToList ); + word TreeToDynaAutoLevel( RegularNode far *Node, RegularBox *&Box ); + word SubtreeToBox( RegularNode far *Node, RegularBox far *&CreatedBox ); + word FillJmpTables( RegularBox far *Box ); + word DiveForSwitch( BoxListItem far *BLItem, + word &Flag, + word &TypeFlag, + List far *Bag + ); + void FinishDiveForOK ( BoxListItem far *BLItem, List far *Bag ); + void FinishDiveForNOK( BoxListItem far *BLItem, List far *Bag ); + word ProcessSwitch( RegularBox far *SwitchBox ); + + void ReduceNrOfInputStates( void ); + word RdcAreSame( DynaAutoItem far *State1, DynaAutoItem far *State2 ); + + + }; + + typedef _DynamicAutomat DynamicAutomat; + + //- struct InputStatesItem -------------------------------------------------------- + + struct far InputStatesItem : public ListItem + { + DynaAutoItem far *AutoItem; + }; + +#endif + diff --git a/source/hierrors.h b/source/hierrors.h new file mode 100644 index 0000000..ef9a700 --- /dev/null +++ b/source/hierrors.h @@ -0,0 +1,10 @@ +#ifndef __HIERRORS_H + #define __HIERRORS_H + + #define HI_OK 0 + #define HI_ERROR 1 + + #define HI_ACCEPT 0xA + #define HI_END 0xE + +#endif diff --git a/source/hililex.cpp b/source/hililex.cpp new file mode 100644 index 0000000..9a0f65d --- /dev/null +++ b/source/hililex.cpp @@ -0,0 +1,441 @@ +#include "source\hililex.h" + +// print info when hunting bugs +// #define DEBUG + +//----------------------------------------------------------------------------- + +bool IsWhiteSpace( char C ) +{ + + switch( C ) + { + case ' ': + case '\t': + case '\n': + return TRUE; + default: + return FALSE; + } + +} + +//- class Lexicator methods -------------------------------------------------------- + +Lexicator::Lexicator( void ) +{ + Correct = TRUE; + + ConstructBuildInHiliLex(); +} + +//----------------------------------------------------------------------------- + +word Lexicator::SniftSnift( char *InFileName, char *OutFileName ) +{ + Buffer far *Buf=new Buffer( InFileName, OutFileName, 10000u ); if(!Buf) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + dword Beg=0, + End, + OldBeg=0; + + ElementID EleID; + bool Success; + char C; + + #ifdef DEBUG + printf("\n\n - Snifter ----------------------------------------------------\n"); + #endif + + for(;;) + { + OldBeg=Beg; + + Success=Akceptor->Accept( Buf, Beg, End, (LexicatorType)EleID ); + + if( Success ) + { + #ifdef DEBUG + printf("\n Element: Beg %lu End %lu ElementID %u\n", Beg, End, EleID ); + #endif + + OldBeg=Beg=End+1; + Buf->Append( Beg, End ); + + continue; + } + else + { + Beg=OldBeg; + Buf->Seek( Beg ); + + Success=Buf->GetChar( C ); + + if( !Success ) + { + delete Buf; + #ifdef DEBUG + printf("\n - Snifter ----------------------------------------------------"); + #endif + return HI_OK; // end of input + } + + if( IsWhiteSpace(C) ) // step cross white space which was no accepted + { + #ifdef DEBUG + printf("\n WhiteSpace: \'%d\'\n",C); + #endif + + Beg++; + } + else + { + delete Buf; + #ifdef DEBUG + printf("\n\n - Snifter ----------------------------------------------------"); + #endif + return HI_OK; // end of input + } + } // if success + } +} + +//----------------------------------------------------------------------------- + +Lexicator::~Lexicator( void ) +{ + delete Akceptor; +} + +//----------------------------------------------------------------------------- + +void Lexicator::PrepareForPop( char *InFileName ) +{ + Buf=new Buffer( InFileName, NULL, 10000u ); // output buffer not used + if(!Buf) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Beg=0; + OldBeg=0; +} + +//----------------------------------------------------------------------------- + +void Lexicator::CancelPop( void ) +{ + delete Buf; +} + +//----------------------------------------------------------------------------- + +bool Lexicator::Pop( SyntactNode *&Element ) +// - takes elements from input file +// - input is buffered +// - lex element "COMMENTS" is ignored -> so not returned +// - when the last item is get, buffer is automaticly deleted +{ + + ElementID EleID; + bool Success; + char C; + + #ifdef DEBUG + printf("\n - POP -"); + #endif + + OldBeg=Beg; + + Success=Akceptor->Accept( Buf, Beg, End, (LexicatorType)EleID ); + + if( Success ) + { + #ifdef DEBUG + printf("\n POP Element: Beg %lu End %lu ElementID %u\n", Beg, End, EleID ); + #endif + + // create node and return it's adress + + switch( EleID ) + { + case LEXICATOR_LBRACE: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_LBRACE; + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_RBRACE: + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_RBRACE; + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_SEMICOLON: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_SEMICOLON; + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_DESCR: // keywords + case LEXICATOR_ACTION: + case LEXICATOR_RAW: + case LEXICATOR_RAWBEG: + case LEXICATOR_RAWEND: + case LEXICATOR_FONT: + case LEXICATOR_SIZE: + case LEXICATOR_COLOR: + case LEXICATOR_UNDERSCORE: + case LEXICATOR_ITALIC: + case LEXICATOR_BOLD: + case LEXICATOR_OUTPUT: + case LEXICATOR_TITLE: + case LEXICATOR_FACEFONT: + case LEXICATOR_BASECOLOR: + case LEXICATOR_BASESIZE: + case LEXICATOR_BGCOLOR: + case LEXICATOR_BACKGROUND: + case LEXICATOR_WIDTH: + case LEXICATOR_INTABLE: + case LEXICATOR_OUTTABLE: + case LEXICATOR_CRLF: + case LEXICATOR_HTMLOUTPUT: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_k; + Element->Data.k.Key =(TokenType)EleID; // HAS THE SAME INT VALUE as returned from automat + // see hitypes.h + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_EQU: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_EQU; + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_STRING: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_s; + Element->Data.s.Beg =Beg; + Element->Data.s.End =End; + // load element + Buf->Load( Beg, End, Element->Data.s.Element ); + Element->Data.s.ID =EleID; + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_COMMENTS: + // dive for valid element -> comments are ignored + OldBeg=Beg=End+1; + return Pop( Element ); + + case LEXICATOR_LPARENT: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_LPARENT; + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_RPARENT: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_RPARENT; + OldBeg=Beg=End+1; + return TRUE; + + case LEXICATOR_ELEMENT: // head keywords + case LEXICATOR_SETUP: + + Element=new SyntactNode; if(!Element) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Element->Type =SNODE_h; + Element->Data.h.Key =(TokenType)EleID; // HAS THE SAME INT VALUE + // see hitypes.h + OldBeg=Beg=End+1; + return TRUE; + + default: + OldBeg=Beg=End+1; + return FALSE; + } + + } + else + { + Beg=OldBeg; + Buf->Seek( Beg ); + + Success=Buf->GetChar( C ); + + if( !Success ) + { + delete Buf; + #ifdef DEBUG + printf("\n - POP cleaned -"); + #endif + return FALSE; // end of input + } + + if( IsWhiteSpace(C) ) // step cross white space which was no accepted + { + #ifdef DEBUG + printf("\n POP WhiteSpace: \'%d\'\n",C); + #endif + + Beg++; + + // dive because this is whitespace + return Pop( Element ); + + } + else + { + delete Buf; + + Correct=FALSE; + + + #ifdef DEBUG + printf("\n - POP cleaned, not accepted whitespace %c -", C ); + #endif + return FALSE; // end of input + } + } // if success +} + +//----------------------------------------------------------------------------- + +bool Lexicator::CorrectFinish( dword &ErrPos ) +{ + if( !Correct ) + { + ErrPos=Beg; + + return FALSE; + } + else + { + ErrPos=0; + + return TRUE; + } +} + +//----------------------------------------------------------------------------- + +word Lexicator::ConstructBuildInHiliLex( void ) +{ + DynamicAutomat far *DAkceptor = new DynamicAutomat(), + far *HelpDAkceptor; + + if(!DAkceptor) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + word i; + + // position in array is the same as ID of element in LexicatorsType + // see hitypes.h + + char *Descriptor[] ={ + // ghost + "" + , // element + "[Ee][Ll][Ee][Mm][Ee][Nn][Tt]" + , // descr + "[Dd][Ee][Ss][Cc][Rr]" + , // action + "[Aa][Cc][Tt][Ii][Oo][Nn]" + , // raw + "[Rr][Aa][Ww]" + , // raw_beg + "[Rr][Aa][Ww]_[Bb][Ee][Gg]" + , // raw_end + "[Rr][Aa][Ww]_[Ee][Nn][Dd]" + , // font + "[Ff][Oo][Nn][Tt]" + , // size + "[Ss][Ii][Zz][Ee]" + , // color + "[Cc][Oo][Ll][Oo][Rr]" + , // underscore + "[Uu][Nn][Dd][Ee][Rr][Ss][Cc][Oo][Rr][Ee]" + , // italic + "[Ii][Tt][Aa][Ll][Ii][Cc]" + , // bold + "[Bb][Oo][Ll][Dd]" + , // setup + "[Ss][Ee][Tt][Uu][Pp]" + , // output + "[Oo][Uu][Tt][Pp][Uu][Tt]" + , // crlf + "[Cc][Rr][Ll][Ff]" + , // htmloutput + "[Hh][Tt][Mm][Ll][Oo][Uu][Tt][Pp][Uu][Tt]" + , // title + "[Tt][Ii][Tt][Ll][Ee]" + , // face_font + "[Ff][Aa][Cc][Ee]_[Ff][Oo][Nn][Tt]" + , // basecolor + "[Bb][Aa][Ss][Ee][Cc][Oo][Ll][Oo][Rr]" + , // basesize + "[Bb][Aa][Ss][Ee][Ss][Ii][Zz][Ee]" + , // bgcolor + "[Bb][Gg][Cc][Oo][Ll][Oo][Rr]" + , // background + "[Bb][Aa][Cc][Gg][Rr][Oo][Uu][Nn][Dd]" + , // width + "[Ww][Ii][Dd][Tt][Hh]" + , // intable + "[Ii][Nn][Tt][Aa][Bb][Ll][Ee]" + , // outtable + "[Oo][Uu][Tt][Tt][Aa][Bb][Ll][Ee]" + , // lbrace + "\\{" + , // rbrace + "\\}" + , // semicolon + ";" + , // equ + "=" + , // string + "\\\"(([^\\\"])|(\\\\\\\"))*\\\"" + , // comments + "#[^\\n]*\\n" + , // lparent + "\\(" + , // rparent + "\\)" + + }; + + // begin with the first element ( 0 is ghost ) + i=1; + + DAkceptor->StringToDynaAuto( Descriptor[i], i ); // i corresponds to enum ID + + i++; + + // make the rest + while( i<=LEXICATOR_RPARENT ) // the highes lex element ID + { + + HelpDAkceptor=new DynamicAutomat(); if(!HelpDAkceptor) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + HelpDAkceptor->StringToDynaAuto( Descriptor[i], i ); + DAkceptor->Wampirator( *HelpDAkceptor ); + delete HelpDAkceptor; + + i++; + } + + DAkceptor->Save("HILEX.A"); + + Akceptor=new StaticAutomat("HILEX.A"); if(!Akceptor) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + #ifdef DEBUG + Akceptor->Print(); + #endif + + delete DAkceptor; + + return HI_OK; +} + +//-EOF ---------------------------------------------------------------------------- diff --git a/source/hililex.h b/source/hililex.h new file mode 100644 index 0000000..6d8a18e --- /dev/null +++ b/source/hililex.h @@ -0,0 +1,53 @@ +#ifndef __HILILEX_H + #define __HILILEX_H + + #include "io.h" + #include "fcntl.h" + #include "sys\stat.h" + #include "source\box.h" + #include "source\hierrors.h" + #include "source\hilist.h" + #include "source\hitypes.h" + #include "source\prefix.h" + #include "source\regtree.h" + #include "source\static.h" + #include "source\synode.h" + + //--------------------------------------------------------------------------- + + bool IsWhiteSpace( char C ); + + //- class Lexicator --------------------------------------------------------- + + class far _Lexicator + { + private: + + StaticAutomat far *Akceptor; + + // for POP + Buffer far *Buf; + dword Beg, + End, + OldBeg; + + public: + + _Lexicator( void ); + word SniftSnift( char *InFileName, char *OutFileName ); + void PrepareForPop( char *InFileName ); // automaticly cleans mem after the last pop + void CancelPop( void ); // call only if you want to finish before input is worked out + bool Pop( SyntactNode *&Element ); + bool CorrectFinish( dword &ErrPos ); + ~_Lexicator(); + + private: + + word ConstructBuildInHiliLex( void ); + + bool Correct; // to recognize, that there is not finished input + }; + + typedef _Lexicator Lexicator; + +#endif \ No newline at end of file diff --git a/source/hilisem.cpp b/source/hilisem.cpp new file mode 100644 index 0000000..7dcf429 --- /dev/null +++ b/source/hilisem.cpp @@ -0,0 +1,2624 @@ +#include "source\hilisem.h" + +// print info when hunting bugs +// #define DEBUG + +#define EXIT_PROGRAM exit(0); + +extern bool Verbose; +extern bool HTMLOutput; +extern bool CRLF; + +//--------------------------------------------------------------------------------------- + +void QuotesAway( char far *String ) +// delete quotes and \X transforms to X inside string +{ + word Dest, + Src, + Lng = strlen( String ); + + if( String == NULL ) return; + + for( Src=Dest=0; Src<(Lng-2); Src++, Dest++ ) + { + String[Dest]=String[Src+1]; + + if( String[Dest] == '\\') + { + String[Dest]=String[Src+2]; + Src++; + } + + } + + String[Dest] = 0; +} + +//--------------------------------------------------------------------------------------- + +#define ERROR_WHEN_WRITING \ + { \ + printf("\n ERROR reported from %s line %d:" \ + "\n Error writing to the file...", __FILE__, __LINE__ );\ + EXIT_PROGRAM \ + } + +//- class DynaCfgFile methods --------------------------------------------------------- + +DynaCfgFile::DynaCfgFile( void ) +{ + Records = new List; if(!Records) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } +} + +//--------------------------------------------------------------------------------------- + +void DynaCfgFile::PrintTokens( void ) +{ + #ifdef DEBUG + + ListItem far *Item=Records->GetHead(); + + while( Item ) + { + printf("\n\n * FileRow ***********************************************" + "\n Head %Fp Tail %Fp Item %Fp Item->Next %Fp ", + Records->Head, + Records->Tail, + Item, + Item->Next + ); + + ((DynaCfgRecordList far *)Item)->Print(); + + Item=Records->Next( Item ); + } + + #endif +} + +//--------------------------------------------------------------------------------------- + +DynaCfgFile::~DynaCfgFile() +{ + #ifdef DEBUG + printf("\n Destructor of ~DynaCfgFile, %u records", Records->NrOfItems ); + #endif + + delete Records; +} + +//- class DynaCfgRecordList methods --------------------------------------------------------- + +DynaCfgRecordList::DynaCfgRecordList( void ) +{ + Tokens = new List; if(!Tokens) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } +} + +//--------------------------------------------------------------------------------------- + +void DynaCfgRecordList::Print( void ) +{ + #ifdef DEBUG + + ListItem far *Item=Tokens->GetHead(); + + while( Item ) + { + printf("\n - Token ---------------------------------------------------"); + + ((DynaCfgToken far *)Item)->Print(); + + Item=Tokens->Next( Item ); + } + + #endif +} +//--------------------------------------------------------------------------------------- + +DynaCfgRecordList::~DynaCfgRecordList() +{ + #ifdef DEBUG + printf("\n Virtual destructor of ~DynaCfgRecordList, %u Token lists", Tokens->NrOfItems ); + #endif + + delete Tokens; +} + +//- struct DynaCfgToken methods -------------------------------------------------------------------------------------- + +void DynaCfgToken::Print( void ) +{ + #ifdef DEBUG + + printf( + "\n DynaCfgToken:" + "\n Idf : %u" + "\n String: %s" + , + Idf, + String + ); + + #endif +} + +//--------------------------------------------------------------------------------------- + +DynaCfgToken::~DynaCfgToken( void ) +{ + #ifdef DEBUG + printf("\n Virtual destructor ~DynaCfgToken deleting %s", String ); + #endif + + if( String ) delete String; +} + +//- class DynaCfgRecord methods ------------------------------------------------------------ + +void DynaCfgRecord::Print( void ) +{ + #ifdef DEBUG + + printf("\n DynaCfgRecord, record type: %u" + , + Type + ); + + switch( Type ) + { + case RECORD_SETUP_TRANSLATION: + printf("\n Output : %u" + "\n CRLF : %u" + "\n HtmlOutput : %u" + , + Data.Setup.OutType, + Data.Setup.CRLF, + Data.Setup.HTMLOutput + ); + + break; + case RECORD_SETUP_PAGE: + + printf("\n Title : %s" + "\n FaceFont : %s" + "\n BaseColor : %s" + "\n BaseSize : %s" + "\n BgColor : %s" + "\n Background: %s" + "\n Width : %s" + , + Data.Setup.Title, + Data.Setup.FaceFont, + Data.Setup.BaseColor, + Data.Setup.BaseSize, + Data.Setup.BgColor, + Data.Setup.Background, + Data.Setup.Width + ); + break; + case RECORD_NORMAL: + printf("\n Underscore: %d" + "\n Italic : %d" + "\n Bold : %d" + "\n Descr : %s" + "\n Font : %s" + "\n Size : %s" + "\n Color : %s" + , + Data.Normal.Underscore, + Data.Normal.Italic, + Data.Normal.Bold, + Data.Normal.Descr, + Data.Normal.Font, + Data.Normal.Size, + Data.Normal.Color + ); + break; + case RECORD_RAW: + printf( + "\n Descr : %s" + "\n RawBeg: %s" + "\n RawEnd: %s" + , + Data.Raw.Descr, + Data.Raw.RawBeg, + Data.Raw.RawEnd + ); + break; + case RECORD_REPLACE: + printf( + "\n Descr : %s" + "\n Raw : %s" + , + Data.Replace.Descr, + Data.Replace.Raw + ); + break; + case RECORD_REMOVE: + printf( + "\n Descr : %s" + , + Data.Remove.Descr + ); + break; + default: + printf("\n Unknown record"); + + } + + #endif +} + +//--------------------------------------------------------------------------------------- + +DynaCfgRecord::~DynaCfgRecord( void ) +{ + #ifdef DEBUG + printf("\n Virtual destructor ~DynaCfgRecord, record type %u", Type ); + #endif + + switch( Type ) + { + case RECORD_SETUP_TRANSLATION: + + #ifdef DEBUG + printf("\n Output : %u" + "\n CRLF : %u" + "\n HTMLOutput: %u" + , + Data.Setup.OutType, + Data.Setup.CRLF, + Data.Setup.HTMLOutput + ); + #endif + + break; + case RECORD_SETUP_PAGE: + + #ifdef DEBUG + printf("\n Title : %s" + "\n FaceFont : %s" + "\n BaseColor : %s" + "\n BaseSize : %s" + "\n BgColor : %s" + "\n Background: %s" + "\n Width : %s" + , + Data.Setup.Title, + Data.Setup.FaceFont, + Data.Setup.BaseColor, + Data.Setup.BaseSize, + Data.Setup.BgColor, + Data.Setup.Background, + Data.Setup.Width + ); + #endif + + if( Data.Setup.Title ) delete Data.Setup.Title; + if( Data.Setup.FaceFont ) delete Data.Setup.FaceFont; + if( Data.Setup.BaseColor ) delete Data.Setup.BaseColor; + if( Data.Setup.BaseSize ) delete Data.Setup.BaseSize; + if( Data.Setup.BgColor ) delete Data.Setup.BgColor; + if( Data.Setup.Background ) delete Data.Setup.Background; + if( Data.Setup.Width ) delete Data.Setup.Width; + + break; + + case RECORD_NORMAL: + + #ifdef DEBUG + printf("\n Underscore: %d" + "\n Italic : %d" + "\n Bold : %d" + "\n Descr : %s" + "\n Font : %s" + "\n Size : %s" + "\n Color : %s" + , + Data.Normal.Underscore, + Data.Normal.Italic, + Data.Normal.Bold, + Data.Normal.Descr, + Data.Normal.Font, + Data.Normal.Size, + Data.Normal.Color + ); + #endif + + if( Data.Normal.Descr ) delete Data.Normal.Descr; + if( Data.Normal.Font ) delete Data.Normal.Font; + if( Data.Normal.Size ) delete Data.Normal.Size; + if( Data.Normal.Color ) delete Data.Normal.Color; + + break; + case RECORD_RAW: + + #ifdef DEBUG + printf( + "\n Descr : %s" + "\n RawBeg: %s" + "\n RawEnd: %s" + , + Data.Raw.Descr, + Data.Raw.RawBeg, + Data.Raw.RawEnd + ); + #endif + + if( Data.Raw.Descr ) delete Data.Raw.Descr; + if( Data.Raw.RawBeg ) delete Data.Raw.RawBeg; + if( Data.Raw.RawEnd ) delete Data.Raw.RawEnd; + + break; + case RECORD_REPLACE: + + #ifdef DEBUG + printf( + "\n Descr : %s" + "\n Raw : %s" + , + Data.Replace.Descr, + Data.Replace.Raw + ); + #endif + + if( Data.Replace.Descr ) delete Data.Replace.Descr; + if( Data.Replace.Raw ) delete Data.Replace.Raw; + + break; + case RECORD_REMOVE: + + #ifdef DEBUG + printf( + "\n Descr : %s" + , + Data.Remove.Descr + ); + #endif + + if( Data.Remove.Descr ) delete Data.Remove.Descr; + + break; + case RECORD_NO_ACTION: + + #ifdef DEBUG + printf( + "\n Descr : %s" + , + Data.No.Descr + ); + #endif + + if( Data.No.Descr ) delete Data.No.Descr; + + break; + + default: + printf("\n ERROR: Unknown record in virtual destructor of ~DynaCfgRecord..."); + exit(0); + } + + + return; +} + +//- class DynaBinaryCfgTableItem methods ------------------------------------------------------------ + +void DynaBinaryCfgTableItem::Print( void ) +{ + #ifdef DEBUG + + printf("\n DynaTableItem ID %u:" + "\n Action: %d" + "\n RawBeg: %s" + "\n RawEnd: %s" + , + ID, + Action, + RawBeg, + RawEnd + ); + + #endif +} + +//--------------------------------------------------------------------------------------- + +void DynaBinaryCfgTableItem::Save( int Handle ) +{ + word Lng; + + // DO NOT save IDs - its index + + // save Action + if( write( Handle, &Action, 2u ) != 2u ) ERROR_WHEN_WRITING + + // save RawBeg + if( RawBeg==NULL ) + { + Lng = 0; + + if( write( Handle, &Lng, 2u ) != 2u ) ERROR_WHEN_WRITING + } + else + { + Lng = strlen(RawBeg)+1u; + + if( write( Handle, &Lng, 2u ) != 2u ) ERROR_WHEN_WRITING + if( write( Handle, RawBeg, Lng ) != Lng ) ERROR_WHEN_WRITING + } + + // save RawEnd + if( RawEnd==NULL ) + { + Lng = 0; + + if( write( Handle, &Lng, 2u ) != 2u ) ERROR_WHEN_WRITING + } + else + { + Lng = strlen(RawEnd)+1u; + + if( write( Handle, &Lng, 2u ) != 2u ) ERROR_WHEN_WRITING + if( write( Handle, RawEnd, Lng ) != Lng ) ERROR_WHEN_WRITING + } + + return; +} + +//--------------------------------------------------------------------------------------- + +DynaBinaryCfgTableItem::~DynaBinaryCfgTableItem( void ) +{ + #ifdef DEBUG + printf("\n Virtual destructor ~DynaBinaryCfgTableItem deleting" + "\n Action: %d" + "\n RawBeg: %s" + "\n RawEnd: %s" + , + Action, + RawBeg, + RawEnd + ); + #endif + + if( RawBeg ) delete RawBeg; + if( RawEnd ) delete RawEnd; +} + +//- class Semantator methods ------------------------------------------------------------ + +Semantator::Semantator( SyntactNode far *SyntactRoot ) +{ + Root = SyntactRoot; + + Table = new List; if(!Table) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Auto = new DynamicAutomat; if(!Auto) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } +} + +//--------------------------------------------------------------------------------------- + +Semantator::~Semantator( void ) +{ + delete Table; + + delete Auto; +} + +//--------------------------------------------------------------------------------------- + +bool Semantator::DiveForR3s( SyntactNode far *Node ) +// returns true if subtree was deleted and false if not +{ + // go through tree and search for R3 nodes ( root of subtree of one record ) + + switch( Node->Type ) + { + case SNODE_R2: + + // if node was deleted set it to NULL, + // destructor will not dive through it + if( DiveForR3s( Node->Data.NeterminalR2.Rl )) + Node->Data.NeterminalR2.Rl=NULL; + + if( DiveForR3s( Node->Data.NeterminalR2.Rr )) + Node->Data.NeterminalR2.Rr=NULL; + + return FALSE; + + case SNODE_R3: + + // yes I am here => transform record which is under + + WorkOnR3Subtree( Node ); + + // subtree no longer needed -> delete it + + delete Node; + + return TRUE; + + case SNODE_T4: + case SNODE_T5: + case SNODE_K: + case SNODE_S: + case SNODE_k: + case SNODE_s: + case SNODE_LBRACE: + case SNODE_RBRACE: + case SNODE_SEMICOLON: + case SNODE_EQU: + case SNODE_NULL: + case SNODE_STAR: + case SNODE_R: + case SNODE_T: + + printf("\n ERROR: Misplaced node %d in DiveForR3s!", Node->Type ); + exit(0); + + default: + + printf("\n ERROR: Unknown node %d probably error in DiveForR3s!", Node->Type ); + exit(0); + } + + return FALSE; +} + +//--------------------------------------------------------------------------------------- + +void Semantator::WorkOnR3Subtree( SyntactNode far *Node ) +// - make ONE RECORD ( convert it from syntact subtree ) +{ + // insert new record to file list + DynaCfgRecordList far *RecordList = new DynaCfgRecordList; if(!RecordList) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + File->Insert( RecordList ); + + + + // insert setup/element token - is here! + + DynaCfgToken far *Token = new DynaCfgToken; if(!Token) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // validity of keyword was checked in lexicator + // => here only fill + // enum IDs are same, see hitypes.h + + Token->Idf = Node + ->Data.NeterminalT4.K // T4 + ->Data.NeterminalK.k // I + ->Data.k.Key; // i + + Token->String = Node + ->Data.NeterminalT4.S // T4 + ->Data.NeterminalS.s // S + ->Data.s.Element; // s + + // token OK -> insert it to record list + RecordList->Insert( Token ); + + + + // rest of tokens is under T4 node -> so dive and than insert tokens + DiveForT4s( Node->Data.NeterminalR3.T, RecordList ); + + return; +} + +//--------------------------------------------------------------------------------------- + +void Semantator::DiveForT4s( SyntactNode far *Node, + DynaCfgRecordList far *RecordList + ) +{ + DynaCfgToken far *Token; + + // go through tree and search for T4 nodes ( node over one TOKEN ) + + switch( Node->Type ) + { + case SNODE_T4: + // yes I am here => transform token under + Token = new DynaCfgToken; if(!Token) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // validity of keyword was checked in lexicator + // => here only fill + // enum IDs are same, see hitypes.h + + Token->Idf = Node + ->Data.NeterminalT4.K // T4 + ->Data.NeterminalK.k // I + ->Data.k.Key; // i + + Token->String = Node + ->Data.NeterminalT4.S // T4 + ->Data.NeterminalS.s // S + ->Data.s.Element; // s + + // token OK -> insert it to record list + RecordList->Insert( Token ); + + return; + case SNODE_T5: + DiveForT4s( Node->Data.NeterminalT5.Tl, RecordList ); + DiveForT4s( Node->Data.NeterminalT5.Tr, RecordList ); + return; + case SNODE_R2: + case SNODE_R3: + case SNODE_S: + case SNODE_k: + case SNODE_s: + case SNODE_LBRACE: + case SNODE_RBRACE: + case SNODE_SEMICOLON: + case SNODE_EQU: + case SNODE_NULL: + case SNODE_STAR: + case SNODE_R: + case SNODE_T: + + printf("\n ERROR: Misplaced node %d in DiveForT4s!", Node->Type ); + exit(0); + + default: + + printf("\n ERROR: Unknown node %d probably error in DiveForT4s!", Node->Type ); + exit(0); + } +} + +//--------------------------------------------------------------------------------------- + +void Semantator::DynaCfgRecordListToDynaCfgRecord + ( + DynaCfgRecordList far *CfgRecordList, + DynaCfgRecord far *&Record + ) +// converts list to single record, allocates this record and returns +// pointer on it +{ + + List far *RecordList = ((DynaCfgRecordList far *)CfgRecordList)->Tokens; + + bool Change; // true if some change when sorting + word i, + L, + Lng, + NrOfDescrs; + char far *StringDescrs; + ListItem far *Item, + far *Item1, + far *Item2, + far *Item3, + far *Item4, + + far *DescrItem + ; + + // sort record list and check what's in + // sort order == enum order by numbers: + + // using enum ID to sort list + + Change=TRUE; + + while( Change ) + { + if( RecordList->NrOfItems == 1 ) break; // nothing to sort + + Item=RecordList->GetHead(); + + Change=FALSE; + + for( i=1; i<=(RecordList->NrOfItems-1); i++ ) // go through list once + { + + if( + ((DynaCfgToken far *)Item)->Idf + > + ((DynaCfgToken far *)Item->Next)->Idf + ) + { + #ifdef DEBUG + //printf("\n\n %u <-> %u", ((DynaCfgToken far *)Item)->Idf, ((DynaCfgToken far *)(Item->Next))->Idf ); + #endif + + // change order in list: 1234 -> 1324 ( Item points to 2 ) + Item1 = Item->Last; + Item2 = Item; + Item3 = Item->Next; + Item4 = Item->Next->Next; + + // 1234 -> 1324 + Item1->Next = Item3; + Item2->Next = Item4; + Item3->Next = Item2; + + Item2->Last = Item3; + Item3->Last = Item1; + Item4->Last = Item2; + + Change=TRUE; + + // item must stay correct -> next is done when switching items! + // item2==item is moved to tail + + continue; + } + + Item=RecordList->Next(Item); + } // for + } + + #ifdef DEBUG + //printf("\n\n In DynaCfgRecordListToDynaCfgRecord after sorting XXXXXXXXXXXXXXX"); + //CfgRecordList->PrintTokens(); + #endif + + // now items are sorted, check if tokens are OK + + if( RecordList->Empty() ) + { + printf("\n ERROR reported from %s line %d:" + "\n Record list is empty - strange -> delete or fill with something...", __FILE__,__LINE__ + ); + exit(0); + } + + // CHECK: the first must be element or setup + + Item = RecordList->GetHead(); + + switch( ((DynaCfgToken far *)Item)->Idf ) + { + case TOKEN_ELEMENT: + // CHECK: there must be descr(s) + // if there is more then one concatenate them + + // it is name of element block, Item1 is backup for error + Item1=Item; + + Item=RecordList->Next( Item ); + + // now item should point to descr + if( Item==NULL + || + ((DynaCfgToken far *)Item)->Idf != TOKEN_DESCR + ) + { + printf("\n ERROR reported from %s line %d:" + "\n Missing descr in %s element block...", __FILE__,__LINE__, ((DynaCfgToken far *)Item1)->String ); + exit(0); + } + + // concatenate existing descrs + // first count total lng, then allocate and in the end copy + // descrs to new location, delete old descrs and insert new + // ( concatened descr put to the first node, others delete ) + // eliminate " ( belongs to lex element not to descr ) + + DescrItem=Item; + + // count lng + Lng=0; NrOfDescrs=0; + + while( Item && ((DynaCfgToken far *)Item)->Idf == TOKEN_DESCR ) + { + NrOfDescrs++; + + // put away " on sides ( belongs to string not to descr ) + + L = strlen( ((DynaCfgToken far *)Item)->String ); // 0 not counted + + for( i=0; iString[i] + = + ((DynaCfgToken far *)Item)->String[i+1]; + + ((DynaCfgToken far *)Item)->String[L-2]=0; // kill " at tail + + L -= 2; + + if( L == 0 ) + { + printf("\n ERROR reported from %s line %d:" + "\n Descriptor is empty string in HILEX cfg file...", __FILE__,__LINE__); + exit(0); + } + + // done + + Lng+=L; + + Item=RecordList->Next( Item ); + } + + if( NrOfDescrs>1 ) + { + // concatenate + + Item=DescrItem; + + StringDescrs = new char[Lng+1]; // add place for 0 + if(!StringDescrs) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + StringDescrs[0] = 0; + + NrOfDescrs=0; + + while( Item && ((DynaCfgToken far *)Item)->Idf == TOKEN_DESCR ) + { + NrOfDescrs++; + + strcat( StringDescrs, ((DynaCfgToken far *)Item)->String ); + + Item3 = Item; // backup item ( will be deleted ) + Item = RecordList->Next( Item ); + + // delete result of descr nodes ( one node is enough ) + if( NrOfDescrs>1 ) RecordList->Delete( Item3 ); + + } + + // put concatenated descr to the first node + delete ((DynaCfgToken far *)DescrItem)->String; + ((DynaCfgToken far *)DescrItem)->String = StringDescrs; + } + + // Item points to the element after descr node + // now here must be action + if( ((DynaCfgToken far *)Item)->Idf != TOKEN_ACTION ) + { + printf("\n ERROR reported from %s line %d:" + "\n Missing ACTION in HILEX cfg file...", __FILE__,__LINE__); + exit(0); + } + + // ACTION -> 3 cases: + // Encapsulate ... Raw_Beg&RawEnd || Null || Color... + // Remove ... there must be NULL + // Replace ... there must be Raw + + if( !stricmp( "\"remove\"", ((DynaCfgToken far *)Item)->String ) + || + !stricmp( "\"no\"", ((DynaCfgToken far *)Item)->String ) + ) + { + // now there must be NULL + Item = RecordList->Next( Item ); + + if( Item!=NULL && Verbose) + { + printf("\n WARNING reported from %s line %d:" + "\n No settings allowed when action REMOVE or NO => ignoring options...\n", __FILE__,__LINE__); + } + } + else + { + if( !stricmp( "\"replace\"", ((DynaCfgToken far *)Item)->String ) ) + { + // now there must be Raw + Item = RecordList->Next( Item ); + + if( Item!=NULL && ((DynaCfgToken far *)Item)->Idf != TOKEN_RAW ) + { + printf("\n ERROR reported from %s line %d:" + "\n When action REPLACE is selected, there must be Raw section in HILEX file...", __FILE__,__LINE__); + exit(0); + } + } + else + { + if( !stricmp( "\"encapsulate\"", ((DynaCfgToken far *)Item)->String ) ) + { + // CHECK: rawbeg&&rawend + // || + // font, size, color, ... + // together -> error + + Item = RecordList->Next( Item ); + + // if nothing default is used + if( Item==NULL && Verbose) + { + printf("\n WARNING reported from %s line %d:" + "\n No settings when action ENCAPSULATE => using default...\n", __FILE__,__LINE__); + } + + + if( ((DynaCfgToken far *)Item)->Idf == TOKEN_RAWEND ) + { + printf("\n ERROR reported from %s line %d:" + "\n Missing RAW_BEG in HILEX cfg file...", __FILE__,__LINE__); + exit(0); + } + + if( ((DynaCfgToken far *)Item)->Idf == TOKEN_RAWBEG ) + { + // now there must be rawend + Item = RecordList->Next( Item ); + + if( Item==NULL + || + ((DynaCfgToken far *)Item)->Idf != TOKEN_RAWEND + ) + { + printf("\n ERROR reported from %s line %d:" + "\n Missing RAW_END in HILEX cfg file...", __FILE__,__LINE__); + exit(0); + } + } + } + else + { + printf("\n ERROR reported from %s line %d:" + "\n Unknown action %s in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit(0); + } + } + } + + // the rest should be OK + + break; + + case TOKEN_SETUP: + // if string == translation there must be output/CRLF/HtmlOutput + // or + // empty + // + // if string == page can be empty or with biggest enum type + // another string is error + + Item = RecordList->GetHead(); // now item points to setup + + if( Item==NULL ) // empty - OK no options -> default will be used + break; + + // setuping translation or page + if( !stricmp( "\"translation\"", ((DynaCfgToken far *)Item)->String ) ) + { + // now here must be output or empty + Item = RecordList->Next( Item ); + + if( Item==NULL ) // empty - OK no options -> default will be used + break; + + if( ((DynaCfgToken far *)Item)->Idf != TOKEN_OUTPUT ) + { + printf("\n ERROR reported from %s line %d:" + "\n In SETUP TRANSLATION can be only OUTPUT keyword used," + "\n nothing else in HILEX cfg file...", __FILE__,__LINE__); + exit( 0 ); + } + + if( + ! + ( + !stricmp( "\"html_page\"", ((DynaCfgToken far *)Item)->String ) + || + !stricmp( "\"html_table\"", ((DynaCfgToken far *)Item)->String ) + || + !stricmp( "\"no_encaps\"", ((DynaCfgToken far *)Item)->String ) + ) + ) + { + printf("\n ERROR reported from %s line %d:" + "\n Option %s not allowed in OUTPUT section in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit( 0 ); + } + + break; + } + + // page is valid keyword of setup, rest is OK ( there is not output ) + if( !stricmp( "\"encapsulation\"", ((DynaCfgToken far *)Item)->String ) ) + break; + + + printf("\n ERROR reported from %s line %d:" + "\n Unknown SETUP option %s in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit(0); + + default: + printf("\n ERROR reported from %s line %d:" + "\n Element or setup identifier missing in HILEX cfg file...", __FILE__,__LINE__); + exit(0); + } + + + + // List is now checked and ok => transform it to record + // => fill DynaCfgRecord + + Item = RecordList->GetHead(); + + switch( ((DynaCfgToken far *)Item)->Idf ) + { + case TOKEN_ELEMENT: + + // time to delete block name ( is ignored) + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item1)->String = NULL; + + Item=RecordList->Next( Item ); + + // now pointing to descr + + DescrItem=Item; + + Item=RecordList->Next( Item ); + + // now pointing to action: ENCAPSULATE/REMOVE/REPLACE/NO + if( !stricmp( "\"no\"", ((DynaCfgToken far *)Item)->String ) ) + { + // no options needed, only save fill type of record + // -> says which action schould be done + Record->Type = RECORD_NO_ACTION; + Record->Data.No.Descr = ((DynaCfgToken far *)DescrItem)->String; + ((DynaCfgToken far *)DescrItem)->String = NULL; + + break; + } + + + + if( !stricmp( "\"remove\"", ((DynaCfgToken far *)Item)->String ) ) + { + // no options needed, only save fill type of record + // -> says which action schould be done + Record->Type = RECORD_REMOVE; + Record->Data.Remove.Descr = ((DynaCfgToken far *)DescrItem)->String; + ((DynaCfgToken far *)DescrItem)->String = NULL; + + break; + } + + + + if( !stricmp( "\"replace\"", ((DynaCfgToken far *)Item)->String ) ) + { + Record->Type = RECORD_REPLACE; + Record->Data.Remove.Descr = ((DynaCfgToken far *)DescrItem)->String; + ((DynaCfgToken far *)DescrItem)->String = NULL; + + // move to option raw ( is there - was checked at the top ) + Item=RecordList->Next( Item ); + + Record->Data.Replace.Raw = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + QuotesAway( Record->Data.Replace.Raw ); + + break; + } + + + + if( !stricmp( "\"encapsulate\"", ((DynaCfgToken far *)Item)->String ) ) + { + // move after action + Item=RecordList->Next( Item ); + + if( Item==NULL ) + { + // item is NULL -> user wants not encapsulate this element + // -> init it, do not forget to init descr + Record->Type = RECORD_NORMAL; + Record->Data.Normal.Font = NULL; + Record->Data.Normal.Size = NULL; + Record->Data.Normal.Color = NULL; + Record->Data.Normal.Underscore = FALSE; + Record->Data.Normal.Italic = FALSE; + Record->Data.Normal.Bold = FALSE; + Record->Data.Normal.Descr = ((DynaCfgToken far *)DescrItem)->String; + ((DynaCfgToken far *)DescrItem)->String = NULL; + + break; + } + + if( ((DynaCfgToken far *)Item)->Idf == TOKEN_RAWBEG ) + { + Record->Type = RECORD_RAW; + Record->Data.Raw.RawBeg = NULL; + Record->Data.Raw.RawEnd = NULL; + + Record->Data.Raw.RawBeg = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + QuotesAway( Record->Data.Raw.RawBeg ); + + Item=RecordList->Next( Item ); + + Record->Data.Raw.RawEnd = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + QuotesAway( Record->Data.Raw.RawEnd ); + + // set descr + Record->Data.Raw.Descr = ((DynaCfgToken far *)DescrItem)->String; + + ((DynaCfgToken far *)DescrItem)->String=NULL; + + // the rest of string ignore + break; + } + + // it's normal, init it + Record->Type = RECORD_NORMAL; + Record->Data.Normal.Font = NULL; + Record->Data.Normal.Size = NULL; + Record->Data.Normal.Color = NULL; + Record->Data.Normal.Underscore = FALSE; + Record->Data.Normal.Italic = FALSE; + Record->Data.Normal.Bold = FALSE; + + // set descr + Record->Data.Normal.Descr = ((DynaCfgToken far *)DescrItem)->String; + + ((DynaCfgToken far *)DescrItem)->String = NULL; + + #ifdef DEBUG + //printf("\n\n In DynaCfgRecordListToDynaCfgRecord after descr:"); + //CfgRecordList->PrintTokens(); + #endif + + // -> work on the rest ( now pointing behind action ) + + while( Item ) + { + + switch( ((DynaCfgToken far *)Item)->Idf ) + { + case TOKEN_FONT: + + Record->Data.Normal.Font = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + case TOKEN_SIZE: + + Record->Data.Normal.Size = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + case TOKEN_COLOR: + + Record->Data.Normal.Color = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + case TOKEN_UNDERSCORE: + + if( !stricmp( "\"true\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Normal.Underscore=TRUE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + break; + } + + if( !stricmp( "\"false\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Normal.Underscore=FALSE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + break; + } + + // neither true nor false -> error + printf("\n ERROR reported from %s line %d:" + "\n Underscore option %s is not TRUE/FALSE in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit(0); + + case TOKEN_ITALIC: + + if( !stricmp( "\"true\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Normal.Italic=TRUE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + break; + } + + if( !stricmp( "\"false\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Normal.Italic=FALSE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + break; + } + + // neither true nor false -> error + printf("\n ERROR reported from %s line %d:" + "\n Italic option %s is not TRUE/FALSE in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit(0); + + case TOKEN_BOLD: + + if( !stricmp( "\"true\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Normal.Bold=TRUE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + break; + } + + if( !stricmp( "\"false\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Normal.Bold=FALSE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + break; + } + + // neither true nor false -> error + printf("\n ERROR reported from %s line %d:" + "\n Bold option %s is not TRUE/FALSE in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit(0); + + + default: + // unknown node -> ignore it -> stop work, but not error + Item=NULL; + + if( Verbose ) + { + printf("\n WARNING reported from %s line %d:" + "\n Unknown option ID %d containing %s in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->Idf, ((DynaCfgToken far *)Item)->String ); + } + + continue; // exit while + } + + Item=RecordList->Next( Item ); + } // while item + } // if( Encapsulate ) + + break; + + case TOKEN_SETUP: + + Item = RecordList->GetHead(); // setup + + if( Item==NULL ) // empty - OK no options -> default will be used + break; + + // now item should point behind Setup + if( !stricmp( "\"translation\"", ((DynaCfgToken far *)Item)->String ) ) + { + Record->Type = RECORD_SETUP_TRANSLATION; + // now set default, if is in cfg file will be changed... + // globals are already set + Record->Data.Setup.OutType = HTML_PAGE; + Record->Data.Setup.CRLF = FALSE; + Record->Data.Setup.HTMLOutput = TRUE; + + + Item = RecordList->Next( Item ); + + if( Item==NULL ) // empty - OK no options -> default used ( already set ) + { + break; + } + else // + { + + while( Item ) + { + + switch( ((DynaCfgToken far *)Item)->Idf ) + { + case TOKEN_OUTPUT: + + if( !stricmp( "\"html_page\"", ((DynaCfgToken far *)Item)->String ) ) + Record->Data.Setup.OutType = HTML_PAGE; + + if( !stricmp( "\"html_table\"", ((DynaCfgToken far *)Item)->String ) ) + Record->Data.Setup.OutType = HTML_TABLE; + + if( !stricmp( "\"no_encaps\"", ((DynaCfgToken far *)Item)->String ) ) + Record->Data.Setup.OutType = NO_ENCAPS; + + // delete string + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String = NULL; + + break; + + case TOKEN_CRLF: + + if( !stricmp( "\"true\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Setup.CRLF=TRUE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + // set global - will be used instead of record things + CRLF = Record->Data.Setup.CRLF; + + break; + } + + if( !stricmp( "\"false\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Setup.CRLF=FALSE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + // set global - will be used instead of record things + CRLF = Record->Data.Setup.CRLF; + + break; + } + + // neither true nor false -> error + printf("\n ERROR reported from %s line %d:" + "\n CRLF option %s is not TRUE/FALSE in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit(0); + + case TOKEN_HTMLOUTPUT: + + if( !stricmp( "\"true\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Setup.HTMLOutput=TRUE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + // set global - will be used instead of record things + HTMLOutput = Record->Data.Setup.HTMLOutput; + + break; + } + + if( !stricmp( "\"false\"", ((DynaCfgToken far *)Item)->String) ) + { + Record->Data.Setup.HTMLOutput=FALSE; + delete ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + // set global - will be used instead of record things + HTMLOutput = Record->Data.Setup.HTMLOutput; + + break; + } + + // neither true nor false -> error + printf("\n ERROR reported from %s line %d:" + "\n HtmlOutput option %s is not TRUE/FALSE in HILEX cfg file...", __FILE__,__LINE__, ((DynaCfgToken far *)Item)->String ); + exit(0); + + default: + // unknown node -> ignore it -> stop work, but not error + Item=NULL; + continue; // exit while + } + + Item=RecordList->Next( Item ); + } // while item + } // else + break; + } + else // setup "page" is valid keyword of setup ( already checked ) + { + Record->Type = RECORD_SETUP_PAGE; + Record->Data.Setup.Title = NULL; + Record->Data.Setup.FaceFont = NULL; + Record->Data.Setup.BaseColor = NULL; + Record->Data.Setup.BaseSize = NULL; + Record->Data.Setup.BgColor = NULL; + Record->Data.Setup.Background = NULL; + Record->Data.Setup.Width = NULL; + + // now go through and fill it + Item = RecordList->Next( Item ); + + while( Item ) + { + + switch( ((DynaCfgToken far *)Item)->Idf ) + { + case TOKEN_TITLE: + + Record->Data.Setup.Title = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + + case TOKEN_FACEFONT: + + Record->Data.Setup.FaceFont = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + + case TOKEN_BASECOLOR: + + Record->Data.Setup.BaseColor = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + + case TOKEN_BASESIZE: + + Record->Data.Setup.BaseSize = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + + case TOKEN_BGCOLOR: + + Record->Data.Setup.BgColor = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + + case TOKEN_BACKGROUND: + + Record->Data.Setup.Background = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + + case TOKEN_WIDTH: + + Record->Data.Setup.Width = ((DynaCfgToken far *)Item)->String; + ((DynaCfgToken far *)Item)->String=NULL; + + break; + + default: + // unknown node -> ignore it -> stop work, but not error + Item=NULL; + continue; // exit while + } + + Item=RecordList->Next( Item ); + } // while item + } // else + + break; + + default: + printf("\n ERROR reported from %s line %d:" + "\n Element or setup identifier missing in HILEX cfg file...", __FILE__,__LINE__); + exit(0); + } + + // now record is filled -> delete old list and return addr of + // newly created single record + + RecordList->Destroy(); + + return; +} + +//--------------------------------------------------------------------------------------- + +void Semantator::RecordsToDynaTable( void ) +// - converts everything inside to raw mode +// - converts DESCRS to AUTOMAT +// - converts records to dynamic table ( declared inside semantator ) +{ + int i; + + ElementID ID; + // in DynaBinaryCfgTableItem + // ID which automat returns when this element is accepted + // - if ID==0 this struct contains beg and end + // of html page or table which is encapsulated + // using hilex + // - else contains element things, + // later will be element encapsulated + // this way: "RawBeg" Element "RawEnd" + + // if CRs not wanted are filtered out in Buffer.cpp/Save + char *HtmlPageHeader[] + = + { // 0 + "" + "\r\n" + "\r\n" + "\r\n" + "\r\n" + "\r\n " + "\r\n " + , // 1 + "Page converted by HILEX" + , // 2 + "" + "\r\n" + "\r\n" + "\r\n" + "\r\n
"
+      "\r\n "
+      "\r\n"
+      };
+
+ char HtmlPageTail[]
+       =
+      "\r\n "
+      "\r\n 
" + "\r\n " + "\r\n" + "\r\n" + ; + + char *HtmlTableHeader[] + = + { // 0 + "" + "\r\n
" + "\r\n" + "\r\n" + , // 1 + "\r\n " + "\r\n
"
+       "\r\n "
+       "\r\n"
+       "\r\n"
+      };
+
+ char HtmlTableTail[]
+       =
+      "\r\n "
+      "\r\n 
" + "\r\n " + "\r\n
" + "\r\n
" + "\r\n
" + "\r\n" + ; + + char far *Buffer = new char[5000]; + if(!Buffer) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + Buffer[0] = 0; + + // --- SORT --- + // sort records inside file using enum RECORD_ types + // setups will be at beginning, elements at tail: + // + // RECORD_SETUP_TRANSLATION // sort to head + // RECORD_SETUP_PAGE // sort to head + // RECORD_NORMAL // do not sort them + // RECORD_RAW // do not sort them + + bool Change; + + ListItem far *Item, + far *Item1, + far *Item2, + far *Item3, + far *Item4; + + #ifdef DEBUG + printf("\n\n - Before sorting ---------------------------------------------"); PrintListOfRecords(); + #endif + + Change=TRUE; + + while( Change ) + { + if( ListOfRecords->NrOfItems == 1 ) break; // nothing to sort + + Item=ListOfRecords->GetHead(); + + Change=FALSE; + + for( i=1; i<=(ListOfRecords->NrOfItems-1); i++ ) // go through list once + { + + if( + ( + ((DynaCfgRecord far *)Item->Next)->Type <= RECORD_SETUP_PAGE + ) + && + ( + ((DynaCfgRecord far *)Item)->Type + > + ((DynaCfgRecord far *)Item->Next)->Type + ) + ) + { + #ifdef DEBUG + printf("\n\n %u <-> %u", ((DynaCfgRecord far *)Item)->Type, ((DynaCfgRecord far *)(Item->Next))->Type ); + #endif + + // change order in list: 1234 -> 1324 ( Item points to 2 ) + Item1 = Item->Last; + Item2 = Item; + Item3 = Item->Next; + Item4 = Item->Next->Next; + + // 1234 -> 1324 + Item1->Next = Item3; + Item2->Next = Item4; + Item3->Next = Item2; + + Item2->Last = Item3; + Item3->Last = Item1; + Item4->Last = Item2; + + Change=TRUE; + + // item must stay correct -> next is done when switching items! + // item2==item is moved to tail + + continue; + } + + Item=ListOfRecords->Next(Item); + } // for + } + + + #ifdef DEBUG + printf("\n\n - After sorting ---------------------------------------------"); PrintListOfRecords(); + #endif + + // --- WORK --- + + DynaCfgRecord far *Record; + DynaBinaryCfgTableItem far *TableItem; + + bool StartTag; + word Lng; + + // Cases: + // 1) Setup translation page/table/no + // Setup page + // + // 2) Setup translation + // + // 3) Setup page + // + // 4) X + // + + OutputType OutType = HTML_PAGE; + + Record = (DynaCfgRecord far *)(ListOfRecords->GetHead()); + + if( Record==NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n HILEX cfg file is empty...", __FILE__,__LINE__); + exit(0); + } + + switch( Record->Type ) + { + case RECORD_SETUP_TRANSLATION: // case 1 or case 2 + + OutType=Record->Data.Setup.OutType; + + Item=Record; // backup setup Record + + // take next + Record = (DynaCfgRecord far *)(ListOfRecords->Next(Record)); + + if( Record==NULL ) + { + printf("\n\n ERROR reported from %s line %d:" + "\n HILEX cfg contains no element section...", __FILE__,__LINE__); + exit(0); + } + + ListOfRecords->Delete( Item ); // delete setup record + + if( Record->Type != RECORD_SETUP_PAGE || !Record ) // case 2 + { + // no concrete title/facefont/... -> construct default header + + switch( OutType ) + { + // -> construct default header for HTML_PAGE + case HTML_PAGE: + + Buffer[0]=0; + + for( i=0; i<=12; i++ ) + strcat( Buffer, HtmlPageHeader[i] ); + + break; + + // -> construct default header for HTML_TABLE + case HTML_TABLE: + + Buffer[0]=0; + + strcat( Buffer, HtmlTableHeader[0] ); + strcat( Buffer, HtmlTableHeader[1] ); + + for( i=4; i<=12; i++ ) + strcat( Buffer, HtmlTableHeader[i] ); + + break; + + default: // NO_ENCAPS + + Buffer[0]=0; + + break; + } + + break; + } + + // else case 1: concrete settings title/facefont/... + // go to next case ( no break ) + + case RECORD_SETUP_PAGE: // case 3 + // only setup page -> default of output is html page + // -> construct html page with settings from this node + + // if from previous case -> jump to each case + + switch( OutType ) + { + case HTML_PAGE: + + Buffer[0]=0; + + strcat( Buffer, HtmlPageHeader[0] ); + + // title + if( Record->Data.Setup.Title ) + { + strcat( Buffer, Record->Data.Setup.Title ); + delete Record->Data.Setup.Title; + Record->Data.Setup.Title = NULL; + } + else + strcat( Buffer, HtmlPageHeader[1] ); + + strcat( Buffer, HtmlPageHeader[2] ); + + // base text color + if( Record->Data.Setup.BaseColor ) + { + strcat( Buffer, Record->Data.Setup.BaseColor ); + delete Record->Data.Setup.BaseColor; + Record->Data.Setup.BaseColor = NULL; + } + else + strcat( Buffer, HtmlPageHeader[3] ); + + strcat( Buffer, HtmlPageHeader[4] ); + + // bg color + if( Record->Data.Setup.BgColor ) + { + strcat( Buffer, Record->Data.Setup.BgColor ); + delete Record->Data.Setup.BgColor; + Record->Data.Setup.BgColor = NULL; + } + else + strcat( Buffer, HtmlPageHeader[5] ); + + // background + if( Record->Data.Setup.Background ) + { + strcat( Buffer, HtmlPageHeader[6] ); // Background= + + strcat( Buffer, Record->Data.Setup.Background ); + delete Record->Data.Setup.Background; + Record->Data.Setup.Background = NULL; + } + + strcat( Buffer, HtmlPageHeader[8] ); + + // font + if( Record->Data.Setup.FaceFont ) + { + strcat( Buffer, Record->Data.Setup.FaceFont ); + delete Record->Data.Setup.FaceFont; + Record->Data.Setup.FaceFont = NULL; + } + else + strcat( Buffer, HtmlPageHeader[9] ); + + strcat( Buffer, HtmlPageHeader[10] ); + + // size + if( Record->Data.Setup.BaseSize ) + { + strcat( Buffer, Record->Data.Setup.BaseSize ); + delete Record->Data.Setup.BaseSize; + Record->Data.Setup.BaseSize = NULL; + } + else + strcat( Buffer, HtmlPageHeader[11] ); + + strcat( Buffer, HtmlPageHeader[12] ); + + // delete setup page record - no longer needed + ListOfRecords->Delete( Record ); + + break; + + case HTML_TABLE: + + Buffer[0]=0; + + strcat( Buffer, HtmlTableHeader[0] ); + strcat( Buffer, HtmlTableHeader[1] ); + + // width ( only if user wants it ) else nothing + if( Record->Data.Setup.Width ) + { + strcat( Buffer, HtmlTableHeader[2] ); + strcat( Buffer, Record->Data.Setup.Width ); + + delete Record->Data.Setup.Width; + Record->Data.Setup.Width = NULL; + } + + // bg color + strcat( Buffer, HtmlTableHeader[4] ); + + if( Record->Data.Setup.BgColor ) + { + strcat( Buffer, Record->Data.Setup.BgColor ); + + delete Record->Data.Setup.BgColor; + Record->Data.Setup.BgColor = NULL; + } + else + strcat( Buffer, HtmlTableHeader[5] ); + + strcat( Buffer, HtmlTableHeader[6] ); + + // font + if( Record->Data.Setup.FaceFont ) + { + strcat( Buffer, Record->Data.Setup.FaceFont ); + delete Record->Data.Setup.FaceFont; + Record->Data.Setup.FaceFont = NULL; + } + else + strcat( Buffer, HtmlTableHeader[7] ); + + strcat( Buffer, HtmlTableHeader[8] ); + + // size + if( Record->Data.Setup.BaseSize ) + { + strcat( Buffer, Record->Data.Setup.BaseSize ); + delete Record->Data.Setup.BaseSize; + Record->Data.Setup.BaseSize = NULL; + } + else + strcat( Buffer, HtmlTableHeader[9] ); + + strcat( Buffer, HtmlTableHeader[10] ); + + // base text color + if( Record->Data.Setup.BaseColor ) + { + strcat( Buffer, Record->Data.Setup.BaseColor ); + delete Record->Data.Setup.BaseColor; + Record->Data.Setup.BaseColor = NULL; + } + else + strcat( Buffer, HtmlTableHeader[11] ); + + strcat( Buffer, HtmlTableHeader[12] ); + + // delete setup page record - no longer needed + ListOfRecords->Delete( Record ); + + break; + + default: // NO_ENCAPS + + // record RECORD_SETUP_PAGE is not used in this case + // => delete it + + ListOfRecords->Delete( Record ); + + Buffer[0]=0; + + break; + } + + break; + + default: // case 4 + // default is default html page => so construct default html page + + Buffer[0]=0; + + for( i=0; i<=12; i++ ) + strcat( Buffer, HtmlPageHeader[i] ); + + break; + } + + + // construct table item with ID 0 => encapsulation of file + + TableItem = new DynaBinaryCfgTableItem; if(!TableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + TableItem->ID = ID = 0; + + // fill RawBeg + // put there content of buffer + Lng = strlen( Buffer ); + + if( Lng ) + { + TableItem->RawBeg = new char[Lng+1]; // allocate + if(!(TableItem->RawBeg)) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + strcpy( TableItem->RawBeg, Buffer ); // copy content + } + else + { + TableItem->RawBeg = NULL; + } + + // fill RawEnd + switch( OutType ) + { + case HTML_PAGE: + + Lng = strlen( HtmlPageTail ); + + TableItem->RawEnd = new char[Lng+1]; // allocate + if(!(TableItem->RawEnd)) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + strcpy( TableItem->RawEnd, HtmlPageTail ); // copy content + + break; + + case HTML_TABLE: + + Lng = strlen( HtmlTableTail ); + + TableItem->RawEnd = new char[Lng+1]; // allocate + if(!(TableItem->RawEnd)) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + strcpy( TableItem->RawEnd, HtmlTableTail ); // copy content + + break; + + default: // NO_ENCAPS + + TableItem->RawEnd = NULL; + + break; + } + + + + // insert item to dynamic table + + Table->Insert( TableItem ); + + #ifdef DEBUG + PrintTable(); + #endif + + // make --ELEMENTS-- the same way -> take the next + + DynamicAutomat far *HelpAuto; + bool FirstAutoDone = FALSE; + + Record = (DynaCfgRecord far *)(ListOfRecords->GetHead()); + + if( Record==NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n HILEX cfg contains no element section...", __FILE__,__LINE__); + exit(0); + } + + ID = 1; + + while( Record ) + { + + TableItem = new DynaBinaryCfgTableItem; if(!TableItem) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + TableItem->ID = ID++; + + Buffer[0]=0; + + switch( Record->Type ) + { + case RECORD_NO_ACTION: + + #ifdef DEBUG + printf("\n\n Creating automat for ID %u...", TableItem->ID ); + #endif + + TableItem->RawBeg = TableItem->RawEnd = NULL; + + if( Record->Data.No.Descr == NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n Descr is NULL...", __FILE__, __LINE__ ); + exit( 0 ); + } + + if( FirstAutoDone ) + { + HelpAuto=new DynamicAutomat; if(!HelpAuto) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + HelpAuto->StringToDynaAuto( Record->Data.No.Descr, TableItem->ID ); + Auto->Wampirator( *HelpAuto ); + delete HelpAuto; + + #ifdef DEBUG + Auto->Print(); + #endif + } + else + { + Auto->StringToDynaAuto( Record->Data.No.Descr, TableItem->ID ); + FirstAutoDone = TRUE; + + #ifdef DEBUG + Auto->Print(); + #endif + } + + // delete descr + delete Record->Data.No.Descr; + Record->Data.No.Descr = NULL; + + // fill Action + TableItem->Action = ACTION_NO; + + break; + + case RECORD_REMOVE: + + #ifdef DEBUG + printf("\n\n Creating automat for ID %u...", TableItem->ID ); + #endif + + TableItem->RawBeg = TableItem->RawEnd = NULL; + + if( Record->Data.Remove.Descr == NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n Descr is NULL...", __FILE__, __LINE__ ); + exit( 0 ); + } + + if( FirstAutoDone ) + { + HelpAuto=new DynamicAutomat; if(!HelpAuto) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + HelpAuto->StringToDynaAuto( Record->Data.Remove.Descr, TableItem->ID ); + Auto->Wampirator( *HelpAuto ); + delete HelpAuto; + + #ifdef DEBUG + Auto->Print(); + #endif + } + else + { + Auto->StringToDynaAuto( Record->Data.Remove.Descr, TableItem->ID ); + FirstAutoDone = TRUE; + + #ifdef DEBUG + Auto->Print(); + #endif + } + + // delete descr + delete Record->Data.Remove.Descr; + Record->Data.Remove.Descr = NULL; + + // fill Action + TableItem->Action = ACTION_REMOVE; + + break; + + case RECORD_REPLACE: + + #ifdef DEBUG + printf("\n\n Creating automat for ID %u...", TableItem->ID ); + #endif + + TableItem->RawBeg = Record->Data.Replace.Raw; + TableItem->RawEnd = NULL; + + // mark unused pointers + Record->Data.Replace.Raw = NULL; + + // --- FINISH WITH CONSTRUCTING AUTOMAT --- + + if( Record->Data.Replace.Descr == NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n Descr is NULL...", __FILE__, __LINE__ ); + exit( 0 ); + } + + if( FirstAutoDone ) + { + HelpAuto=new DynamicAutomat; if(!HelpAuto) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + HelpAuto->StringToDynaAuto( Record->Data.Replace.Descr, TableItem->ID ); + Auto->Wampirator( *HelpAuto ); + delete HelpAuto; + + #ifdef DEBUG + Auto->Print(); + #endif + } + else + { + Auto->StringToDynaAuto( Record->Data.Replace.Descr, TableItem->ID ); + FirstAutoDone = TRUE; + + #ifdef DEBUG + Auto->Print(); + #endif + } + + // delete descr + delete Record->Data.Replace.Descr; + Record->Data.Replace.Descr = NULL; + + // fill action + TableItem->Action = ACTION_REPLACE; + + break; + + + case RECORD_RAW: + // only fill pointers, already filled + + #ifdef DEBUG + printf("\n\n Creating automat for ID %u...", TableItem->ID ); + #endif + + TableItem->RawBeg = Record->Data.Raw.RawBeg; + TableItem->RawEnd = Record->Data.Raw.RawEnd; + + // mark unused pointers + Record->Data.Raw.RawBeg = NULL; + Record->Data.Raw.RawEnd = NULL; + + // --- FINISH WITH CONSTRUCTING AUTOMAT --- + + if( Record->Data.Raw.Descr == NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n Descr is NULL...", __FILE__, __LINE__ ); + exit( 0 ); + } + + if( FirstAutoDone ) + { + HelpAuto=new DynamicAutomat; if(!HelpAuto) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + HelpAuto->StringToDynaAuto( Record->Data.Raw.Descr, TableItem->ID ); + Auto->Wampirator( *HelpAuto ); + delete HelpAuto; + + #ifdef DEBUG + Auto->Print(); + #endif + } + else + { + Auto->StringToDynaAuto( Record->Data.Raw.Descr, TableItem->ID ); + FirstAutoDone = TRUE; + + #ifdef DEBUG + Auto->Print(); + #endif + } + + // delete descr + delete Record->Data.Raw.Descr; + Record->Data.Raw.Descr = NULL; + + // fill action + if( TableItem->RawBeg==NULL && TableItem->RawEnd==NULL ) + TableItem->Action = ACTION_NO; + else + TableItem->Action = ACTION_ENCAPSULATE; + + + break; + + case RECORD_NORMAL: + + // what's round must be constructed + + // CONSTRUCT RawBeg + #ifdef DEBUG + printf("\n\n Creating automat for ID %u...", TableItem->ID ); + #endif + + Buffer[0]=0; + + if( Record->Data.Normal.Underscore ) + strcat( Buffer, ""); + if( Record->Data.Normal.Italic ) + strcat( Buffer, ""); + if( Record->Data.Normal.Bold ) + strcat( Buffer, ""); + + StartTag=TRUE; + + // font + if( Record->Data.Normal.Font !=NULL ) + { + strcat( Buffer, ""); + } + + // and fill RawBeg + if( Buffer[0]==0 ) + TableItem->RawBeg = NULL; + else + { + Lng = strlen( Buffer ); + TableItem->RawBeg = new char[Lng+1]; // allocate + if(!TableItem->RawBeg) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + strcpy( TableItem->RawBeg, Buffer ); // copy content + } + + + // CONSTRUCT RawEnd + + Buffer[0]=0; + + if( StartTag==FALSE ) + strcat( Buffer, ""); + + if( Record->Data.Normal.Bold ) + strcat( Buffer, ""); + if( Record->Data.Normal.Italic ) + strcat( Buffer, ""); + if( Record->Data.Normal.Underscore ) + strcat( Buffer, ""); + + + if( Buffer[0]==0 ) + TableItem->RawEnd = NULL; + else + { + Lng = strlen( Buffer ); + TableItem->RawEnd = new char[Lng+1]; // allocate + if(!TableItem->RawEnd) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + strcpy( TableItem->RawEnd, Buffer ); // copy content + } + + // --- FINISH WITH CONSTRUCTING AUTOMAT --- + + if( Record->Data.Normal.Descr == NULL ) + { + printf("\n ERROR reported from %s line %d:" + "\n Descr is NULL...", __FILE__, __LINE__ ); + exit( 0 ); + } + + if( FirstAutoDone ) + { + HelpAuto=new DynamicAutomat; if(!HelpAuto) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + HelpAuto->StringToDynaAuto( Record->Data.Normal.Descr, TableItem->ID ); + Auto->Wampirator( *HelpAuto ); + delete HelpAuto; + + #ifdef DEBUG + Auto->Print(); + #endif + } + else + { + Auto->StringToDynaAuto( Record->Data.Normal.Descr, TableItem->ID ); + FirstAutoDone = TRUE; + + #ifdef DEBUG + Auto->Print(); + #endif + } + + // delete descr + delete Record->Data.Normal.Descr; + Record->Data.Normal.Descr = NULL; + + // fill action + TableItem->Action = ACTION_ENCAPSULATE; + + break; + + default: + printf("\n ERROR reported from %s line %d:" + "\n More than one Setup block for one of the options...", __FILE__,__LINE__); + exit(0); + } + + // and now insert table item to list + Table->Insert( TableItem ); + + // backup record for deleting + Item = Record; + + // take the next record + Record = (DynaCfgRecord far *)(ListOfRecords->Next(Record)); + + // delete record from list ( save memory ) + ListOfRecords->Delete( Item ); + } + + #ifdef DEBUG + PrintTable(); + #endif + + delete Buffer; + + return; +} + +//--------------------------------------------------------------------------------------- + +void Semantator::PrintTable( void ) +{ + #ifdef DEBUG + + ListItem far *Item=Table->GetHead(); + + while( Item ) + { + printf("\n\n * TableItem ***********************************************"); + + ((DynaBinaryCfgTableItem far *)Item)->Print(); + + Item=Table->Next( Item ); + } + + #endif +} + +//--------------------------------------------------------------------------------------- + +void Semantator::PrintListOfRecords( void ) +{ + #ifdef DEBUG + + ListItem far *Item=ListOfRecords->GetHead(); + + while( Item ) + { + printf("\n\n * Record ***********************************************"); + + ((DynaCfgRecord far *)Item)->Print(); + + Item=ListOfRecords->Next( Item ); + } + + #endif +} + +//--------------------------------------------------------------------------------------- + +void Semantator::Save( char *FileName ) +{ + + #ifdef DEBUG + printf("\n\n Saving automat %Fp to file %s...", this, FileName ); + #endif + + int Handle; + + if((Handle = open( FileName, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, + S_IREAD | S_IWRITE)) == -1) + { + printf("\n ERROR reported from %s line %d:" + "\n Error opening file \"%s\"...", __FILE__, __LINE__, FileName ); + EXIT_PROGRAM + } + + // --- save magic --- + + if( write( Handle, "BCA", 3u ) != 3u ) ERROR_WHEN_WRITING + + // --- save options for translation --- + + if( write( Handle, &HTMLOutput, 1u ) != 1u ) ERROR_WHEN_WRITING + + if( write( Handle, &CRLF, 1u ) != 1u ) ERROR_WHEN_WRITING + + // --- save encapsulation table --- + + // save nr of items in table ( contains encapsulation things ) + if( write( Handle, &(Table->NrOfItems), 2u ) != 2u ) ERROR_WHEN_WRITING + + + ListItem far *Item=Table->GetHead(); + + while( Item ) + { + ((DynaBinaryCfgTableItem far *)Item)->Save( Handle ); + + Item=Table->Next( Item ); + } + + // --- save automat --- + + #ifdef DEBUG + Auto->Print(); + #endif + + Auto->Append( Handle ); + + // --- finish --- + + close( Handle ); + +} + +//--------------------------------------------------------------------------------------- + +void Semantator::SyntactTreeToDynamicTable( void ) +{ + // alloc File and transform syntact tree to it + File = new DynaCfgFile; if(!File) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + #ifdef DEBUG + printf("\n\n Converting syntact tree to dynamic configuration File..."); + #endif + + DiveForR3s( Root ); + + #ifdef DEBUG + printf("\n\n Deleting skelet of syntact tree ( not strings )..."); + #endif + + if( Root->Type != SNODE_R3 ) delete Root; // already deleted in DiveForR3 + + + #ifdef DEBUG + File->PrintTokens(); + #endif + + #ifdef DEBUG + printf("\n\n Converting each RecordList (== list of tokens ) to one SingleRecord..."); + #endif + + + + ListItem far *Item = File->Records->GetHead(); + DynaCfgRecord far *Record; + + ListOfRecords = new List; if(!ListOfRecords) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + while( Item ) + { + Record = new DynaCfgRecord; if(!Record) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + DynaCfgRecordListToDynaCfgRecord( ((DynaCfgRecordList far *)Item), + Record + ); + #ifdef DEBUG + printf("\n\n Token converted to record:"); Record->Print(); + #endif + + ListOfRecords->Insert( Record ); // insert newly created record + + Item=File->Records->Next(Item); + } + + #ifdef DEBUG + printf("\n\n Deleting the rest of dynamic configuration file..."); + #endif + + delete File; // no longer needed + + #ifdef DEBUG + printf("\n\n Converting list of records to dynamic table..."); + #endif + + RecordsToDynaTable(); + + #ifdef DEBUG + printf("\n\n Deleting list of records..."); + #endif + + PrintListOfRecords(); + + delete ListOfRecords; // no longer needed ( now is in table ) + + // now is in memory only Table ( declared inside Semantator class ) + + return; +} + +//- EOF --------------------------------------------------------------------------------- + + diff --git a/source/hilisem.h b/source/hilisem.h new file mode 100644 index 0000000..ac8f2b4 --- /dev/null +++ b/source/hilisem.h @@ -0,0 +1,243 @@ +#ifndef __HILISEM_H + #define __HILISEM_H + + #include "source\dynauto.h" + #include "source\hierrors.h" + #include "source\hitypes.h" + #include "source\synode.h" + #include "string.h" + + // finishes translation from hili config file to binary + + //--------------------------------------------------------------------------------- + + void QuotesAway( char far *String ); + + //- class DynaCfgFile --------------------------------------------------------- + + class far DynaCfgFile + { + public: + + List far *Records; // List of DynaCfgRecordLists then list of DynaCfgRecords + + public: + + DynaCfgFile( void ); + void inline Insert( ListItem far *InsertedItem ) { Records->Insert( InsertedItem ); } + void PrintTokens( void ); + ~DynaCfgFile(); + + }; + + //- class DynaCfgRecordList --------------------------------------------------------- + + class far DynaCfgRecordList : public ListItem + { + // record list contains tokens + + public: + + List far *Tokens; + + public: + + DynaCfgRecordList( void ); + void Print( void ); + void inline Insert( ListItem far *InsertedItem ) { Tokens->Insert( InsertedItem ); } + ~DynaCfgRecordList(); + + }; + + //- struct Token --------------------------------------------------------------- + + struct far DynaCfgToken : public ListItem + { + // Idf=String; + + // string is transformed to number: TokenType + TokenType Idf; // Element/ + // Descr/ + // Color/Size/Font/ + // RawBeg/RawEnd/ + // Setup/ + // Face_font/Title/BaseColor/BaseSize/ + // BgColor/Background + char far *String; + + void Print( void ); + virtual ~DynaCfgToken( void ); + }; + + //- struct DynaCfgRecord --------------------------------------------------------- + + struct far DynaCfgRecord : public ListItem + { + + RecordType Type; // Normal ... Element/Descr/Action/Color/Size/Font + // || + // Raw ... Element/Descr/Action/RawBeg/RawEnd + // || + // Replace ... Element/Descr/Action/Raw + // || + // Remove ... Element/Descr/Action + // || + // Setup_translation ... Output/CRLF/HTMLOutput + // || + // Setup_encapsulation ... Face_font/Title/ + // BaseColor/BaseSize/ + // BgColor/Background + + + + // for details see hitypes.h + union + { + + struct + { + char + far *Descr, + far *Font, + far *Size, + far *Color; + bool Underscore, + Italic, + Bold; + } + Normal; + + struct + { + char + far *Descr, + far *RawBeg, + far *RawEnd; + } + Raw; + + struct + { + char + far *Descr, + far *Raw; + } + Replace; + + struct + { + char + far *Descr; + } + Remove; + + struct + { + char + far *Descr; + } + No; + + struct + { + OutputType OutType; // translation block + bool CRLF, // translation block + HTMLOutput; // translation block + + char + far *Title, // page + far *FaceFont, // page + far *BaseColor, // page + far *BaseSize, // page + far *BgColor, // page, table + far *Background, // page + far *Width; // table + } + Setup; + + } + Data; + + public: + + void Print( void ); + virtual ~DynaCfgRecord( void ); + + }; + + //- struct DynaBinaryCfgTableItem --------------------------------------------------------- + + struct far DynaBinaryCfgTableItem : public ListItem + { + + // ID which automat returns when this element is accepted + ElementID ID; // - if ID==0 this struct contains beg and end + // of html page or table which is encapsulated + // using hilex + // - else contains element things, + // later will be element encapsulated + // this way: "RawBeg" Element "RawEnd" + + ActionType Action; // ACTION_ENCAPSULATE, _REPLACE, _REMOVE, _NO + + char far *RawBeg, // when Replace used as Raw + far *RawEnd; // when Encapsulate are used both + + + public: + + void Print( void ); + void Save( int Handle ); + ~DynaBinaryCfgTableItem( void ); + + }; + + //- class Semantator --------------------------------------------------------- + + class far _Semantator + { + + private: + + SyntactNode far *Root; // root of syntact tree + + List far *Table; // list of DynaBinaryCfgTableItems -> cfg file in binary form + DynamicAutomat far *Auto; // automat constructed using cfg file + + public: + + _Semantator( SyntactNode far *SyntactRoot ); + + void SyntactTreeToDynamicTable( void ); + void PrintTable( void ); + void PrintListOfRecords( void ); + void Save( char *FileName ); // saves table and automat to *.BCA + + ~_Semantator( void ); + + private: + + bool DiveForR3s( SyntactNode far *Node ); + void DiveForT4s( SyntactNode far *Node, + DynaCfgRecordList far *RecordList + ); + void WorkOnR3Subtree( SyntactNode far *Node ); + void DynaCfgRecordListToDynaCfgRecord( DynaCfgRecordList far *CfgRecordList, + DynaCfgRecord far *&Record + ); + void RecordsToDynaTable( void ); + + private: + + DynaCfgFile far *File; + List far *ListOfRecords; + }; + + typedef _Semantator Semantator; + + //- EOF ---------------------------------------------------------------------- + +#endif + + + diff --git a/source/hilist.cpp b/source/hilist.cpp new file mode 100644 index 0000000..b420ce0 --- /dev/null +++ b/source/hilist.cpp @@ -0,0 +1,282 @@ +#include "source\hilist.h" + +// print info when hunting bugs +// #define DEBUG + +//- class List methods ------------------------------------------------------- + +List::List( void ) +{ + #ifdef DEBUG + printf("\n\n List(): %luB",(unsigned long)farcoreleft() ); + #endif + + Head=new ListItem; + Tail=new ListItem; + + if( Head==NULL || Tail==NULL ) + { + printf("\n Error: not enough far memory in %s line %d...", __FILE__, __LINE__ ); + exit(0); + } + + // init + NrOfItems=0; + Head->Last=Tail->Next=NULL; + Head->Next=Tail; + Tail->Last=Head; + + #ifdef DEBUG + printf("->%luB, this 0x%Fp head 0x%Fp tail 0x%Fp", (unsigned long)farcoreleft(), this, Head, Tail ); + #endif +} + +//---------------------------------------------------------------------------- + +void List::InsertAfterHead( ListItem far *InsertedItem ) +// Inserted item is inserted not copied! +{ + if( InsertedItem ) + { + Head->Next->Last=InsertedItem; + + InsertedItem->Next=Head->Next; + InsertedItem->Last=Head; + + Head->Next=InsertedItem; + + NrOfItems++; + + #ifdef DEBUG + printf("\n Item %Fp inserted,", InsertedItem ); + #endif + } + + #ifdef DEBUG + printf(" far mem: %luB...",(unsigned long)farcoreleft() ); + #endif +} + +//---------------------------------------------------------------------------- + +void List::InsertBeforeTail( ListItem far *InsertedItem ) +// Inserted item is inserted not copied! +{ + if( InsertedItem ) + { + InsertedItem->Next=Tail; + InsertedItem->Last=Tail->Last; + + Tail->Last->Next=InsertedItem; + Tail->Last=InsertedItem; + + NrOfItems++; + + #ifdef DEBUG + printf("\n Item %Fp inserted,", InsertedItem ); + #endif + } + + #ifdef DEBUG + printf(" far mem: %luB...",(unsigned long)farcoreleft() ); + #endif +} + +//---------------------------------------------------------------------------- + +void List::PasteAtTail( ListItem far *InsHead, ListItem far *InsTail, word NrOfNewItems ) +{ + Tail->Last->Next=InsHead; + InsHead->Last=Tail->Last; + + InsTail->Next=Tail; + Tail->Last=InsTail; + + NrOfItems+=NrOfNewItems; +} + +//---------------------------------------------------------------------------- + +void List::Delete( ListItem far *DelItem ) +// DelItem points to node in queue which should be deleted +{ + if( DelItem && DelItem!=Head && DelItem!=Tail ) + { + DelItem->Last->Next=DelItem->Next; + DelItem->Next->Last=DelItem->Last; + + // must be used delete, because program evides new instances + // and if farfree( DelItem ); is used after return 0 of main + // it says Null pointer assignment... + delete DelItem; + + NrOfItems--; + + #ifdef DEBUG + printf("\n Item %Fp deleted,", DelItem ); + #endif + } + + #ifdef DEBUG + printf(" far mem: %luB...",(unsigned long)farcoreleft() ); + #endif +} + +//---------------------------------------------------------------------------- + +void List::Get( ListItem far *Item ) +// take Item out of list but DO NOT delete +{ + if( Item && Item!=Head && Item!=Tail ) + { + Item->Last->Next=Item->Next; + Item->Next->Last=Item->Last; + + NrOfItems--; + + #ifdef DEBUG + printf("\n Item %Fp taken out,", Item ); + #endif + } + + #ifdef DEBUG + printf(" far mem: %luB...",(unsigned long)farcoreleft() ); + #endif + +} + +//---------------------------------------------------------------------------- + +ListItem far *List::Next( ListItem far *Item ) +// if next is tail returns NULL +{ + if( Item->Next==Tail ) + return NULL; + else + return + Item->Next; +} + +//---------------------------------------------------------------------------- + +ListItem far *List::Last( ListItem far *Item ) +// if last is head returns NULL +{ + if( Item->Last==Head ) + return NULL; + else + return Item->Last; +} + +//---------------------------------------------------------------------------- + +ListItem far *List::GetHead( void ) +// get node head which contains data ( it's different from Head! ) +// if no data node in queue => returns NULL +{ + if( Head->Next==Tail ) + return NULL; + else + return Head->Next; +} + +//---------------------------------------------------------------------------- + +ListItem far *List::GetTail( void ) +// if no data node in queue => returns NULL +{ + if( Head->Next==Tail ) + return NULL; + else + return Tail->Last; +} + +//---------------------------------------------------------------------------- + +void List::Destroy( void ) +{ + while( Head->Next!=Tail ) Delete( Head->Next ); + + NrOfItems=0; + + #ifdef DEBUG +// printf("\n Destroy, far mem: %luB...",(unsigned long)farcoreleft() ); + #endif + + return; +} + +//---------------------------------------------------------------------------- + +void List::LeaveContent( void ) +{ + NrOfItems=0; + + Head->Last=Tail->Next=NULL; + Head->Next=Tail; + Tail->Last=Head; +} + +//---------------------------------------------------------------------------- + +bool List::Empty( void ) +{ + if( Head->Next==Tail ) + return TRUE; + else + return FALSE; +} + +//---------------------------------------------------------------------------- + +ListItem far *List::Pop( void ) +{ + ListItem far *PopItem; + + if( Head->Next != Tail ) + { + PopItem=Tail->Last; + + // change pointers + Tail->Last->Last->Next=Tail; + Tail->Last =Tail->Last->Last; + + + #ifdef DEBUG + printf("\n POP item %Fp ( not deleted )", PopItem ); + #endif + + NrOfItems--; + + return PopItem; + } + else + { + #ifdef DEBUG + printf("\n stack empty"); + #endif + + return NULL; + } +} + +//---------------------------------------------------------------------------- + +List::~List( void ) +{ + #ifdef DEBUG + printf("\n ~List() this 0x%Fp, items %u", this, NrOfItems ); + #endif + + Destroy(); + + delete Head;// is better than farfree(Head); + delete Tail;// is better than farfree(Tail); + + #ifdef DEBUG + printf(", far free: %luB...",(unsigned long)farcoreleft() ); + #endif +} + +//- EOF --------------------------------------------------------------------------- + diff --git a/source/hilist.h b/source/hilist.h new file mode 100644 index 0000000..e2268d1 --- /dev/null +++ b/source/hilist.h @@ -0,0 +1,56 @@ +#ifndef __HILIST_H + #define __HILIST_H + + #include + #include + #include + + #include "source\hierrors.h" + #include "source\hitypes.h" + + //- struct ListItem -------------------------------------------------------- + + typedef struct far _ListItem ListItem; + + struct far _ListItem + { + _ListItem far *Next, + far *Last; + + virtual ~_ListItem( void ) {}; + }; + + //- class List ------------------------------------------------------------- + + class far List + { + public: + ListItem far *Head; + ListItem far *Tail; // service head and tail are empty + // nodes + word NrOfItems; // data items ( Head, Tail not in ) + + List( void ); + void inline Insert( ListItem far *InsertedItem ) { InsertBeforeTail( InsertedItem ); } + void InsertAfterHead( ListItem far *InsertedItem ); // InsertedItem is inserted => not copied! + void InsertBeforeTail( ListItem far *InsertedItem ); // InsertedItem is inserted => not copied! + void inline Paste( ListItem far *InsHead, ListItem far *InsTail, word NrOfNewItems ) { PasteAtTail( InsHead, InsTail, NrOfNewItems ); }; + void PasteAtTail( ListItem far *InsHead, ListItem far *InsTail, word NrOfNewItems ); + void Delete( ListItem far *DelItem ); // DelItem points to node in queue which should be deleted + void Get( ListItem far *Item ); // take item out of list but DO NOT delete + ListItem far *Next( ListItem far *Item ); + ListItem far *Last( ListItem far *Item ); + ListItem far *GetHead( void ); + ListItem far *GetTail( void ); + void Destroy( void ); // destroys every data node + void LeaveContent( void ); // make list empty, nodes not destroyed + bool Empty( void ); + + void Push( ListItem far *PushedItem ) { InsertBeforeTail( PushedItem ); } + ListItem far *Pop( void ); // pop it but DO NOT delete item + + ~List(); + + }; + +#endif \ No newline at end of file diff --git a/source/hilisyn.cpp b/source/hilisyn.cpp new file mode 100644 index 0000000..f65844f --- /dev/null +++ b/source/hilisyn.cpp @@ -0,0 +1,564 @@ +#include "source\hilisyn.h" + +// print info when hunting bugs +// #define DEBUG + +#define EXIT_PROGRAM exit(0) + +//- Grammar Rights in in binary form ---------------------------------------------------------------------- + + #define NR_OF_GRAMMAR_RIGHTS 8 + + // GRights are checked from end to beg => valid items are moved to the end + // in front of grights are 0 + + GrammarRight + // * -> R + GRight1={ SNODE_STAR, { SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_R, }, 1 }, + // R -> RR + GRight2={ SNODE_R, { SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_R, + SNODE_R }, 2 }, + // R -> H(S){T} + GRight3={ SNODE_R, { SNODE_H, + SNODE_LPARENT, + SNODE_S, + SNODE_RPARENT, + SNODE_LBRACE, + SNODE_T, + SNODE_RBRACE }, 7 }, + // T -> K=S; + GRight4={ SNODE_T, { + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_K, + SNODE_EQU, + SNODE_S, + SNODE_SEMICOLON }, 4 }, + // T -> TT + GRight5={ SNODE_T, { SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_T, + SNODE_T }, 2 }, + // K -> k + GRight6={ SNODE_K, { SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_k }, 1 }, + // S -> s + GRight7={ SNODE_S, { SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_s }, 1 }, + // H -> h + GRight8={ SNODE_H, { SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_NULL, + SNODE_h }, 1 }; + +//- class Syntactator methods ---------------------------------------------------------------------------- + +Syntactator::Syntactator( char *InputFileName ) +{ + LeftStack=new List; if(!LeftStack) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + RightStack=new Lexicator; if(!RightStack) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + RightStack->PrepareForPop( InputFileName ); +} + +//----------------------------------------------------------------------------- + +Syntactator::~Syntactator( void ) +{ + delete LeftStack; + delete RightStack; +} + +//----------------------------------------------------------------------------- + + +void Syntactator::LRAnalyzer( SyntactNode far *&SyntactTree ) +{ + SyntactNode far *Element=NULL; + + while( RightStack->Pop( Element ) ) + { + if( Element ) + { + LeftStack->Push( Element ); // NODE + + ReduceLeftStack(); + } + else + { + break; + } + + #ifdef DEBUG + printf("\n-------> After POP and REDUCE, LeftStackItems %d <-------", LeftStack->NrOfItems); + #endif + } + + // print content of LeftStack + #ifdef DEBUG + printf("\n-------> State of LeftStack after SYNTACTATOR <-------"); + + Item=LeftStack->GetHead(); + + while( Item ) + { + printf("\n Type: %d", ((SyntactNode far *)Item)->Type ); + + Item=LeftStack->Next( Item ); + } + + printf("\n-------> State of LeftStack after SYNTACTATOR <-------"); + #endif + + // --- CHECK FOR ERRORS --- + + ListItem far *Item; + + // check if input worked out + dword ErrPos; + + if( !RightStack->CorrectFinish( ErrPos ) ) + { + printf("\n ERROR reported from %s line %d:" + "\n Syntact error at offset %lu in HLX cfg file." + , __FILE__, __LINE__, ErrPos ); + + // search for error + // R ... ok records + // something else -> not complete record -> error in it + // => go through stack roots while R + // => when not R print while roots not R + // => then exit + + // jump cross R + Item=LeftStack->GetHead(); + + if( Item==NULL ) + { + printf("\n Error is in the first element in cfg file..."); + exit(0); + } + else + { + printf( + "\n Unknown element, invalid keyword or missing \'\"\' block" + "\n is influenced by mistake which is right behind inside..." + "\n\n" + ); + } + + while( Item ) + { + switch( ((SyntactNode far *)Item)->Type ) + { + case SNODE_STAR: + case SNODE_R: + case SNODE_R2: + case SNODE_R3: + Item=LeftStack->Next( Item ); + continue; + default: + break; + } + break; + } + + // print !R(s) + while( Item ) + { + switch( ((SyntactNode far *)Item)->Type ) + { + case SNODE_STAR: + case SNODE_R: + case SNODE_R2: + case SNODE_R3: + break; + default: + ((SyntactNode far *)Item)->Print(); // print content of tree + Item=LeftStack->Next( Item ); + continue; + } + break; + } + + exit(0); + } + + + + // check the state of stack, there must be ONE item - R2 or R3 - + // ( because I DO NOT use gright 1 ) neterminal R2/R3 is not + // reduced to initial symbol * + + if( LeftStack->NrOfItems!=1 ) // on left stack must be right one item + { + printf("\n ERROR reported from %s line %d:" + "\n Syntact error in HLX file - LR analyzer not accepts it..." + "\n" + "\n Error was detected in this block:" + "\n" + , __FILE__, __LINE__ ); + + // search for error + // R ... ok records + // something else -> not complete record -> error in it + // => go through stack roots while R + // => when not R print while roots not R + // => then exit + + // jump cross R + Item=LeftStack->GetHead(); + + if( Item==NULL ) + { + printf("\n Input file empty?"); + exit(0); + } + + while( Item ) + { + switch( ((SyntactNode far *)Item)->Type ) + { + case SNODE_STAR: + case SNODE_R: + case SNODE_R2: + case SNODE_R3: + Item=LeftStack->Next( Item ); + continue; + default: + break; + } + break; + } + + // print !R(s) + while( Item ) + { + switch( ((SyntactNode far *)Item)->Type ) + { + case SNODE_STAR: + case SNODE_R: + case SNODE_R2: + case SNODE_R3: + break; + + case SNODE_RPARENT: + ((SyntactNode far *)Item)->Print(); // print content of tree + + if( Item->Next != LeftStack->Tail + && + ((SyntactNode far *)Item->Next)->Type!=SNODE_LBRACE + ) + { + printf("\n\n Error: Missing \'{\'."); + exit(0); + } + else + { + Item=LeftStack->Next( Item ); + continue; + } + case SNODE_H: + ((SyntactNode far *)Item)->Print(); // print content of tree + + if( Item->Next != LeftStack->Tail + && + ((SyntactNode far *)Item->Next)->Type!=SNODE_LPARENT + ) + { + printf("\n\n Error: Missing \'(\'."); + exit(0); + } + else + { + Item=LeftStack->Next( Item ); + continue; + } + + case SNODE_K: + ((SyntactNode far *)Item)->Print(); // print content of tree + + if( Item->Next != LeftStack->Tail + && + ((SyntactNode far *)Item->Next)->Type!=SNODE_EQU + ) + { + printf("\n\n Error: Missing \'=\'."); + exit(0); + } + else + { + Item=LeftStack->Next( Item ); + continue; + } + + case SNODE_S: + ((SyntactNode far *)Item)->Print(); // print content of tree + + if( Item->Next != LeftStack->Tail + && + ((SyntactNode far *)Item->Next)->Type!=SNODE_SEMICOLON + && + ((SyntactNode far *)Item->Next)->Type!=SNODE_RPARENT + ) + { + // missing ) or ; + // recognize what's before: + // H(S -> ) + // K=S -> ; + + if( ((SyntactNode far *)Item->Last)->Type==SNODE_LPARENT ) + printf("\n\n Error: Missing \')\'."); + else + printf("\n\n Error: Missing \';\'."); + + exit(0); + } + else + { + Item=LeftStack->Next( Item ); + continue; + } + + default: + ((SyntactNode far *)Item)->Print(); // print content of tree + Item=LeftStack->Next( Item ); + continue; + } + break; + } + + printf("\n\n Error: Missing \'}\'."); + + exit(0); + } + + // NO ERRORS -> SUCCESS + + // pop OK syntact tree which will be returned + SyntactTree=((SyntactNode far *)(LeftStack->Pop())); + + return; +} + +//----------------------------------------------------------------------------- + +void Syntactator::ReduceLeftStack( void ) +{ + + while( ReduceLeftStackStep() ) ; + +} + +//----------------------------------------------------------------------------- + +bool Syntactator::ReduceLeftStackStep( void ) +{ + ListItem far *Item; + SyntactNode far *SNode; + SyntactNode far *TempNode; + SyntactNodeType TopOfStack[GRAMMARRIGHT_MAXRIGHT]; + word r; + int i, + FromBack, + Height=0; // TopOfStack height <0,MAXRIGHT> + GrammarRight *Right; + bool Success; + + // create top of stack in string form + + FromBack = GRAMMARRIGHT_MAXRIGHT-1; + Item = LeftStack->GetTail(); + + // null TopOfStack + for( i=0; iType ) + { + case SNODE_R2: + case SNODE_R3: + TopOfStack[ FromBack-- ] = SNODE_R; + break; + case SNODE_T4: + case SNODE_T5: + TopOfStack[ FromBack-- ] = SNODE_T; + break; + default: + TopOfStack[ FromBack-- ] = (( SyntactNode far *)Item)->Type; + } + + // inc Height of TopOfStack + if( ++Height>=GRAMMARRIGHT_MAXRIGHT ) break; // its enough, I do not need more than MAXRIGHT + + Item=LeftStack->Last( Item); + } + + + // check what's on the top of stack with grammar rights + // DO NOT USE RIGHT 1 -> IS NOT IMPORTANT, REDUCE TO ONE "R" + for( r=2; r<=NR_OF_GRAMMAR_RIGHTS; r++ ) + { + switch( r ) + { + case 2: + Right=&GRight2; + break; + case 3: + Right=&GRight3; + break; + case 4: + Right=&GRight4; + break; + case 5: + Right=&GRight5; + break; + case 6: + Right=&GRight6; + break; + case 7: + Right=&GRight7; + break; + case 8: + Right=&GRight8; + break; + default: + EXIT_PROGRAM; + } + + // roll through the right part of the gright ( from end to front ) + + // can not reduce, top is shorter than the right part of the gright + if( Right->LngOfR > Height ) + continue; // take the next gright + + Success=TRUE; + + for( i = GRAMMARRIGHT_MAXRIGHT - 1; + i >= (int)(GRAMMARRIGHT_MAXRIGHT - Right->LngOfR); + i-- + ) + { + if( Right->R[i] != TopOfStack[i] ) + { + Success=FALSE; + break; + } + } + + // top of stack OK ( can be reduced )? + if( Success ) + { + // REDUCE ( pop from stack from BACK TO FRONT ) + switch( r ) + { + case 2: + SNode = new SyntactNode; if(!SNode) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + SNode->Type =SNODE_R2; + SNode->Data.NeterminalR2.Rr =((SyntactNode far *)(LeftStack->Pop())); + SNode->Data.NeterminalR2.Rl =((SyntactNode far *)(LeftStack->Pop())); + + LeftStack->Push( SNode ); + break; + case 3: + SNode = new SyntactNode; if(!SNode) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + SNode->Type =SNODE_R3; + TempNode =((SyntactNode far *)(LeftStack->Pop())); + delete TempNode; // its "}" no longer needed + SNode->Data.NeterminalR3.T =((SyntactNode far *)(LeftStack->Pop())); + TempNode =((SyntactNode far *)(LeftStack->Pop())); + delete TempNode; // its "{" no longer needed + TempNode =((SyntactNode far *)(LeftStack->Pop())); + delete TempNode; // its ")" no longer needed + SNode->Data.NeterminalR3.S =((SyntactNode far *)(LeftStack->Pop())); + TempNode =((SyntactNode far *)(LeftStack->Pop())); + delete TempNode; // its "(" no longer needed + SNode->Data.NeterminalR3.H =((SyntactNode far *)(LeftStack->Pop())); + + LeftStack->Push( SNode ); + break; + case 4: + SNode = new SyntactNode; if(!SNode) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + SNode->Type =SNODE_T4; + TempNode =((SyntactNode far *)(LeftStack->Pop())); + delete TempNode; // its ";" no longer needed + SNode->Data.NeterminalT4.S =((SyntactNode far *)(LeftStack->Pop())); + TempNode =((SyntactNode far *)(LeftStack->Pop())); + delete TempNode; // its "=" no longer needed + SNode->Data.NeterminalT4.K =((SyntactNode far *)(LeftStack->Pop())); + + LeftStack->Push( SNode ); + break; + case 5: + SNode = new SyntactNode; if(!SNode) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + SNode->Type =SNODE_T5; + SNode->Data.NeterminalT5.Tr =((SyntactNode far *)(LeftStack->Pop())); + SNode->Data.NeterminalT5.Tl =((SyntactNode far *)(LeftStack->Pop())); + + LeftStack->Push( SNode ); + break; + case 6: + SNode = new SyntactNode; if(!SNode) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + SNode->Type =SNODE_K; + SNode->Data.NeterminalK.k =((SyntactNode far *)(LeftStack->Pop())); + + LeftStack->Push( SNode ); + break; + case 7: + SNode = new SyntactNode; if(!SNode) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + SNode->Type =SNODE_S; + SNode->Data.NeterminalS.s =((SyntactNode far *)(LeftStack->Pop())); + + LeftStack->Push( SNode ); + break; + case 8: + SNode = new SyntactNode; if(!SNode) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + SNode->Type =SNODE_H; + SNode->Data.NeterminalH.h =((SyntactNode far *)(LeftStack->Pop())); + + LeftStack->Push( SNode ); + break; + } + + + + return TRUE; + } + + // else try the next gright + } + + return FALSE; +} + +//- EOF ---------------------------------------------------------------------- + diff --git a/source/hilisyn.h b/source/hilisyn.h new file mode 100644 index 0000000..3fa46bf --- /dev/null +++ b/source/hilisyn.h @@ -0,0 +1,81 @@ +#ifndef __HILISYN_H + #define __HILISYN_H + + #include "source\hierrors.h" + #include "source\hilist.h" + #include "source\hitypes.h" + #include "source\synode.h" + + //- Info ---------------------------------------------------------------------- + + /* + + Syntax grammar of Hilex configuration file: + + * ... initial symbol + -| ... end of input + + * -> R -| // in LR analyzer this gright is NOT used + R -> RR + + R -> H(S){T} + T -> K=S; + T -> TT + + S -> string // s + K -> keyword // k + H -> head // h + + */ + + //- struct GrammarRight --------------------------------------------------------- + + #define GRAMMARRIGHT_MAXRIGHT 7 + + struct far _GrammarRight + { + SyntactNodeType L; + SyntactNodeType R[GRAMMARRIGHT_MAXRIGHT]; + word LngOfR; + }; + + typedef _GrammarRight GrammarRight; + + // list of rights is in HILISYN.CPP + + #include "source\hililex.h" + + //- class Syntactator --------------------------------------------------------- + + class far _Syntactator + // right stack is input file + // left stack is stack where I am reduce using grammar rights + { + private: + + List far *LeftStack; // left stack - list of syntact trees + Lexicator far *RightStack; // input file divided by lexicator + + public: + + _Syntactator( char *InputFileName ); + + void LRAnalyzer( SyntactNode far *&SyntactTree ); + // checks input and + // builds syntact tree and returns + // pointer on it + + void Cancel( void ) { RightStack->CancelPop(); }; + // if some error occure frees lstack + ~_Syntactator( void ); + + private: + + void ReduceLeftStack( void ); // reduces left stack using grights + bool ReduceLeftStackStep( void ); + + }; + + typedef _Syntactator Syntactator; + +#endif \ No newline at end of file diff --git a/source/hitypes.h b/source/hitypes.h new file mode 100644 index 0000000..3ac4057 --- /dev/null +++ b/source/hitypes.h @@ -0,0 +1,176 @@ +#ifndef __HITYPES_H + #define __HITYPES_H + + //- Common types ------------------------------------------------------------------ + + typedef unsigned char bool; + typedef unsigned char byte; + typedef unsigned int word; + typedef unsigned long dword; + + + #define TRUE 1 + #define FALSE !TRUE + + //- Data types ---------------------------------------------------------------- + + enum ItemType // types of tree nodes and boxes + { + ANONYM=0, + SWITCH, // tree, box + REPEATER, // tree, box + OR, // tree, box + CONTINUE, // box + SPAINBOOT, // tree + UFO + }; + + typedef unsigned int AutoItemID; + typedef unsigned int ElementID; + + enum ListSignature + { + IN, + OK, + NOK, + NOT_A_LIST + }; + + enum SyntactNodeType + { + SNODE_NULL, + SNODE_STAR, + SNODE_R, + SNODE_R2, + SNODE_R3, + SNODE_T, + SNODE_T4, + SNODE_T5, + SNODE_K, + SNODE_S, + SNODE_H, + SNODE_LBRACE, + SNODE_RBRACE, + SNODE_LPARENT, + SNODE_RPARENT, + SNODE_EQU, + SNODE_SEMICOLON, + SNODE_k, + SNODE_s, + SNODE_h + }; + + enum TokenType + { + TOKEN_GHOST, + + TOKEN_ELEMENT =1, + TOKEN_DESCR, + TOKEN_ACTION, + TOKEN_RAW, + TOKEN_RAWBEG, + TOKEN_RAWEND, + TOKEN_FONT, + TOKEN_SIZE, + TOKEN_COLOR, + TOKEN_UNDERSCORE, + TOKEN_ITALIC, + TOKEN_BOLD, + + TOKEN_SETUP, + TOKEN_OUTPUT, + TOKEN_CRLF, + TOKEN_HTMLOUTPUT, + TOKEN_TITLE, + TOKEN_FACEFONT, + TOKEN_BASECOLOR, + TOKEN_BASESIZE, + TOKEN_BGCOLOR, + TOKEN_BACKGROUND, + TOKEN_WIDTH, + TOKEN_INTABLE, + TOKEN_OUTTABLE + }; + + + // Keywords MUST HAVE THE SAME ID AS IN TokenType - see Lexicator::Pop + // order is important! (is used when sorting ) + enum LexicatorType + { + // same as in TokenType + LEXICATOR_GHOST, + + // keywords + LEXICATOR_ELEMENT =1, // head keyword + LEXICATOR_DESCR, + LEXICATOR_ACTION, + LEXICATOR_RAW, + LEXICATOR_RAWBEG, + LEXICATOR_RAWEND, + LEXICATOR_FONT, + LEXICATOR_SIZE, + LEXICATOR_COLOR, + LEXICATOR_UNDERSCORE, + LEXICATOR_ITALIC, + LEXICATOR_BOLD, + + LEXICATOR_SETUP, // head keyword + LEXICATOR_OUTPUT, + LEXICATOR_CRLF, + LEXICATOR_HTMLOUTPUT, + LEXICATOR_TITLE, + LEXICATOR_FACEFONT, + LEXICATOR_BASECOLOR, + LEXICATOR_BASESIZE, + LEXICATOR_BGCOLOR, + LEXICATOR_BACKGROUND, + LEXICATOR_WIDTH, + LEXICATOR_INTABLE, + LEXICATOR_OUTTABLE, + + // rest of lexical elements brace {}, parent () + LEXICATOR_LBRACE, + LEXICATOR_RBRACE, + LEXICATOR_SEMICOLON, + LEXICATOR_EQU, + LEXICATOR_STRING, + LEXICATOR_COMMENTS, + LEXICATOR_LPARENT, + LEXICATOR_RPARENT + }; + + + enum RecordType + { + RECORD_SETUP_TRANSLATION, + RECORD_SETUP_PAGE, + RECORD_NORMAL, // means that encapsulate and there is color/size/... + RECORD_RAW, // means that encapsulate & rawbeg/rawend + RECORD_REPLACE, // means that replace => raw... + RECORD_REMOVE, // means that remove + RECORD_NO_ACTION, // means that no action + + RECORD_EMPTY + }; + + enum OutputType + { + NO_ENCAPS, + HTML_TABLE, + HTML_PAGE + }; + + enum ActionType + { + ACTION_NO, // ==NO action, encapsulate&&(RawBeg==RawEnd==NULL) + ACTION_ENCAPSULATE, + ACTION_REPLACE, + ACTION_REMOVE + }; + + #define INFINITY 65535u + + //- EOF --------------------------------------------------------------------- + +#endif + diff --git a/source/prefix.cpp b/source/prefix.cpp new file mode 100644 index 0000000..68e2a76 --- /dev/null +++ b/source/prefix.cpp @@ -0,0 +1,480 @@ +#include "source\prefix.h" + +// print info when hunting bugs +// #define DEBUG + +// #define DELETE_INFIX + +#define EXIT_PROGRAM exit(0) + +//- RegularString methods ---------------------------------------------------- + +RegularString::RegularString( char far *iInfix ) +{ + Infix=iInfix; + Prefix=NULL; // space allocated in time ToPrefix +} + +//-------------------------------------------------------------------------------------- + +bool RegularString::SnortleBackShlash( char far *Where, word Off ) +// Gets pointer to some char, counts \ sequence if there is +// if nr. of \ is odd => \ is valid => TRUE ... vycuchal jsem \ +// if nr. of \ is even => \ not valid it's \ itself => FALSE +// Examples when moving operation * where it should be: +// a* ... *a +// \a* ... *\a +// \\a* ... \\*a +// \\\a* ... \\*\a +// \\\\a* ... \\\\*a +// \\\\\a* ... \\\\*\a +{ + word RetVal=FALSE; + + if( Off==0xFFFF ) return FALSE; // called with 0-1 parameter + + for( ; Off>0; Off-- ) + { + if( Where[Off]=='\\' ) + RetVal=!RetVal; + else + break; + } + + if( Where[Off]=='\\' ) // treats Off==0 + RetVal=!RetVal; + + return RetVal; +} + +//-------------------------------------------------------------------------------------- + +word RegularString::BubbleLeft( word &Off, word Shift ) +// +// function: +// bubbles left +// stops on corresponding '(' or '[' or 'A' +// what's right is moved Shift positions right +// +// in Off returns the first free position from left in hole which was +// created ( in Prefix ) +{ + + + word + h=strlen(Prefix)-1, // point to last char in Prefix + p=0, + Pars=0, + PreLng; + + + // if last char is parent and has valid \ before, its default + // ( parent has common mean ) + + if( SnortleBackShlash( Prefix, h-1 ) ) + { + // before character is \ => do this: + // \(NULL + // ______\(NULL + + Prefix[h+1 +Shift]=0; // set NULL; + Prefix[h +Shift]=Prefix[h]; // move char + Prefix[h-1 +Shift]='\\'; // move \ + + Off=h-1; + + return HI_OK; + }; + + // now treat other cases... + + switch( Prefix[h] ) + { + case ')': + + // h points to valid ) + Pars=1; + + while( Pars ) + { + if( h>0 ) + h--; // move one char left + else + { + printf("\n ERROR reported from %s line %d:" + "\n in RegExp \"%s\" missing (.", __FILE__, __LINE__, Infix ); + EXIT_PROGRAM; + } + + switch( Prefix[h] ) + { + case ')': + if( !SnortleBackShlash( Prefix, h-1 ) ) // there's no valid \ + Pars++; + + break; + + case '(': + if( !SnortleBackShlash( Prefix, h-1 ) ) // there's no valid \ + Pars--; + + break; + } // switch + } // while + + // now h points to left bracket => move this bracket and + // everything what's right Shift positions right + Off=h; + + PreLng=strlen( Prefix ); // points to NULL because array counted from 0 + + for( p=PreLng+Shift; p>=h+Shift; p--) // move substring, NULL too + Prefix[p]=Prefix[p-Shift]; + + #ifdef DEBUG + // printf("\n Bubble result: \"%s\" HoleBegAt: %u", Prefix, Off ); + #endif + + return HI_OK; + + case ']': + // h points to valid ] + Pars=1; + + while( Pars ) + { + if( h>0 ) + h--; // move one char left + else + { + printf("\n ERROR reported from %s line %d:" + "\n in RegExp \"%s\" missing [.", __FILE__, __LINE__, Infix ); + EXIT_PROGRAM; + } + + if( Prefix[h] == '[' && !SnortleBackShlash( Prefix, h-1 ) ) + Pars--; + + } // while + + // now h points to left bracket => move this bracket and + // everything what's right Shift positions right + Off=h; + + PreLng=strlen( Prefix ); // points to NULL because array counted from 0 + + for( p=PreLng+Shift; p>=h+Shift; p--) // move substring, NULL too + Prefix[p]=Prefix[p-Shift]; + + #ifdef DEBUG + // printf("\n Bubble result: \"%s\" HoleBegAt: %u", Prefix, Off ); + #endif + + return HI_OK; + + default: // some switch-character: a* + + // h points to last char in prefix => to char + + if( !SnortleBackShlash( Prefix, h-1 ) ) // there's no \ + { + Prefix[h+1 +Shift]=0; // set NULL; + Prefix[h +Shift]=Prefix[h]; // move char + + Off=h; + } + else + { + // before character is \ => do this: + // \aNULL + // ______\aNULL + + Prefix[h+1 +Shift]=0; // set NULL; + Prefix[h +Shift]=Prefix[h]; // move char + Prefix[h-1 +Shift]='\\'; // move \ + + Off=h-1; + } + + + #ifdef DEBUG + // printf("\n Bubble result: \"%s\" HoleBegAt: %u", Prefix, Off ); + #endif + + return HI_OK; + + } // switch + +} + +//-------------------------------------------------------------------------------------- + +word RegularString::SayRepeaterLng( char far *Where, word Off, + word &Lng, word &Diff ) +// gets offset of valid {, returns lng of repeater type {.,.} +// other repeaters lng is fixed, see TransformRepeater head comment +// difference is difference between original txt operation and new +{ + switch( Where[Off] ) + { + case '?': + Lng=5; + Diff=4; + return HI_OK; + case '+': + Lng=9; + Diff=8; + return HI_OK; + case '*': + Lng=9; + Diff=8; + return HI_OK; + case '{': + Off--; // Off points to {, must be counted in + Lng=0; + + do + { + ++Lng; + } + while( Where[Off+Lng]!='}' && Where[Off+Lng]!=0 ); + + if( Where[Off+Lng]!=0 ) + { + Diff=Lng-1; + return Lng; + } + else + { + printf("\n ERROR reported from %s line %d:" + "\n in RegExp \"%s\" missing }.", __FILE__, __LINE__, Infix ); + EXIT_PROGRAM; + } + + default: + printf("\n ERROR reported from %s line %d:" + "\n UFO repeater in RegExp \"%s\" off %u.", __FILE__, __LINE__, Infix, Off ); + EXIT_PROGRAM; + } + return HI_OK; +} + +//-------------------------------------------------------------------------------------- + +word RegularString::TransformRepeater( word SrcOff, word DstOff ) +// Transforms repeaters to universal format - 6B wide. Text numbers are +// converted to binary form - word ( here in comments 15 means text number +// and '15'is its binary form ) +// +// Conversion is done this way: ( INFINITY==65535 ) +// ? ... {0,1} ... 5 +// + ... {1,INFINITY} ... 9 +// * ... {0,INFINITY} ... 9 +// {15} ... {15} +// {15,} ... {15,INFINITY} +// {14,15} ... {14,15 +// +// +// SrcOff is offset of text form of repeater ( in Infix ) +// DstOff is place where to store binary result ( in Prefix ) +{ + word i; + + Prefix[DstOff ]='{'; + + switch( Infix[SrcOff] ) + { + case '?': + Prefix[DstOff+1]='0'; + Prefix[DstOff+2]=','; + Prefix[DstOff+3]='1'; + Prefix[DstOff+4]='}'; + break; + + case '+': + case '*': + if( Infix[SrcOff]=='+') + Prefix[DstOff+1]='1'; + else + Prefix[DstOff+1]='0'; + + Prefix[DstOff+2]=','; + Prefix[DstOff+3]='6'; + Prefix[DstOff+4]='5'; + Prefix[DstOff+5]='5'; + Prefix[DstOff+6]='3'; + Prefix[DstOff+7]='5'; + Prefix[DstOff+8]='}'; + break; + + case '{': + // errors are already fixed in SayRepeaterLng + i=0; + + do + { + ++i; // { already done, jump across + Prefix[DstOff+i]=Infix[SrcOff+i]; + } + while( Infix[SrcOff+i]!='}' ); + + break; + } + + return HI_OK; +} + +//-------------------------------------------------------------------------------------- + +word RegularString::ToPrefix( void ) +// goes through Infix, copies normal chars to Prefix. When some operation +// moves it to right place in order Prefix notation. Transforms repeaters +// to universal format +{ + #ifdef DEBUG + printf("\n ToPrefix conversion:\n \"%s\"", Infix ); + #endif + + // ------------------------------------------ + // - Allocating vector of the STATIC LENGHT - + // ------------------------------------------ + + Prefix=(char far *)farmalloc((dword)strlen(Infix)+3000lu); // after conversion realloc is made + if( !Prefix ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); EXIT_PROGRAM; } + #ifdef DEBUG + else + printf("\n Infix strlen %lu -> allocated bytes %lu...", (dword)strlen(Infix), (dword)strlen(Infix)+3000lu ); + #endif + + + Prefix[0]=0; + + word i=0, // offset in infix + p=0, // offset in prefix + Off, + Shift, + Difference; + + while( Infix[i]!=0 ) // to the end of Infix + { + + switch( Infix[i] ) + { + case '\\': // tohle mi hlida \|, \* apod. => nemusim to testovat + + // move cross two chars - char after \ is ignored + Prefix[p++]=Infix[i++]; + Prefix[p]=0; + + Prefix[p++]=Infix[i++]; + Prefix[p]=0; + + continue; + + case '|': + + if(i==0) // "|a" has no sense - missing left argument + { + printf("\n ERROR reported from %s line %d:" + "\n In Descr=\"%s\"; missing left argument of OR operation.", __FILE__, __LINE__, Infix ); + EXIT_PROGRAM; + } + + BubbleLeft( Off, 1 ); + + Prefix[Off]=Infix[i]; // sets | + + p++; // move right in Prefix + i++; // move right in Infix + + #ifdef DEBUG + // printf("\n ToPrefix step: \"%s\"", Prefix ); + #endif + + break; + + case '?': + case '+': + case '*': + + if(i==0) + { + printf("\n ERROR reported from %s line %d:" + "\n In Descr=\"%s\"; missing left argument of repeater" + "\n -> there is nothing to repeate.", __FILE__, __LINE__, Infix ); + EXIT_PROGRAM; + } + + case '{': + + // make free space for prefix operation + SayRepeaterLng( Infix, i, Shift, Difference ); + + BubbleLeft( Off, Shift ); + + TransformRepeater( i, Off ); // transform to universal format + + #ifdef DEBUG + // printf("\n ToPrefix step: \"%s\"", Prefix ); + #endif + + p+=Difference; // were add -> correcting difference + p++; // move right in Prefix + + + if( Infix[i]=='{') i+=Difference; + i++; // move right in Infix + + break; + + case '}': + if(i==0) + { + printf("\n ERROR reported from %s line %d:" + "\n In Descr=\"%s\"; is \'}\' without \'{\'." + , __FILE__, __LINE__, Infix ); + EXIT_PROGRAM; + } + case ']': + if(i==0) + { + printf("\n ERROR reported from %s line %d:" + "\n In Descr=\"%s\"; is \']\' without \'[\'." + , __FILE__, __LINE__, Infix ); + EXIT_PROGRAM; + } + + + default: + + Prefix[p++]=Infix[i++]; + Prefix[p]=0; + } // switch + } // while + + #ifdef DEBUG + printf("\n -->\n \"%s\"", Prefix ); + #endif + + // make realloc, if fails leave as it is + char far *Ptr; + Ptr = (char far *)farrealloc(Prefix,(dword)strlen(Prefix)+1lu); + if( Ptr ) Prefix=Ptr; + + return HI_OK; +} + +//-------------------------------------------------------------------------------------- + +RegularString::~RegularString() +{ + #ifdef DELETE_INFIX + if( Infix ) farfree( Infix ); + #endif + + if( Prefix ) farfree( Prefix ); +} + +//- EOF ------------------------------------------------------------------------ + + diff --git a/source/prefix.h b/source/prefix.h new file mode 100644 index 0000000..8f10a3b --- /dev/null +++ b/source/prefix.h @@ -0,0 +1,33 @@ +#ifndef __PREFIX_H + #define __PREFIX_H + + + #include + #include + #include + #include + + #include "source\hierrors.h" + #include "source\hitypes.h" + + + class far RegularString + { + + public: + + RegularString( char far *iInfix ); + word ToPrefix( void ); + ~RegularString(); + + char far *Infix, // infix not deleted -> use it when reporting error + far *Prefix; + + private: + bool SnortleBackShlash( char far *Where, word Off ); + word BubbleLeft( word &Off, word Shift ); + word SayRepeaterLng( char far *Where, word Off, word &Lng, word &Diff ); + word TransformRepeater( word SrcOff, word DstOff ); + }; + +#endif diff --git a/source/regtree.cpp b/source/regtree.cpp new file mode 100644 index 0000000..bc77448 --- /dev/null +++ b/source/regtree.cpp @@ -0,0 +1,777 @@ +#include "source\regtree.h" + +// print info when hunting bugs +// #define DEBUG + +// print pointers in CreateSubtree +// #define SHOWPTRS + +#define REMOVESPAINBOOTS + +char far *ErrReport=NULL; // for reporting errors + +//- class RegularNode methods ----------------------------------------------------------------------------- + +RegularNode::RegularNode( ItemType iType, word &Width, char far *iExpr=NULL) +{ + word Error; + + Continue=NULL; + Type=iType; + + switch( Type ) + { + case SWITCH: + // alloc and copy space for switch + Error=CopySwitch( iExpr, Data.Switch.Expr ); // "a", "[c-f]"... + + if( Error ) + { + printf("\n ERROR reported from %s line %d:" + "\n Failed when building tree for \"%s\" (CopySwitch)...", __FILE__, __LINE__, ErrReport ); + exit(0); + } + + #ifdef DEBUG + printf("%s", Data.Switch.Expr ); + #endif + + Width=strlen( Data.Switch.Expr ); + return; + + case REPEATER: + Error= + RepeaterStringToBinary( iExpr, + Data.Repeater.From, + Data.Repeater.To, + Width + ); + + if( Error ) + { + printf("\n ERROR reported from %s line %d:" + "\n Failed when building tree for \"%s\" (RepeaterStringToBinary)...", __FILE__, __LINE__, ErrReport ); + exit(0); + } + + Data.Repeater.Son=NULL; + + #ifdef DEBUG + printf("{%u,%u}", Data.Repeater.From, Data.Repeater.To ); + #endif + return; + case OR: + Data.Or.LeftSon=NULL; + Data.Or.RightSon=NULL; + + #ifdef DEBUG + printf("|"); + #endif + + Width=1; + return; + case SPAINBOOT: + Data.SpainBoot.Son=NULL; + + #ifdef DEBUG + printf("()"); + #endif + + Width=1; + return; + default: + break; + + } +} + +//------------------------------------------------------------------------------ + +word RegularNode::CopySwitch( char far *Src, char far *&Dest ) +// accepts and copies switch +// types: +// a +// \a +// \\ +// [...] +// +// wrong input: (a), \\\, ... +{ + word e, + SrcLng; + Dest=NULL; + char far *Ptr; + + switch( Src[0] ) + { + case '\\': // type 2., type 3. + + Dest=(char far *)farmalloc(2lu+1lu); + if( !Dest ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); exit(0); } + + Dest[0]='\\'; + Dest[1]=Src[1]; + Dest[2]=0; + + return HI_OK; + + case '[': // type 4. ( errors already fixed ) + + Dest=(char far *)farmalloc( (dword)strlen(Src)+1lu ); + if( !Dest ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); exit(0); } + + SrcLng=strlen(Src); + + e=0; + + do + { + if( SrcLng<=e ) + { + printf("\n ERROR reported from %s line %d:" + "\n When building tree - missing \']\' in \"%s\"", __FILE__, __LINE__, ErrReport ); + exit(0); + } + + if( Src[e]=='\\' ) // treat [...\]...] + { + Dest[e]=Src[e]; + e++; + Dest[e]=Src[e]; + } + else + { + Dest[e]=Src[e]; + } + } + while( Src[++e]!=']' ); + + Dest[e]=Src[e]; // copy [ + e++; + Dest[e]=NULL; // make string + + // make realloc, if fails leave as it is + Ptr = (char far *)farrealloc( Dest, + (dword)strlen(Dest)+1lu + ); + if( Ptr ) + Dest=Ptr; + else + { + printf("\n ERROR reported from %s line %d:" + "\n When building tree for \"%s\" realloc fails...", __FILE__, __LINE__, ErrReport ); + exit(0); + } + + return HI_OK; + + case '|': + case '{': + case '}': + case '(': + case ')': + case ']': + printf("\n ERROR reported from %s line %d:" + "\n It's operation or parent not a switch: \'%c\'," + "\n when building tree for \"%s\"...", __FILE__, __LINE__, Src[0], ErrReport ); + exit(0); + + default: // type 1. + + Dest=(char far *)farmalloc(1lu+1lu); + if( !Dest ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); exit(0); } + + Dest[0]=Src[0]; + Dest[1]=0; + + return HI_OK; + + } // switch +} + +//------------------------------------------------------------------------------ + +word RegularNode::RepeaterStringToBinary( char far *Expr, + word &From, word &To, + word &Width ) +{ + From=To=0; + + if( !Expr ) + { + printf("\n ERROR reported from %s line %d:" + "\n repeater string Expr is NULL - when building tree for \"%s\"...", __FILE__, __LINE__, ErrReport ); + exit(0); + }; + + if( Expr[0]!='{' ) + { + printf("\n ERROR reported from %s line %d:" + "\n It's NOT repeater string: \"%s\" - when building tree for \"%s\"...", __FILE__, __LINE__, Expr, ErrReport ); + exit(0); + } + + // now try to transform it + word e=1, // pointer in Expr point after { + t=0; // pointer in Temp // ptrs point to free + char Temp[10]; + + // copy text number + while( Expr[e]>='0' && Expr[e]<='9' ) + { + Temp[t++]=Expr[e++]; + + if( t>5 ) // infinity: 65535 + { + Temp[t]=0; // t points to free -> OK + printf("\n ERROR reported from %s line %d:" + "\n too many repeater iterations: \"%s\" - when building tree for \"%s\"...", __FILE__, __LINE__, Temp, ErrReport ); + exit(0); + } + } + + Temp[t]=0; // make string + + long LongNumber; + + LongNumber=atol(Temp); + From=(word)LongNumber; // From converted + + if( Expr[e]=='}') // {15} + { + To=From; + + Width=e+1; + + return HI_OK; + } + + // else there is , + e++; + + // and now here is } (means infinity) + if( Expr[e]=='}') // {15,} + { + To=0xFFFF; + + Width=e+1; + + return HI_OK; + } + + // or number => make binary To + t=0; + + while( Expr[e]>='0' && Expr[e]<='9' ) + { + Temp[t++]=Expr[e++]; + + if( t>5 ) // infinity: 65535 + { + Temp[t]=0; // t points to free -> OK + printf("\n ERROR reported from %s line %d:" + "\n too many repeater iterations: \"%s\" - when building tree for \"%s\"...", __FILE__, __LINE__, Temp, ErrReport ); + exit(0); + } + } + + Temp[t]=0; // make string + + LongNumber=atol(Temp); + To=(word)LongNumber; // To converted + + Width=e+1; + + return HI_OK; +} + +//------------------------------------------------------------------------------ + +void RegularNode::Print( void ) +// prints info about node, used for debug +{ + switch( Type ) + { + case SWITCH: + #ifdef DEBUG + printf("%s", Data.Switch.Expr ); + #ifdef SHOWPTRS + printf("\n SWITCH %Fp : Continue %Fp\n", this, Continue ); + #endif + #endif + return; + case REPEATER: + + #ifdef DEBUG + printf("{From,To}"); // only for debug, so shema is enought + #ifdef SHOWPTRS + printf("\n REPEATER %Fp : Continue %Fp Son %Fp\n", this, Continue, Data.Repeater.Son ); + #endif + #endif + return; + case OR: + #ifdef DEBUG + printf("|"); + #ifdef SHOWPTRS + printf("\n OR %Fp : Continue %Fp LSon %Fp RSon %Fp\n", this, Continue, Data.Or.LeftSon, Data.Or.RightSon ); + #endif + #endif + return; + case SPAINBOOT: + #ifdef DEBUG + printf("()"); + #ifdef SHOWPTRS + printf("\n SPAINBOOT %Fp : Continue %Fp Son %Fp\n", this, Continue, Data.SpainBoot.Son ); + #endif + #endif + return; + } +} + +//------------------------------------------------------------------------------ + +RegularNode::~RegularNode() +{ + switch( Type ) + { + case SWITCH: + if( Data.Switch.Expr ) + farfree( Data.Switch.Expr ); + break; + case REPEATER: + case OR: + default: + break; + } +} + +//- class RegularTree methods ----------------------------------------------------------------------------- + +RegularTree::RegularTree() +{ + Root=NULL; +} + +//------------------------------------------------------------------------------ + +word RegularTree::PrefixToTree( char far *iPrefix ) +// builds tree from regular expression in prefix notation +{ + #ifdef DEBUG + printf("\n\n PrefixToTree conversion, building...\n %s\n ", iPrefix ); + #endif + + ErrReport=iPrefix; // init global + + Prefix =iPrefix; + Off=0; + + CreateSubtree( Root ); // build tree + + #ifdef REMOVESPAINBOOTS + RemoveSpainBoots(); // optimize it + #endif + + return HI_OK; +} + +//------------------------------------------------------------------------------ + +word RegularTree::CreateSubtree( RegularNode far *&RetNode, + ItemType WhoCalls + ) +// Goes from left of prefix string to right +// Calls itself recursively and all the time moving Off right, +// each call returns new Off ( kolik toho zpracoval ) +// +// Off points to free == nezpracovane +// +// -> MOVE CROSS ) RIGHT IN STRING CAN ONLY SPAINBOOT NODE, OTHERS CAN NOT <- +// so therefore its done inside its section +// +// -> REPEATER vaze ONLY NEIGHBOUR SWITCH OR () nic vic +// ( only son subtree is repeated ) <- +// so therefore parameter WhoCalls==REPEATER in this case, using this +// avoiding Continue in son and forsing continuing from repeater +// +// -> "OR" IS PROXY OF OR PARENT, SO DISTRIBUTES WhoCalls TO SONS -< +// +// in other cases WhoCalls==FALSE +{ + word Width; + RegularNode far *NewNode; + + switch( Prefix[Off] ) + { + case NULL: // return back from backtrack - end of string + NewNode=NULL; + + RetNode=NewNode; + + return HI_OK; + + case '|': // Or + + NewNode=new RegularNode( OR, Width ); + if( !NewNode ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); exit(0); } + + Off++; + + CreateSubtree( NewNode->Data.Or.LeftSon, REPEATER ); + CreateSubtree( NewNode->Data.Or.RightSon, REPEATER); + + if( WhoCalls!=REPEATER ) + CreateSubtree( NewNode->Continue ); + else + NewNode->Continue=NULL; + + RetNode=NewNode; + + #ifdef SHOWPTRS + printf("\n OR %Fp : Continue %Fp LSon %Fp RSon %Fp", NewNode, NewNode->Continue, NewNode->Data.Or.LeftSon, NewNode->Data.Or.RightSon ); + #endif + + return HI_OK; + + case '{': // Repeater + + NewNode=new RegularNode( REPEATER, Width, Prefix+Off ); + if( !NewNode ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); exit(0); } + + // roll right cross repeater + + Off+=Width; // now points to free + + // now construct what will be repeated + + CreateSubtree( NewNode->Data.Repeater.Son, REPEATER ); + CreateSubtree( NewNode->Continue ); + + RetNode=NewNode; + + #ifdef SHOWPTRS + printf("\n REPEATER %Fp : Continue %Fp Son %Fp", NewNode, NewNode->Continue, NewNode->Data.Repeater.Son ); + #endif + + return HI_OK; + + case '(': // subexpression => SpainBoot + + NewNode=new RegularNode( SPAINBOOT, Width ); + if( !NewNode ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); exit(0); } + + Off++; // now Off points behind ( + + CreateSubtree( NewNode->Data.SpainBoot.Son ); + + // now Off points to ), nobody can move across ) + // only ( section can do this ( here ) + // => section ) is leave of backtrack, from this section + // I am moving up + + Off++; // now Off points behind ) + + if( WhoCalls!=REPEATER ) + CreateSubtree( NewNode->Continue ); + else + NewNode->Continue=NULL; + + RetNode=NewNode; + + #ifdef SHOWPTRS + printf("\n SPAINBOOT %Fp : Continue %Fp Son %Fp ", NewNode, NewNode->Continue, NewNode->Data.SpainBoot.Son ); + #endif + + return HI_OK; + + case ')': // end of subexpression + + NewNode=NULL; // return back from backtrack + // cross ) I am moving only in ( section + + RetNode=NewNode; + + return HI_OK; + + default: // Switch ... '\a', '\\', '[', 'a' + + #ifdef DEBUG + printf("\n CREATE SUBTREE Width %u Prefix+Off %s...\n", Width, Prefix+Off ); + #endif + + NewNode=new RegularNode( SWITCH, Width, Prefix+Off ); + if( !NewNode ) { printf("\n ERROR in %s line %d: not enough FAR memory...", __FILE__, __LINE__ ); exit(0); } + + Off+=Width; // now points to free + + if( WhoCalls!=REPEATER ) + CreateSubtree( NewNode->Continue ); + else + NewNode->Continue=NULL; + + RetNode=NewNode; + + #ifdef SHOWPTRS + printf("\n SWITCH %Fp : Continue %Fp", NewNode, NewNode->Continue ); + #endif + + return HI_OK; + } +} + +//------------------------------------------------------------------------------ + +void RegularTree::RemoveSpainBoots( void ) +// optimizes tree: removes SpainBoots: () nodes from tree +{ + bool AddrChanged; + RegularNode far *NewAddr; + + #ifdef DEBUG + printf("\n\n Remove SPAINBOOTs - preorder before:\n"); + #ifndef SHOWPTRS + printf(" "); + #endif + + PreorderPrint( Root ); + #endif + + RemoveSpainBootsStep( Root, AddrChanged, NewAddr ); + + if( AddrChanged ) Root=NewAddr; + + #ifdef DEBUG + printf("\n\n Remove SPAINBOOTs - preorder after:\n"); + #ifndef SHOWPTRS + printf(" "); + #endif + + PreorderPrint( Root ); + #endif + + + if( AddrChanged ) Root=NewAddr; + + return; +} + +//------------------------------------------------------------------------------ + +void RegularTree::RemoveSpainBootsStep( RegularNode far *Node, + bool &AddrChanged, + RegularNode far *&NewAddr + ) +// backtrack, postorder +// if node is SpainBoot, commits suicide and returns addr of its son +{ + bool Changed; + RegularNode far *Addr, + far *RightestBrother; + + + if( Node!=NULL ) + { + + switch( Node->Type ) + { + case SWITCH: + RemoveSpainBootsStep( Node->Continue, + Changed, + Addr ); + if( Changed ) Node->Continue=Addr; + + AddrChanged=FALSE; + return; + case REPEATER: + RemoveSpainBootsStep( Node->Data.Repeater.Son, + Changed, + Addr ); + if( Changed ) Node->Data.Repeater.Son=Addr; + + RemoveSpainBootsStep( Node->Continue, + Changed, + Addr ); + if( Changed ) Node->Continue=Addr; + + AddrChanged=FALSE; + return; + case OR: + RemoveSpainBootsStep( Node->Data.Or.LeftSon, + Changed, + Addr ); + if( Changed ) Node->Data.Or.LeftSon=Addr; + + RemoveSpainBootsStep( Node->Data.Or.RightSon, + Changed, + Addr ); + if( Changed ) Node->Data.Or.RightSon=Addr; + + RemoveSpainBootsStep( Node->Continue, + Changed, + Addr ); + if( Changed ) Node->Continue=Addr; + + AddrChanged=FALSE; + return; + case SPAINBOOT: + RemoveSpainBootsStep( Node->Data.SpainBoot.Son, + Changed, + Addr ); + if( Changed ) Node->Data.SpainBoot.Son=Addr; + + RemoveSpainBootsStep( Node->Continue, + Changed, + Addr ); + if( Changed ) Node->Continue=Addr; + + + // parent (A) Continue must be redirected to son (B), + // A.Continue=B; + // + // now find end of string in son level, and redirect + // it: + // B.RightestBrother.Continue=SpainBoot.Continue + + // Before: After: + // + // A->SpainBoot->E A->B->C->D->E + // | + // | + // B->C->D->Null + + + // find the rightest Brother of SpainBoot son + RightestBrother=Node->Data.SpainBoot.Son->Continue; + + while( RightestBrother !=NULL + && + RightestBrother->Continue!=NULL + ) + { + RightestBrother=RightestBrother->Continue; + } + + if( RightestBrother!=NULL ) + RightestBrother->Continue=Node->Continue; + else // node is null + Node->Data.SpainBoot.Son->Continue=Node->Continue; + + // move up son ( Parent.Continue=Son; ) + AddrChanged=TRUE; + NewAddr=Node->Data.SpainBoot.Son; + + // now can be SpainBoot deleted + delete Node; + + return; + } // switch + } // if + else + { + // node is NULL + + AddrChanged=FALSE; + + } +} + +//------------------------------------------------------------------------------ + +void RegularTree::RootOfDeath( RegularNode far *Node ) +// kills tree by postorder with node deletion +// ( preorder print is done in time ) +{ + + if( Node!=NULL ) + { + + switch( Node->Type ) + { + case SWITCH: + Node->Print(); + RootOfDeath( Node->Continue ); + delete Node; + + return; + case REPEATER: + Node->Print(); + RootOfDeath( Node->Data.Repeater.Son ); + RootOfDeath( Node->Continue ); + delete Node; + + return; + case OR: + Node->Print(); + RootOfDeath( Node->Data.Or.LeftSon ); + RootOfDeath( Node->Data.Or.RightSon ); + RootOfDeath( Node->Continue ); + delete Node; + + return; + case SPAINBOOT: + Node->Print(); + RootOfDeath( Node->Data.SpainBoot.Son ); + RootOfDeath( Node->Continue ); + delete Node; + + return; + } // switch + } // if +} + +//------------------------------------------------------------------------------ + +void RegularTree::PreorderPrint( RegularNode far *Node ) +{ + if( Node!=NULL ) + { + + switch( Node->Type ) + { + case SWITCH: + Node->Print(); // for debug + PreorderPrint( Node->Continue ); + return; + case REPEATER: + Node->Print(); // for debug + PreorderPrint( Node->Data.Repeater.Son ); + PreorderPrint( Node->Continue ); + return; + case OR: + Node->Print(); // for debug + PreorderPrint( Node->Data.Or.LeftSon ); + PreorderPrint( Node->Data.Or.RightSon ); + PreorderPrint( Node->Continue ); + return; + case SPAINBOOT: + Node->Print(); // for debug + PreorderPrint( Node->Data.SpainBoot.Son ); + PreorderPrint( Node->Continue ); + return; + } // switch + } // if +} + +//------------------------------------------------------------------------------ + +RegularTree::~RegularTree() +{ + #ifdef DEBUG + printf("\n\n RegularTree destructor..."); + #endif + + #ifdef DEBUG + printf("\n RootOfDeath:" + "\n " + ); + #endif + + RootOfDeath( Root ); + + #ifdef DEBUG + printf("\n RegularTree destructed..."); + #endif +} + +//- EOF ----------------------------------------------------------------------------- + diff --git a/source/regtree.h b/source/regtree.h new file mode 100644 index 0000000..9f169b3 --- /dev/null +++ b/source/regtree.h @@ -0,0 +1,102 @@ +#ifndef __REGTREE_H + #define __REGTREE_H + + #include + #include + #include + #include + + #include "source\hierrors.h" + #include "source\hitypes.h" + + //- class RegularNode -------------------------------------------------------- + + class far _RegularNode + { + public: + + _RegularNode( ItemType iType, word &Width, char far *iExpr ); + void Print( void ); + ~_RegularNode(); + + ItemType Type; + _RegularNode far *Continue; + + union // specific node data + { + struct + { + _RegularNode far *LeftSon; + _RegularNode far *RightSon; + } + Or; + + struct + { + _RegularNode far *Son; // what's inside () + } + SpainBoot; + + struct + { + char far *Expr; + } + Switch; + + struct + { + word From; + word To; // INFINITY == 65535 + _RegularNode far *Son; + } + Repeater; + + + } + Data; // union + + + private: + word RepeaterStringToBinary( char far *Expr, word &From, word &To, + word &Width ); + word CopySwitch( char far *Src, char far *&Dest ); + + }; + + typedef _RegularNode RegularNode; + + //- class RegularTree -------------------------------------------------------- + + class far _RegularTree + { + public: + + _RegularTree( void ); + word PrefixToTree( char far *iPrefix ); + void PreorderPrint( RegularNode far *Node ); + ~_RegularTree(); + + + + RegularNode far *Root; + + private: + + char far *Prefix; // Used by CreateSubtree, filled by PrefixToTree + word Off; // Used by CreateSubtree, filled by PrefixToTree + + word CreateSubtree( RegularNode far *&NewNode, ItemType WhoCalls=ANONYM ); + void RemoveSpainBoots( void ); + void RemoveSpainBootsStep( RegularNode far *Node, + bool &AddrChanged, RegularNode far *&NewAddr ); + void RootOfDeath( RegularNode far *Node ); + + // char far *ErrReport; this string is global initialized in regular + // tree constructor + + }; + + typedef _RegularTree RegularTree; + +#endif + diff --git a/source/static.cpp b/source/static.cpp new file mode 100644 index 0000000..e779f8d --- /dev/null +++ b/source/static.cpp @@ -0,0 +1,635 @@ +#include "source\static.h" + +// print info when hunting bugs +// #define DEBUG + +// #define ACCEPTED_TO_FILE + +//- class StatJmpTable methods --------------------------------------------------------------------------------- + +StatJmpTable::StatJmpTable( int Handle ) +{ + + // items in table + if( read( Handle, &NrOfItems, 2u ) != 2u ) + { + printf("\n ERROR reported from %s line %d:" + "\n Error reading from file...", __FILE__, __LINE__ ); + exit(0); + } + + // load jmp table + Items=(StatJmpTableItem far *)new (StatJmpTableItem[NrOfItems]); if(!Items) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + if( read( Handle, Items, NrOfItems*sizeof(StatJmpTableItem) ) != (NrOfItems*sizeof(StatJmpTableItem)) ) + { + printf("\n ERROR reported from %s line %d:" + "\n Error reading from file...", __FILE__, __LINE__ ); + exit(0); + } + +} + +//---------------------------------------------------------------------------------- + +StatJmpTable::~StatJmpTable( void ) +{ + delete Items; +} + +//---------------------------------------------------------------------------------- + +void StatJmpTable::Print( void ) +{ + word i; + + for( i=0; iInsert( Robotek ); + } +} + +//---------------------------------------------------------------------------------- + +StaticAutomat::StaticAutomat( int Handle ) +{ + word j; + Robot far *Robotek; + + Load( Handle ); + + // alocate lists for Accept + Queue =new List; if(!Queue) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + NextStep =new List; if(!NextStep) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + StopNextStep =new List; if(!StopNextStep) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + InputStatesPool =new List; if(!InputStatesPool) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // create InputStatesPool for Accept + for( j=0; jInsert( Robotek ); + } +} + +//----------------------------------------------------------------------------- + +StaticAutomat::~StaticAutomat() +{ + word i; + + for( i=0; iPrint(); + #endif + + i++; + + } + + close( Handle ); + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +word StaticAutomat::Load( int Handle ) +{ + #ifdef DEBUG + printf("\n\n Loading static automat %Fp from file %u...", this, Handle ); + #endif + + word i; + StatJmpTable far *JumpTable; + + // NrOfStates + if( read( Handle, &NrOfItems, 2u ) != 2u ) ERROR_WHEN_READING + + // alloc an array + Engine=(StatJmpTable far **)farmalloc(sizeof(StatJmpTable far **)*NrOfItems); if(!Engine) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // NrOfInputStates + if( read( Handle, &NrOfInputItems, 2u ) != 2u ) ERROR_WHEN_READING + + // alloc an array + InputStates=(AutoItemID far *)new ( AutoItemID [NrOfInputItems]); if(!InputStates) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + + // input states self + if( read( Handle, InputStates, NrOfInputItems*sizeof(word) ) != (NrOfInputItems*sizeof(word)) ) ERROR_WHEN_READING + + // states self + for( i=0; iPrint(); + #endif + + i++; + + } + + return HI_OK; +} + +//----------------------------------------------------------------------------- + +bool StaticAutomat::Accept( Buffer far *Buf, + dword BegOff, + dword &EndOff, + LexicatorType &EleID + ) +{ + StatJmpTableItem far *EngineIDItems; + List far *Help; + Robot far *Robotek; + ListItem far *Item; + dword HelpTo, + GetCharSucc; + word j; + AutoItemID ID, + HelpID; + char C; + bool FromToFit, + StopInput, + FirstCycle; + + AcceptItem AcceptedItem; + + + + StopInput =FALSE; + + // init it to recognize that nothing was accepted + AcceptedItem.To = BegOff; // not exist smallest token + AcceptedItem.ID = INFINITY; + + // in first cycle is as input used InputStatePool + // -> cannot be deleted so detect... + FirstCycle =TRUE; + + // lists are empty -> so no reason to make them empty + #ifdef DEBUG + printf("\n %u %u %u", Queue->NrOfItems, NextStep->NrOfItems, StopNextStep->NrOfItems ); + #endif + + if( !Buf->Seek( BegOff ) ) + { + #ifdef DEBUG + printf("\n Buffer seek maked..."); + #endif + + return FALSE; + } + + // init Queue with InputStatesPool + Help = Queue; + Queue = InputStatesPool; + + + + // make one step + while( Queue->NrOfItems ) + { + + // take character from input if everybody wants it + if( StopInput ) + { + StopInput=FALSE; + } + else + { + GetCharSucc=Buf->GetChar( C ); // contains position moved see prec implementation + + if( !GetCharSucc ) + { + #ifdef DEBUG + printf("\n Buffer GetChar maked -> end of input..."); + #endif + + // Here is the end of file. For some elements is some whitespace + // required to finish accepting -> simulate this whitespace after eof... + // In GetCharSucc I have flag that I wasn't successful. + + C='\n'; // simulate whitespace, new line is the best + + } + } + + // go through robot queue + Item=Queue->Head->Next; // direct access for speedup + + while( Item != Queue->Tail ) // for each robot + { + + ID=((Robot far *)Item)->ID; + + FromToFit=FALSE; + + EngineIDItems=Engine[ID]->Items; // for speedup + + for( j=0; jNrOfItems; j++ ) // go through table + { + + if( + C>=EngineIDItems[j].From + && + C<=EngineIDItems[j].To + && + !(EngineIDItems[j].Flags&JMP_REST) + ) + { + + FromToFit=TRUE; // I am inside through from-to, rest cannot be used + + // ACCEPTING ITEM + if( EngineIDItems[j].Flags&JMP_ACCEPT ) + { + + if( EngineIDItems[j].Flags&JMP_STOP ) // if stop last char was not accepted -> dec to in this case + HelpTo=Buf->GetPos()-GetCharSucc; + else + HelpTo=Buf->GetPos(); + + if( HelpTo >= AcceptedItem.To ) // token longest and with smallest ID must be taken + { + // search for element ID ( is smaller ? ), EVERYTIME IS THE LAST ITEM IN TABLE + HelpID = EngineIDItems[ Engine[ID]->NrOfItems-1u ].JmpTo; + + if( HelpTo == AcceptedItem.To ) + { + if( AcceptedItem.ID > HelpID ) // jmp to contains ELEMENT ID + AcceptedItem.ID = HelpID; + } + else + AcceptedItem.ID = HelpID; + + AcceptedItem.To = HelpTo; + + #ifdef DEBUG + if( EngineIDItems[j].Flags&JMP_STOP ) + printf("\n step FROM-TO accept from %lu to %lu", BegOff, AcceptedItem.To ); + else + printf("\n \'%c\' step FROM-TO accept from %lu to %lu", C, BegOff, AcceptedItem.To ); + #endif + } + #ifdef DEBUG + else + { + if( EngineIDItems[j].Flags&JMP_STOP ) + printf("\n step FROM-TO NOT accept from %lu to %lu", BegOff, HelpTo ); + else + printf("\n \'%c\' step FROM-TO NOT accept from %lu to %lu", C, BegOff, HelpTo ); + } + #endif + + continue; // to for + } + + // CONTINUE THROUGH ITEM + if( + !(EngineIDItems[j].Flags&JMP_END) + ) + { + // continue through automat + + // was accepted + #ifdef DEBUG + printf("\n C \'%c\' FROM-TO -> to state %u, pos %lu", C, EngineIDItems[j].JmpTo, Buf->GetPos() ); + Engine[ID]->Print(); + #endif + + if( EngineIDItems[j].Flags&JMP_STOP ) + { + // concentrate stop robots after head + Robotek=new Robot( EngineIDItems[j].JmpTo, TRUE ); if(!Robotek) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + StopNextStep->Insert( Robotek ); + } + else + { + Robotek=new Robot( EngineIDItems[j].JmpTo ); if(!Robotek) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + NextStep->Insert( Robotek ); + } + } + + // ( next cases are ignored -> so killed when Queue destroyed ) + + } // if + else + { + + if( + FromToFit==FALSE + && + EngineIDItems[j].Flags&JMP_REST + ) + { + + + // ACCEPTING ITEM + if( EngineIDItems[j].Flags&JMP_ACCEPT ) + { + + if( EngineIDItems[j].Flags&JMP_STOP ) // if stop last char was not accepted -> dec to in this case + HelpTo=Buf->GetPos()-GetCharSucc; + else + HelpTo=Buf->GetPos(); + + if( HelpTo >= AcceptedItem.To ) // token longest and with smallest ID must be taken + { + // search for element ID ( is smaller ? ), EVERYTIME IS THE LAST ITEM IN TABLE + HelpID = EngineIDItems[ Engine[ID]->NrOfItems-1u ].JmpTo; + + if( HelpTo == AcceptedItem.To ) + { + if( AcceptedItem.ID > HelpID ) // jmp to contains ELEMENT ID + AcceptedItem.ID = HelpID; + } + else + AcceptedItem.ID = HelpID; + + AcceptedItem.To = HelpTo; + + #ifdef DEBUG + if( EngineIDItems[j].Flags&JMP_STOP ) + printf("\n step REST accept from %lu to %lu", BegOff, AcceptedItem.To ); + else + printf("\n \'%c\' step REST accept from %lu to %lu", C, BegOff, AcceptedItem.To ); + #endif + } + else + { + #ifdef DEBUG + if( EngineIDItems[j].Flags&JMP_STOP ) + printf("\n step REST NOT accept from %lu to %lu", BegOff, HelpTo ); + else + printf("\n \'%c\' step REST NOT accept from %lu to %lu", C, BegOff, HelpTo ); + #endif + } + + continue; // to for + } + + // CONTINUE THROUGH ITEM + if( + !(EngineIDItems[j].Flags&JMP_END) + ) + { + // continue through automat + + // char was accepted + #ifdef DEBUG + printf("\n C \'%c\' REST -> to state %u, pos %lu", C, EngineIDItems[j].JmpTo, Buf->GetPos() ); + #endif + + if( EngineIDItems[j].Flags&JMP_STOP ) + { + Robotek=new Robot( EngineIDItems[j].JmpTo, TRUE ); if(!Robotek) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + StopNextStep->Insert( Robotek ); + } + else + { + Robotek=new Robot( EngineIDItems[j].JmpTo ); if(!Robotek) { printf("\n ERROR reported from %s line %d:\n Not enough far memory...", __FILE__, __LINE__ ); exit(0); } + NextStep->Insert( Robotek ); + } + } + + // ( next cases are ignored -> so killed when Queue destroyed ) + + } // if + } // else + } // for + + Item = Item->Next; + } // while Item + + + + if( FirstCycle ) + { + Queue = Help; // rescue InputStatesPool items + FirstCycle = FALSE; + } + else + Queue->Destroy(); // prepare for the next step + + // Queue is now empty + + if( !(StopNextStep->NrOfItems) ) // if( StopNextStep->Empty() ) + { + // now Queue contains stop robots, and NextStepQueue is empty + + // Queue == StopNextStep == NULL + + Help=Queue; + Queue=NextStep; + NextStep=Help; + + StopInput=FALSE; + } + else + { + // continue of work on stop queue + + Help =Queue; + Queue =StopNextStep; + StopNextStep =Help; + + // NextStep stays the same + + StopInput=TRUE; + } + + // if simulating whitespace on place of EOF break away... + if( !GetCharSucc ) break; + + } // while of step + + + + // CHECK RESULTS + + + + if( AcceptedItem.ID != INFINITY ) // something was accepted + { + EndOff = AcceptedItem.To; + EleID = (LexicatorType)AcceptedItem.ID; + + #ifdef ACCEPTED_TO_FILE + Buf->Append( BegOff, AcceptedItem.To ); + #endif + + #ifdef DEBUG + printf("\n Accept RESULT from %lu to %lu ID %u", BegOff, AcceptedItem.To, AcceptedItem.ID ); + #endif + + return TRUE; + } + else + { + EndOff=BegOff; + + return FALSE; + } +} + +//----------------------------------------------------------------------------- + +void StaticAutomat::Print( void ) +{ + word i; + + #ifdef DEBUG + printf("\n\n - STATIC PRINT ------------------------------------------------------------" + "\n StaticAutomat profile:" + "\n NrOfStates: %u" + "\n NrOfInputStates: %u" + "\n ListOfInputStates:" + , + NrOfItems, + NrOfInputItems + ); + #endif + + // InputStates + for( i=0; iPrint(); + } + + #ifdef DEBUG + printf("\n - STATIC PRINT ------------------------------------------------------------\n"); + #endif +} + +//- EOF ---------------------------------------------------------------------------- diff --git a/source/static.h b/source/static.h new file mode 100644 index 0000000..b5b1afd --- /dev/null +++ b/source/static.h @@ -0,0 +1,118 @@ +#ifndef __STATIC_H + #define __STATIC_H + + #include "io.h" + #include "fcntl.h" + #include "sys\stat.h" + #include "source\buffer.h" + #include "source\dynauto.h" + #include "source\hierrors.h" + #include "source\hitypes.h" + #include "source\hilist.h" + + //- class StatJmpTable -------------------------------------------------------- + + class far StatJmpTable; + + //- class Robot ---------------------------------------------------------------- + + class far _Robot : public ListItem + { + public: + + AutoItemID ID; + bool Stop; // true if new input character NOT wanted + + public: + + _Robot( AutoItemID StartHere, bool iStop=FALSE ) { ID=StartHere; Stop=iStop; }; + + }; + + typedef _Robot Robot; + + //- struct AcceptItem -------------------------------------------------------- + + struct _AcceptItem + { + dword To; + + ElementID ID; // elementID + + void Print( void ); + }; + + typedef _AcceptItem AcceptItem; + + //- class StaticAutomat -------------------------------------------------------- + + struct far StatJmpTableItem; + + class far _StaticAutomat + { + private: + + AutoItemID NrOfItems; + word NrOfInputItems; + + StatJmpTable far **Engine; + AutoItemID far *InputStates; + + List far *InputStatesPool; // dynamic list of input states + + public: + + _StaticAutomat( char *FileName ); + _StaticAutomat( int Handle ); + bool Accept( Buffer far *Buf, + dword BegOff, dword &EndOff, + LexicatorType &EleID + ); + void Print( void ); + ~_StaticAutomat(); + + private: + word Load( char *FileName ); + word Load( int Handle ); + + // Accept lists, declared here for Accept speedup + List far *Queue, + far *NextStep, + far *StopNextStep; + + }; + + typedef _StaticAutomat StaticAutomat; + + //- class StatJmpTableItem -------------------------------------------------------- + + struct far StatJmpTableItem + { + char From, + To; + + AutoItemID JmpTo; + + byte Flags; + }; + + //- class StatJmpTable -------------------------------------------------------- + + class far StatJmpTable + { + private: + StatJmpTableItem far *Items; + word NrOfItems; + + public: + + StatJmpTable( int Handle); + friend bool StaticAutomat::Accept( Buffer far *Buf, dword BegOff, dword &EndOff, LexicatorType &EleID ); + void Print( void ); + ~StatJmpTable( void ); + + private: + word SwitchToStatJmpTable( char far *Expr ); + }; + +#endif diff --git a/source/support.cpp b/source/support.cpp new file mode 100644 index 0000000..94ba14e --- /dev/null +++ b/source/support.cpp @@ -0,0 +1,35 @@ +#include "source\support.h" + +// print info when hunting bugs +// #define DEBUG + +//- Beep ----------------------------------------------------------------------- + +void Beep( void ) +{ + sound(200); + delay(300); + nosound(); + delay(150); +} + +//- KeybWait ----------------------------------------------------------------------- + +void KeybWait( void ) +{ + while( kbhit() ); getch(); + getch(); +} + +//- KeybClear ----------------------------------------------------------------------- + +void KeybClear( void ) +{ + while( kbhit() ) getch(); +} + +//- EOF ----------------------------------------------------------------------- + + + + diff --git a/source/support.h b/source/support.h new file mode 100644 index 0000000..9b57dcf --- /dev/null +++ b/source/support.h @@ -0,0 +1,11 @@ +#ifndef __SUPPORT_H + #define __SUPPORT_H + + #include + #include + + void Beep( void ); + void KeybWait( void ); + void KeybClear( void ); + +#endif diff --git a/source/synode.cpp b/source/synode.cpp new file mode 100644 index 0000000..fccaf8a --- /dev/null +++ b/source/synode.cpp @@ -0,0 +1,359 @@ +#include "source\synode.h" + +// print info when hunting bugs +// #define DEBUG + +//- class SyntactNode methods ---------------------------------------------------------------------------- + +void SyntactNode::DeleteNodeElements( void ) +// - goes through the tree and frees s.Element and i.Element +// this function is used for explicit deleting of this elements +// In normal case are deleted in semantic analyzer +{ + switch( Type ) + { + case SNODE_R2: + Data.NeterminalR2.Rl->DeleteNodeElements(); + Data.NeterminalR2.Rr->DeleteNodeElements(); + return; + case SNODE_R3: + Data.NeterminalR3.H->DeleteNodeElements(); + Data.NeterminalR3.S->DeleteNodeElements(); + Data.NeterminalR3.T->DeleteNodeElements(); + return; + case SNODE_T4: + Data.NeterminalT4.K->DeleteNodeElements(); + Data.NeterminalT4.S->DeleteNodeElements(); + return; + case SNODE_T5: + Data.NeterminalT5.Tl->DeleteNodeElements(); + Data.NeterminalT5.Tr->DeleteNodeElements(); + return; + case SNODE_K: + Data.NeterminalK.k->DeleteNodeElements(); + return; + case SNODE_S: + Data.NeterminalS.s->DeleteNodeElements(); + return; + case SNODE_H: + Data.NeterminalH.h->DeleteNodeElements(); + return; + case SNODE_k: // leaf + // contains nothing dynamic -> return back + return; + case SNODE_s: // leaf + // delete element + if( Data.s.Element != NULL ) + delete Data.s.Element; + return; + case SNODE_h: // leaf + // contains nothing dynamic -> return back + return; + + case SNODE_LBRACE: + case SNODE_RBRACE: + case SNODE_LPARENT: + case SNODE_RPARENT: + case SNODE_SEMICOLON: + case SNODE_EQU: + case SNODE_NULL: + case SNODE_STAR: + case SNODE_R: + case SNODE_T: + + printf("\n ERROR reported from %s line %d:" + "\n Usually not created node %d in DeleteNodeElements!", + __FILE__, + __LINE__, + Type + ); + exit(0); + + default: + + // unknown node -> probably error + printf("\n ERROR reported from %s line %d:" + "\n Unknown node %d probably error!", + __FILE__, + __LINE__, + Type + ); + exit(0); + } +} + +//----------------------------------------------------------------------------- + +void SyntactNode::Print( void ) +// backtrack destructor +{ + switch( Type ) + { + case SNODE_R2: + if( Data.NeterminalR2.Rl ) Data.NeterminalR2.Rl->Print(); + if( Data.NeterminalR2.Rr ) Data.NeterminalR2.Rr->Print(); + return; + case SNODE_R3: + if( Data.NeterminalR3.H ) Data.NeterminalR3.H->Print(); + if( Data.NeterminalR3.S ) Data.NeterminalR3.S->Print(); + if( Data.NeterminalR3.T ) Data.NeterminalR3.T->Print(); + return; + case SNODE_T4: + if( Data.NeterminalT4.K ) Data.NeterminalT4.K->Print(); + printf("="); + if( Data.NeterminalT4.S ) Data.NeterminalT4.S->Print(); + printf(";\n"); + return; + case SNODE_T5: + if( Data.NeterminalT5.Tl ) Data.NeterminalT5.Tl->Print(); + if( Data.NeterminalT5.Tr ) Data.NeterminalT5.Tr->Print(); + return; + case SNODE_K: + if( Data.NeterminalK.k ) Data.NeterminalK.k->Print(); + return; + case SNODE_S: + if( Data.NeterminalS.s ) Data.NeterminalS.s->Print(); + return; + case SNODE_H: + if( Data.NeterminalH.h ) Data.NeterminalH.h->Print(); + return; + case SNODE_k: // leaf + // keywords must be printed + switch( Data.k.Key ) + { + case LEXICATOR_DESCR: // keywords + printf(" Descr"); + return; + case LEXICATOR_RAWBEG: + printf(" Raw_beg"); + return; + case LEXICATOR_RAWEND: + printf(" Raw_end"); + return; + case LEXICATOR_FONT: + printf(" Font"); + return; + case LEXICATOR_SIZE: + printf(" Size"); + return; + case LEXICATOR_COLOR: + printf(" Color"); + return; + case LEXICATOR_UNDERSCORE: + printf(" Underscore"); + return; + case LEXICATOR_ITALIC: + printf(" Italic"); + return; + case LEXICATOR_BOLD: + printf(" Bold"); + return; + case LEXICATOR_OUTPUT: + printf(" Output"); + return; + case LEXICATOR_CRLF: + printf(" CRLF"); + return; + case LEXICATOR_HTMLOUTPUT: + printf(" HTMLOut"); + return; + case LEXICATOR_TITLE: + printf(" Title"); + return; + case LEXICATOR_FACEFONT: + printf(" Face_font"); + return; + case LEXICATOR_BASECOLOR: + printf(" BaseColor"); + return; + case LEXICATOR_BASESIZE: + printf(" BaseSize"); + return; + case LEXICATOR_BGCOLOR: + printf(" BgColor"); + return; + case LEXICATOR_BACKGROUND: + printf(" Background"); + return; + case LEXICATOR_WIDTH: + printf(" Width"); + return; + default: + return; + } + case SNODE_s: // leaf + printf("%s", Data.s.Element ); + return; + case SNODE_h: // leaf + // head keywords must be printed + switch( Data.h.Key ) + { + case LEXICATOR_SETUP: // head keywords + printf(" Setup"); + return; + case LEXICATOR_ELEMENT: // head keywords + printf(" Element"); + return; + default: + return; + } + case SNODE_LBRACE: + printf("\n{\n"); + return; + case SNODE_RBRACE: + printf("\n}\n"); + return; + case SNODE_LPARENT: + printf("("); + return; + case SNODE_RPARENT: + printf(")"); + return; + case SNODE_SEMICOLON: + printf(";\n"); + return; + case SNODE_EQU: + printf("="); + return; + case SNODE_NULL: + return; + case SNODE_STAR: + case SNODE_R: + case SNODE_T: + return; + + default: + + // unknown node -> probably error + printf("\n ERROR reported from %s line %d:" + "\n Unknown node %d probably error!", + __FILE__, + __LINE__, + Type + ); + exit(0); + } +} + +//----------------------------------------------------------------------------- + +SyntactNode::~SyntactNode( void ) +// backtrack destructor +{ + switch( Type ) + { + case SNODE_R2: + #ifdef DEBUG + printf("\n v Rl %d", Type ); + #endif + if( Data.NeterminalR2.Rl ) delete Data.NeterminalR2.Rl; + #ifdef DEBUG + printf("\n v Rr %d", Type ); + #endif + if( Data.NeterminalR2.Rr ) delete Data.NeterminalR2.Rr; + return; + case SNODE_R3: + #ifdef DEBUG + printf("\n v H %d", Type ); + #endif + if( Data.NeterminalR3.H ) delete Data.NeterminalR3.H; + #ifdef DEBUG + printf("\n v S %d", Type ); + #endif + if( Data.NeterminalR3.S ) delete Data.NeterminalR3.S; + #ifdef DEBUG + printf("\n v T %d", Type ); + #endif + if( Data.NeterminalR3.T ) delete Data.NeterminalR3.T; + return; + case SNODE_T4: + #ifdef DEBUG + printf("\n v I %d", Type ); + #endif + if( Data.NeterminalT4.K ) delete Data.NeterminalT4.K; + #ifdef DEBUG + printf("\n v S %d", Type ); + #endif + if( Data.NeterminalT4.S ) delete Data.NeterminalT4.S; + return; + case SNODE_T5: + #ifdef DEBUG + printf("\n v Tl %d", Type ); + #endif + if( Data.NeterminalT5.Tl ) delete Data.NeterminalT5.Tl; + #ifdef DEBUG + printf("\n v Tr %d", Type ); + #endif + if( Data.NeterminalT5.Tr ) delete Data.NeterminalT5.Tr; + return; + case SNODE_K: + #ifdef DEBUG + printf("\n v i %d", Type ); + #endif + if( Data.NeterminalK.k ) delete Data.NeterminalK.k; + return; + case SNODE_S: + #ifdef DEBUG + printf("\n v s %d", Type ); + #endif + if( Data.NeterminalS.s ) delete Data.NeterminalS.s; + return; + case SNODE_H: + #ifdef DEBUG + printf("\n v h %d", Type ); + #endif + if( Data.NeterminalH.h ) delete Data.NeterminalH.h; + return; + case SNODE_k: // leaf + // DO NOT delete element ( deleted in semantic ) + // deepest point of backtrack + #ifdef DEBUG + printf("\n \"%s\" bottom -> returning back", Data.i.Element ); + #endif + return; + case SNODE_s: // leaf + // DO NOT delete element ( deleted in semantic ) + // deepest point of backtrack + #ifdef DEBUG + printf("\n \"%s\" bottom -> returning back", Data.s.Element ); + #endif + return; + case SNODE_h: // leaf + // DO NOT delete element ( deleted in semantic ) + // deepest point of backtrack + #ifdef DEBUG + printf("\n \"%s\" bottom -> returning back", Data.h.Element ); + #endif + return; + + case SNODE_LBRACE: + case SNODE_RBRACE: + case SNODE_LPARENT: + case SNODE_RPARENT: + case SNODE_SEMICOLON: + case SNODE_EQU: + case SNODE_NULL: + case SNODE_STAR: + case SNODE_R: + case SNODE_T: + + // do not delete nothing AND do not dive + #ifdef DEBUG + printf("\n deleting node %d", Type ); + #endif + return; + + default: + + // unknown node -> probably error + printf("\n ERROR reported from %s line %d:" + "\n Unknown node %d probably error!", + __FILE__, + __LINE__, + Type + ); + exit(0); + } +} + +//- EOF ---------------------------------------------------------------------------- diff --git a/source/synode.h b/source/synode.h new file mode 100644 index 0000000..1e64ec6 --- /dev/null +++ b/source/synode.h @@ -0,0 +1,143 @@ +#ifndef __SYNODE_H + #define __SYNODE_H + + #include "source\hierrors.h" + #include "source\hilist.h" + #include "source\hitypes.h" + + //- struct SyntactNode --------------------------------------------------------- + + struct far _SyntactNode : public ListItem + { + + SyntactNodeType Type; + + // Union type: + // SNODE_NULL, + // SNODE_STAR, + // SNODE_R, + // SNODE_R2, + // SNODE_R3, + // SNODE_T, + // SNODE_T4, + // SNODE_T5, + // SNODE_K, + // SNODE_S, + // SNODE_H, + // SNODE_LBRACE, + // SNODE_RBRACE, + // SNODE_LPARENT, + // SNODE_RPARENT, + // SNODE_EQU, + // SNODE_SEMICOLON, + // SNODE_k, + // SNODE_s, + // SNODE_h + + // constant nodes {}();= are not constructed -> SAVING MEM + + union + { + + struct + { + _SyntactNode far *R; + } + Star; + + struct + { + _SyntactNode far *Rl; + _SyntactNode far *Rr; + } + NeterminalR2; + + struct + { + _SyntactNode far *H; + //_SyntactNode far *Lp; // constant node ( + _SyntactNode far *S; + //_SyntactNode far *Rp; // constant node ) + //_SyntactNode far *Lb; // constant node { + _SyntactNode far *T; + //_SyntactNode far *Rb; // constant node } + } + NeterminalR3; + + struct + { + _SyntactNode far *K; + //_SyntactNode far *Equ; // constant node = + _SyntactNode far *S; + //_SyntactNode far *Semicolon; // constant node ; + } + NeterminalT4; + + struct + { + _SyntactNode far *Tl; + _SyntactNode far *Tr; + } + NeterminalT5; + + struct + { + _SyntactNode far *k; // point to LexicalElement containing ID of keyword + } + NeterminalK; + + struct + { + _SyntactNode far *s; // point to LexicalElement containing string + } + NeterminalS; + + struct + { + _SyntactNode far *h; // point to LexicalElement containing ID of head keyword + } + NeterminalH; + + struct + { + ElementID ID; // contains SNODE_s + dword Beg; + dword End; + char far *Element; + } + s; // string + + struct + { + ElementID ID; + TokenType Key; // contains enum ID of keyword + // DESCR, RAW_BEG, ... + // ( see hitypes.h ) + } + k; // keyword + + struct + { + ElementID ID; + TokenType Key; // contains enum ID of head keywords + // ELEMENT or SETUP + // ( see hitypes.h ) + } + h; // head keyword + + } + Data; + + + + public: + + void DeleteNodeElements( void ); + void Print( void ); // for printing error - not debuged + ~_SyntactNode( void ); + + }; + + typedef _SyntactNode SyntactNode; + +#endif diff --git a/toexplor.hlx b/toexplor.hlx new file mode 100644 index 0000000..ba7290b --- /dev/null +++ b/toexplor.hlx @@ -0,0 +1,52 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for LITESTEP switching +# Shell => Explorer +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION") +{ + Output ="NO_ENCAPS"; # HTML_PAGE or HTML_TABLE or NO_ENCAPS + + CRLF ="FALSE"; # add CRs to output ( Unix hates them ) + HtmlOutput ="FALSE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#000080"; + BaseSize ="+1"; + BgColor ="#606060"; +} + +#--------------------------------------------------------------------------------- + +Element( "Line where shell is specified" ) +{ + Descr="shell[^\n]*\n"; + + Action="Replace"; + + # making new line + Raw="shell=Explorer.exe +"; + +} + +#--------------------------------------------------------------------------------- + +Element( "Other lines" ) +{ + Descr="[^\n]+"; + + Action="NO"; +} + +#--------------------------------------------------------------------------------- diff --git a/tolite.hlx b/tolite.hlx new file mode 100644 index 0000000..c26897e --- /dev/null +++ b/tolite.hlx @@ -0,0 +1,53 @@ +#--------------------------------------------------------------------------------- +# +# Configuration file for LITESTEP switching +# Shell => litestep +# +# +# by Dvorka +# +#--------------------------------------------------------------------------------- + +Setup( "TRANSLATION") +{ + Output ="NO_ENCAPS"; # HTML_PAGE or HTML_TABLE or NO_ENCAPS + + CRLF ="FALSE"; # add CRs to output ( Unix hates them ) + HtmlOutput ="FALSE"; # convert < to < ... +} + +#--------------------------------------------------------------------------------- + +Setup( "ENCAPSULATION" ) +{ + Face_font ="COURIER NEW"; + Title ="HILEX translated source"; + BaseColor ="#000080"; + BaseSize ="+1"; + BgColor ="#606060"; +} + +#--------------------------------------------------------------------------------- + +Element( "Line where shell is specified" ) +{ + Descr="shell[^\n]*\n"; + + Action="Replace"; + + # making new line + Raw="shell=c:\\litestep\\litestep.exe +"; + +} + +#--------------------------------------------------------------------------------- + +Element( "Other lines" ) +{ + Descr="[^\n]+"; + + Action="NO"; +} + +#---------------------------------------------------------------------------------