From ee130973e28f09ec3a234f4296ec604736703f98 Mon Sep 17 00:00:00 2001 From: Abu Abacus Date: Sat, 3 Jan 2026 18:31:15 +0100 Subject: [PATCH] Initial check in docu --- doc/grammars/calc/calc.dpr | 36 + doc/grammars/calc/calc.txt | 5 + doc/grammars/calc/calcLexer.g | 46 ++ doc/grammars/calc/calcParser.g | 92 +++ doc/grammars/calc/readme.txt | 10 + doc/grammars/filter/filter.g | 43 ++ doc/grammars/filter/filter.pas | 234 +++++++ doc/grammars/filter/filterTokens.pas | 19 + doc/grammars/filter/filterTokens.txt | 7 + doc/grammars/multiLexer/JavaDocLexer.pas | 367 ++++++++++ doc/grammars/multiLexer/JavaDocTokens.pas | 21 + doc/grammars/multiLexer/JavaDocTokens.txt | 9 + doc/grammars/multiLexer/JavaLexer.pas | 286 ++++++++ doc/grammars/multiLexer/JavaTokens.pas | 25 + doc/grammars/multiLexer/JavaTokens.txt | 13 + doc/grammars/multiLexer/demo.dpr | 49 ++ doc/grammars/multiLexer/javaDocLexer.g | 76 +++ doc/grammars/multiLexer/javaLexer.g | 68 ++ doc/grammars/multiLexer/javaParser.g | 20 + doc/grammars/multiLexer/javaParser.pas | 91 +++ doc/grammars/multiLexer/javaParserTokens.pas | 25 + doc/grammars/multiLexer/javaParserTokens.txt | 13 + doc/grammars/multiLexer/test.in | 20 + doc/grammars/pascal/readme.txt | 10 + doc/grammars/pascal/tools/ast/ast.pas | 359 ++++++++++ doc/grammars/pascal/tools/ast/astProgram.pas | 12 + doc/grammars/pascal/wirth/block.gif | Bin 0 -> 14973 bytes doc/grammars/pascal/wirth/expr.gif | Bin 0 -> 11612 bytes doc/grammars/pascal/wirth/idconst.gif | Bin 0 -> 11694 bytes doc/grammars/pascal/wirth/stmt.gif | Bin 0 -> 21053 bytes doc/grammars/pascal/wirth/test/wpTest.dpr | 38 ++ doc/grammars/pascal/wirth/test/wpTest.dproj | 107 +++ doc/grammars/pascal/wirth/test/x.pas | 13 + doc/grammars/pascal/wirth/type.gif | Bin 0 -> 16095 bytes doc/grammars/pascal/wirth/var.gif | Bin 0 -> 13619 bytes doc/grammars/pascal/wirth/wpLex.pas | 607 +++++++++++++++++ doc/grammars/pascal/wirth/wpPar.pas | 418 ++++++++++++ doc/grammars/pascal/wp.dpr | 42 ++ doc/grammars/pascal/wpLexer.g | 237 +++++++ doc/grammars/pascal/wpParser.g | 368 +++++++++++ doc/tutorial/calc/calc.dpr | 36 + doc/tutorial/calc/calc.txt | 5 + doc/tutorial/calc/calcLexer.g | 49 ++ doc/tutorial/calc/calcLexer.pas | 430 ++++++++++++ doc/tutorial/calc/calcLexerTokens.pas | 24 + doc/tutorial/calc/calcLexerTokens.txt | 12 + doc/tutorial/calc/calcParser.g | 93 +++ doc/tutorial/calc/calcParser.pas | 203 ++++++ doc/tutorial/calc/calcParserTokens.pas | 24 + doc/tutorial/calc/calcParserTokens.txt | 12 + doc/tutorial/calc/readme.txt | 11 + doc/tutorial/hoc/hoc 1/hocLexer.g | 91 +++ doc/tutorial/hoc/hoc 1/hocLexer.pas | 505 ++++++++++++++ doc/tutorial/hoc/hoc 1/hocLexerTokens.pas | 26 + doc/tutorial/hoc/hoc 1/hocLexerTokens.txt | 14 + doc/tutorial/hoc/hoc 1/hocParser.g | 101 +++ doc/tutorial/hoc/hoc 1/hocParser.pas | 170 +++++ doc/tutorial/hoc/hoc 1/hocParserTokens.pas | 26 + doc/tutorial/hoc/hoc 1/hocParserTokens.txt | 14 + doc/tutorial/old/filter/filter.g | 43 ++ doc/tutorial/old/filter/filter.pas | 234 +++++++ doc/tutorial/old/filter/filterTokens.pas | 19 + doc/tutorial/old/filter/filterTokens.txt | 7 + doc/tutorial/old/multiLexer/JavaDocLexer.pas | 367 ++++++++++ doc/tutorial/old/multiLexer/JavaDocTokens.pas | 21 + doc/tutorial/old/multiLexer/JavaDocTokens.txt | 9 + doc/tutorial/old/multiLexer/JavaLexer.pas | 286 ++++++++ doc/tutorial/old/multiLexer/JavaTokens.pas | 25 + doc/tutorial/old/multiLexer/JavaTokens.txt | 13 + doc/tutorial/old/multiLexer/demo.dpr | 49 ++ doc/tutorial/old/multiLexer/javaDocLexer.g | 76 +++ doc/tutorial/old/multiLexer/javaLexer.g | 68 ++ doc/tutorial/old/multiLexer/javaParser.g | 20 + doc/tutorial/old/multiLexer/javaParser.pas | 91 +++ .../old/multiLexer/javaParserTokens.pas | 25 + .../old/multiLexer/javaParserTokens.txt | 13 + doc/tutorial/old/multiLexer/test.in | 20 + doc/usersguide/dpg.pdf | Bin 0 -> 108056 bytes doc/usersguide/dpg.tex | 36 + doc/usersguide/src/app/app-grammar.tex | 625 ++++++++++++++++++ doc/usersguide/src/error/error-err.tex | 77 +++ doc/usersguide/src/error/error.tex | 0 doc/usersguide/src/gram/gram.tex | 53 ++ doc/usersguide/src/intro/intro.tex | 63 ++ doc/usersguide/src/lang/lang-atomprod.tex | 40 ++ doc/usersguide/src/lang/lang-err.tex | 77 +++ doc/usersguide/src/lang/lang-opt.tex | 265 ++++++++ doc/usersguide/src/lang/lang-prodoper.tex | 41 ++ doc/usersguide/src/lang/lang-rest.tex | 82 +++ doc/usersguide/src/lang/lang-sect.tex | 249 +++++++ doc/usersguide/src/lang/lang-simpprod.tex | 79 +++ doc/usersguide/src/lang/lang-syntactic.tex | 49 ++ doc/usersguide/src/lang/lang.tex | 10 + doc/usersguide/src/rt/rt-err.tex | 94 +++ doc/usersguide/src/rt/rt.tex | 3 + doc/usersguide/src/start/start.tex | 200 ++++++ doc/usersguide/src/tokens/tokens.tex | 281 ++++++++ doc/usersguide/zlbook.cls | 88 +++ 98 files changed, 9430 insertions(+) create mode 100644 doc/grammars/calc/calc.dpr create mode 100644 doc/grammars/calc/calc.txt create mode 100644 doc/grammars/calc/calcLexer.g create mode 100644 doc/grammars/calc/calcParser.g create mode 100644 doc/grammars/calc/readme.txt create mode 100644 doc/grammars/filter/filter.g create mode 100644 doc/grammars/filter/filter.pas create mode 100644 doc/grammars/filter/filterTokens.pas create mode 100644 doc/grammars/filter/filterTokens.txt create mode 100644 doc/grammars/multiLexer/JavaDocLexer.pas create mode 100644 doc/grammars/multiLexer/JavaDocTokens.pas create mode 100644 doc/grammars/multiLexer/JavaDocTokens.txt create mode 100644 doc/grammars/multiLexer/JavaLexer.pas create mode 100644 doc/grammars/multiLexer/JavaTokens.pas create mode 100644 doc/grammars/multiLexer/JavaTokens.txt create mode 100644 doc/grammars/multiLexer/demo.dpr create mode 100644 doc/grammars/multiLexer/javaDocLexer.g create mode 100644 doc/grammars/multiLexer/javaLexer.g create mode 100644 doc/grammars/multiLexer/javaParser.g create mode 100644 doc/grammars/multiLexer/javaParser.pas create mode 100644 doc/grammars/multiLexer/javaParserTokens.pas create mode 100644 doc/grammars/multiLexer/javaParserTokens.txt create mode 100644 doc/grammars/multiLexer/test.in create mode 100644 doc/grammars/pascal/readme.txt create mode 100644 doc/grammars/pascal/tools/ast/ast.pas create mode 100644 doc/grammars/pascal/tools/ast/astProgram.pas create mode 100644 doc/grammars/pascal/wirth/block.gif create mode 100644 doc/grammars/pascal/wirth/expr.gif create mode 100644 doc/grammars/pascal/wirth/idconst.gif create mode 100644 doc/grammars/pascal/wirth/stmt.gif create mode 100644 doc/grammars/pascal/wirth/test/wpTest.dpr create mode 100644 doc/grammars/pascal/wirth/test/wpTest.dproj create mode 100644 doc/grammars/pascal/wirth/test/x.pas create mode 100644 doc/grammars/pascal/wirth/type.gif create mode 100644 doc/grammars/pascal/wirth/var.gif create mode 100644 doc/grammars/pascal/wirth/wpLex.pas create mode 100644 doc/grammars/pascal/wirth/wpPar.pas create mode 100644 doc/grammars/pascal/wp.dpr create mode 100644 doc/grammars/pascal/wpLexer.g create mode 100644 doc/grammars/pascal/wpParser.g create mode 100644 doc/tutorial/calc/calc.dpr create mode 100644 doc/tutorial/calc/calc.txt create mode 100644 doc/tutorial/calc/calcLexer.g create mode 100644 doc/tutorial/calc/calcLexer.pas create mode 100644 doc/tutorial/calc/calcLexerTokens.pas create mode 100644 doc/tutorial/calc/calcLexerTokens.txt create mode 100644 doc/tutorial/calc/calcParser.g create mode 100644 doc/tutorial/calc/calcParser.pas create mode 100644 doc/tutorial/calc/calcParserTokens.pas create mode 100644 doc/tutorial/calc/calcParserTokens.txt create mode 100644 doc/tutorial/calc/readme.txt create mode 100644 doc/tutorial/hoc/hoc 1/hocLexer.g create mode 100644 doc/tutorial/hoc/hoc 1/hocLexer.pas create mode 100644 doc/tutorial/hoc/hoc 1/hocLexerTokens.pas create mode 100644 doc/tutorial/hoc/hoc 1/hocLexerTokens.txt create mode 100644 doc/tutorial/hoc/hoc 1/hocParser.g create mode 100644 doc/tutorial/hoc/hoc 1/hocParser.pas create mode 100644 doc/tutorial/hoc/hoc 1/hocParserTokens.pas create mode 100644 doc/tutorial/hoc/hoc 1/hocParserTokens.txt create mode 100644 doc/tutorial/old/filter/filter.g create mode 100644 doc/tutorial/old/filter/filter.pas create mode 100644 doc/tutorial/old/filter/filterTokens.pas create mode 100644 doc/tutorial/old/filter/filterTokens.txt create mode 100644 doc/tutorial/old/multiLexer/JavaDocLexer.pas create mode 100644 doc/tutorial/old/multiLexer/JavaDocTokens.pas create mode 100644 doc/tutorial/old/multiLexer/JavaDocTokens.txt create mode 100644 doc/tutorial/old/multiLexer/JavaLexer.pas create mode 100644 doc/tutorial/old/multiLexer/JavaTokens.pas create mode 100644 doc/tutorial/old/multiLexer/JavaTokens.txt create mode 100644 doc/tutorial/old/multiLexer/demo.dpr create mode 100644 doc/tutorial/old/multiLexer/javaDocLexer.g create mode 100644 doc/tutorial/old/multiLexer/javaLexer.g create mode 100644 doc/tutorial/old/multiLexer/javaParser.g create mode 100644 doc/tutorial/old/multiLexer/javaParser.pas create mode 100644 doc/tutorial/old/multiLexer/javaParserTokens.pas create mode 100644 doc/tutorial/old/multiLexer/javaParserTokens.txt create mode 100644 doc/tutorial/old/multiLexer/test.in create mode 100644 doc/usersguide/dpg.pdf create mode 100644 doc/usersguide/dpg.tex create mode 100644 doc/usersguide/src/app/app-grammar.tex create mode 100644 doc/usersguide/src/error/error-err.tex create mode 100644 doc/usersguide/src/error/error.tex create mode 100644 doc/usersguide/src/gram/gram.tex create mode 100644 doc/usersguide/src/intro/intro.tex create mode 100644 doc/usersguide/src/lang/lang-atomprod.tex create mode 100644 doc/usersguide/src/lang/lang-err.tex create mode 100644 doc/usersguide/src/lang/lang-opt.tex create mode 100644 doc/usersguide/src/lang/lang-prodoper.tex create mode 100644 doc/usersguide/src/lang/lang-rest.tex create mode 100644 doc/usersguide/src/lang/lang-sect.tex create mode 100644 doc/usersguide/src/lang/lang-simpprod.tex create mode 100644 doc/usersguide/src/lang/lang-syntactic.tex create mode 100644 doc/usersguide/src/lang/lang.tex create mode 100644 doc/usersguide/src/rt/rt-err.tex create mode 100644 doc/usersguide/src/rt/rt.tex create mode 100644 doc/usersguide/src/start/start.tex create mode 100644 doc/usersguide/src/tokens/tokens.tex create mode 100644 doc/usersguide/zlbook.cls diff --git a/doc/grammars/calc/calc.dpr b/doc/grammars/calc/calc.dpr new file mode 100644 index 0000000..0c90e80 --- /dev/null +++ b/doc/grammars/calc/calc.dpr @@ -0,0 +1,36 @@ +program calc; + +{$APPTYPE CONSOLE} + +uses + Classes, + SysUtils, + calcLexer in 'calcLexer.pas', + calcParser in 'calcParser.pas'; + +var + stm: TFileStream; + lex: TcalcLexer; + par: TcalcParser; + +begin + if ParamCount <> 1 then + begin + writeln('usage: calc '); + exit; + end + else + begin + try + stm := TFileStream.Create( ParamStr(1), fmOpenRead); + lex := TcalcLexer.Create(stm); + par := TcalcParser.Create(lex); + + par.calc; + except + end; + end; + + stm.Free; + par.Free; +end. diff --git a/doc/grammars/calc/calc.txt b/doc/grammars/calc/calc.txt new file mode 100644 index 0000000..fb388c7 --- /dev/null +++ b/doc/grammars/calc/calc.txt @@ -0,0 +1,5 @@ +1+2+3+4+5+6+7+8+9; +(((((2+3))))); +(-1*(-2*(-3*(-4+ -5)))); +(-1*(-2*(-3*(-4+ 5)))); +7 * -(-9); \ No newline at end of file diff --git a/doc/grammars/calc/calcLexer.g b/doc/grammars/calc/calcLexer.g new file mode 100644 index 0000000..d7cd232 --- /dev/null +++ b/doc/grammars/calc/calcLexer.g @@ -0,0 +1,46 @@ +// ============================================================================ +// Demo lexer for a four operator calculator +// ============================================================================ +unit calcLexer; + +lexer TcalcLexer; +options +{ + exportVocab = calcLexer; + k = 2; +} + +// ============================================================================ +// Simple tokens +// ============================================================================ +LPAREN : '('; +RPAREN : ')'; + +PLUS : '+'; +MINUS : '-'; +STAR : '*'; +SLASH : '/'; + +SEMI : ';'; + +// ============================================================================ +// INT +// ============================================================================ +INT : ('0'..'9')+; + +// ============================================================================ +// White space +// ============================================================================ +WS + : + ( + '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | '\t' { tab; } + | ' ' + ) + { + _ttype := TT_SKIP; + } + ; diff --git a/doc/grammars/calc/calcParser.g b/doc/grammars/calc/calcParser.g new file mode 100644 index 0000000..cdc7cbf --- /dev/null +++ b/doc/grammars/calc/calcParser.g @@ -0,0 +1,92 @@ +// ============================================================================ +// Demo parser for four operator calculator +// ============================================================================ +unit calcParser; + +parser TcalcParser; +options +{ + importVocab = calcLexer; + exportVocab = calcParser; +} +memberdecl +{ + value : integer; +} + +// ============================================================================ +// calc +// ============================================================================ +calc + : (expression SEMI {writeln(value);} )+ + ; + + +// ============================================================================ +// expression +// ============================================================================ +expression + : simpleExpression + ; + +// ============================================================================ +// simpleExpression +// ============================================================================ +simpleExpression +local +{ + temp: integer; +} + : term { temp := value; } + ( + PLUS term { temp := temp + value; } + | MINUS term { temp := temp - value; } + )* { value := temp; } + ; + +// ============================================================================ +// term +// ============================================================================ +term +local +{ + temp: integer; +} + : factor { temp := value; } + ( + STAR factor { temp := temp * value; } + | SLASH factor { temp := temp div value; } + )* { value := temp; } + ; + +// ============================================================================ +// factor +// ============================================================================ +factor +local +{ + s: integer; +} +{ + s := 1; +} + : + ( + PLUS { s := 1; } + | MINUS { s := -1; } + )? + ( + uInt + | LPAREN expression RPAREN + ) + { + value := s * value; + } + ; + +// ============================================================================ +// uInt +// ============================================================================ +uInt + : x:INT { value := StrToInt( x.TokenText); } + ; diff --git a/doc/grammars/calc/readme.txt b/doc/grammars/calc/readme.txt new file mode 100644 index 0000000..15c7183 --- /dev/null +++ b/doc/grammars/calc/readme.txt @@ -0,0 +1,10 @@ +To build demo project you must first compile the grammars. + +1. Open calc.dpp in DPG +2. Press F9 to compile the grammars + +After the compilation the project can be opened in delphi. Be sure that the dpg +runtime library is in the delphi library path. (In the project settings, +or in the environment settings). + +Have fun... \ No newline at end of file diff --git a/doc/grammars/filter/filter.g b/doc/grammars/filter/filter.g new file mode 100644 index 0000000..fcddd47 --- /dev/null +++ b/doc/grammars/filter/filter.g @@ -0,0 +1,43 @@ +unit filter; + +lexer Tfilter; +options +{ + k = 2; + filter = true; +} + +// ---------------------------------------------------------------------------- +// Paragraph +// ---------------------------------------------------------------------------- +P + : "

" + ; + +// ---------------------------------------------------------------------------- +// Break +// ---------------------------------------------------------------------------- +BR + : "
" + ; + +// ---------------------------------------------------------------------------- +// Newline +// ---------------------------------------------------------------------------- +NEWLINE + : + ( + '\r' '\n' { newLine; _ttype := TT_SKIP; } + | '\r' { newLine; _ttype := TT_SKIP; } + | '\n' { newLine; _ttype := TT_SKIP; } + ) + ; + +// ---------------------------------------------------------------------------- +// Tab +// ---------------------------------------------------------------------------- +TAB + : '\t' { tab; _ttype := TT_SKIP; } + ; + + diff --git a/doc/grammars/filter/filter.pas b/doc/grammars/filter/filter.pas new file mode 100644 index 0000000..94c5345 --- /dev/null +++ b/doc/grammars/filter/filter.pas @@ -0,0 +1,234 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.78r +// Grammar: filter.g +// ============================================================================ +unit filter; + +interface + +uses + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTypes, + filterTokens, + SysUtils; + +type + // ========================================================================= + // Class Tfilter declaration + // ========================================================================= + Tfilter = class( TdpgLexer) + + protected // Public grammar rules ("rescoped") + procedure mP ( pCreate: boolean); + procedure mBR ( pCreate: boolean); + procedure mNEWLINE ( pCreate: boolean); + procedure mTAB ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mP +// ============================================================================ +procedure Tfilter.mP( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_P; + + match('

'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mBR +// ============================================================================ +procedure Tfilter.mBR( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_BR; + + match('
'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mNEWLINE +// ============================================================================ +procedure Tfilter.mNEWLINE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_NEWLINE; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + newLine; _ttype := TT_SKIP; + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; _ttype := TT_SKIP; + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; _ttype := TT_SKIP; + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#10,#13], FileName, Line, Column); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mTAB +// ============================================================================ +procedure Tfilter.mTAB( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_TAB; + + match(#9); + tab; _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function Tfilter.NextToken : IdpgToken; +begin + while( true) do + begin + ResetText; + + try + if (( LA(1) in ['<']) and (LA(2) in ['p'])) then + begin + mP(true); + result := fReturnToken; + end + + else if (( LA(1) in ['<']) and (LA(2) in ['b'])) then + begin + mBR(true); + result := fReturnToken; + end + + else if (( LA(1) in [#10,#13])) then + begin + mNEWLINE(true); + result := fReturnToken; + end + + else if (( LA(1) in [#9])) then + begin + mTAB(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + begin + consume; + continue; + end; + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + consume; + continue; + end; + end; +end; + +end. diff --git a/doc/grammars/filter/filterTokens.pas b/doc/grammars/filter/filterTokens.pas new file mode 100644 index 0000000..b20bca4 --- /dev/null +++ b/doc/grammars/filter/filterTokens.pas @@ -0,0 +1,19 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.78r +// Grammar: filter.g +// ============================================================================ +unit filterTokens; + +interface + +const + TT_EOF = 1; + TT_P = 4; + TT_BR = 5; + TT_NEWLINE = 6; + TT_TAB = 7; + +implementation +end. diff --git a/doc/grammars/filter/filterTokens.txt b/doc/grammars/filter/filterTokens.txt new file mode 100644 index 0000000..a93fffe --- /dev/null +++ b/doc/grammars/filter/filterTokens.txt @@ -0,0 +1,7 @@ +// $Delphi Parser Generator: filter.pas -> TfilterTokens.txt$ +Tfilter +TT_EOF=1 +TT_P=4 +TT_BR=5 +TT_NEWLINE=6 +TT_TAB=7 diff --git a/doc/grammars/multiLexer/JavaDocLexer.pas b/doc/grammars/multiLexer/JavaDocLexer.pas new file mode 100644 index 0000000..2652451 --- /dev/null +++ b/doc/grammars/multiLexer/JavaDocLexer.pas @@ -0,0 +1,367 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javadoclexer.g +// ============================================================================ +unit JavaDocLexer; + +interface + +uses + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTokenStreamSelector, + dpgTypes, + JavaDocTokens, + SysUtils; + +type + // ========================================================================= + // Class TJavaDocLexer declaration + // ========================================================================= + TJavaDocLexer = class( TdpgLexer) + + public + Selector : IdpgTokenStreamSelector; + + protected // Protected grammar rules + procedure mID ( pCreate: boolean); + + protected // Public grammar rules ("rescoped") + procedure mPARAM ( pCreate: boolean); + procedure mEXCEPTION ( pCreate: boolean); + procedure mSTAR ( pCreate: boolean); + procedure mJAVADOC_CLOSE ( pCreate: boolean); + procedure mNEWLINE ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mPARAM +// ============================================================================ +procedure TJavaDocLexer.mPARAM( pCreate: boolean); +var + _begin: integer; + _cnt_3: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_PARAM; + + match('@param'); + _cnt_3 := 0; + + while(true) do + begin + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else + begin + if _cnt_3 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), [' '], FileName, Line, Column); + end; + + INC(_cnt_3); + end; + mID(false); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mID +// ============================================================================ +procedure TJavaDocLexer.mID( pCreate: boolean); +var + _begin: integer; + _cnt_9: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_ID; + + _cnt_9 := 0; + + while(true) do + begin + if (( LA(1) in ['a'..'z'])) then + begin + match( ['a'..'z']); + end + + else + begin + if _cnt_9 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), ['a'..'z'], FileName, Line, Column); + end; + + INC(_cnt_9); + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mEXCEPTION +// ============================================================================ +procedure TJavaDocLexer.mEXCEPTION( pCreate: boolean); +var + _begin: integer; + _cnt_6: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_EXCEPTION; + + match('@exception'); + _cnt_6 := 0; + + while(true) do + begin + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else + begin + if _cnt_6 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), [' '], FileName, Line, Column); + end; + + INC(_cnt_6); + end; + mID(false); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mSTAR +// ============================================================================ +procedure TJavaDocLexer.mSTAR( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_STAR; + + match('*'); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mJAVADOC_CLOSE +// ============================================================================ +procedure TJavaDocLexer.mJAVADOC_CLOSE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_JAVADOC_CLOSE; + + match('*/'); + Selector.Pop; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mNEWLINE +// ============================================================================ +procedure TJavaDocLexer.mNEWLINE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_NEWLINE; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#10,#13], FileName, Line, Column); + newLine; + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function TJavaDocLexer.NextToken : IdpgToken; +var + la1 : char; + la2 : char; +begin + while( true) do + begin + ResetText; + + try + la1 := LA(1); + la2 := LA(2); + + if (( LA(1) in ['@']) and (LA(2) in ['p'])) then + begin + mPARAM(true); + result := fReturnToken; + end + + else if (( LA(1) in ['@']) and (LA(2) in ['e'])) then + begin + mEXCEPTION(true); + result := fReturnToken; + end + + else if (( LA(1) in ['*']) and (LA(2) in ['/'])) then + begin + mJAVADOC_CLOSE(true); + result := fReturnToken; + end + + else if (( LA(1) in ['*'])) then + begin + mSTAR(true); + result := fReturnToken; + end + + else if (( LA(1) in [#10,#13])) then + begin + mNEWLINE(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + begin + consume; + continue; + end; + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + consume; + continue; + end; + end; +end; + +end. diff --git a/doc/grammars/multiLexer/JavaDocTokens.pas b/doc/grammars/multiLexer/JavaDocTokens.pas new file mode 100644 index 0000000..8aa1885 --- /dev/null +++ b/doc/grammars/multiLexer/JavaDocTokens.pas @@ -0,0 +1,21 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javadoclexer.g +// ============================================================================ +unit JavaDocTokens; + +interface + +const + TT_EOF = 1; + TT_PARAM = 4; + TT_EXCEPTION = 5; + TT_ID = 6; + TT_STAR = 7; + TT_JAVADOC_CLOSE = 8; + TT_NEWLINE = 9; + +implementation +end. diff --git a/doc/grammars/multiLexer/JavaDocTokens.txt b/doc/grammars/multiLexer/JavaDocTokens.txt new file mode 100644 index 0000000..10a1496 --- /dev/null +++ b/doc/grammars/multiLexer/JavaDocTokens.txt @@ -0,0 +1,9 @@ +// $Delphi Parser Generator: JavaDocLexer.pas -> TJavaDocLexerTokens.txt$ +TJavaDocLexer +TT_EOF=1 +TT_PARAM=4 +TT_EXCEPTION=5 +TT_ID=6 +TT_STAR=7 +TT_JAVADOC_CLOSE=8 +TT_NEWLINE=9 diff --git a/doc/grammars/multiLexer/JavaLexer.pas b/doc/grammars/multiLexer/JavaLexer.pas new file mode 100644 index 0000000..206dcd5 --- /dev/null +++ b/doc/grammars/multiLexer/JavaLexer.pas @@ -0,0 +1,286 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javalexer.g +// ============================================================================ +unit JavaLexer; + +interface + +uses + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTokenStreamSelector, + dpgTypes, + JavaTokens, + SysUtils; + +type + // ========================================================================= + // Class TJavaLexer declaration + // ========================================================================= + TJavaLexer = class( TdpgLexer) + + public + Selector : IdpgTokenStreamSelector; + + protected // Internals + procedure initialize; override; + + protected // Public grammar rules ("rescoped") + procedure mSEMI ( pCreate: boolean); + procedure mJAVADOC_OPEN ( pCreate: boolean); + procedure mID ( pCreate: boolean); + procedure mWS ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mSEMI +// ============================================================================ +procedure TJavaLexer.mSEMI( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_SEMI; + + match(';'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mJAVADOC_OPEN +// ============================================================================ +procedure TJavaLexer.mJAVADOC_OPEN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_JAVADOC_OPEN; + + match('/**'); + Selector.Push('docLexer'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mID +// ============================================================================ +procedure TJavaLexer.mID( pCreate: boolean); +var + _begin: integer; + _cnt_5: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_ID; + + _cnt_5 := 0; + + while(true) do + begin + if (( LA(1) in ['a'..'z'])) then + begin + match( ['a'..'z']); + end + + else + begin + if _cnt_5 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), ['a'..'z'], FileName, Line, Column); + end; + + INC(_cnt_5); + end; + _ttype := testLit( _ttype); + + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mWS +// ============================================================================ +procedure TJavaLexer.mWS( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_WS; + + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else if (( LA(1) in [#9])) then + begin + match(#9); + end + + else if (( LA(1) in [#10,#13])) then + begin + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#10,#13], FileName, Line, Column); + newLine; + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#9..#10,#13,' '], FileName, Line, Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function TJavaLexer.NextToken : IdpgToken; +var + _first : TdpgCharSet; + +begin + _first := [#9..#10,#13,' ','/',';','a'..'z']; + + while( true) do + begin + ResetText; + + try + if (( LA(1) in [';'])) then + begin + mSEMI(true); + result := fReturnToken; + end + + else if (( LA(1) in ['/'])) then + begin + mJAVADOC_OPEN(true); + result := fReturnToken; + end + + else if (( LA(1) in ['a'..'z'])) then + begin + mID(true); + result := fReturnToken; + end + + else if (( LA(1) in [#9..#10,#13,' '])) then + begin + mWS(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + Raise EdpgMismatchedChar.Create(LA(1), _first, FileName, Line, Column); + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + Raise; + end; + end; +end; + +// ---------------------------------------------------------------------------- +// InitLiterals +// ---------------------------------------------------------------------------- +procedure TJavaLexer.initialize; +begin + fLiterals.Add('int', 10); +end; + +end. diff --git a/doc/grammars/multiLexer/JavaTokens.pas b/doc/grammars/multiLexer/JavaTokens.pas new file mode 100644 index 0000000..e4cef1e --- /dev/null +++ b/doc/grammars/multiLexer/JavaTokens.pas @@ -0,0 +1,25 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javalexer.g +// ============================================================================ +unit JavaTokens; + +interface + +const + TT_EOF = 1; + TT_PARAM = 4; + TT_EXCEPTION = 5; + TT_ID = 6; + TT_STAR = 7; + TT_JAVADOC_CLOSE = 8; + TT_NEWLINE = 9; + LT_int = 10; + TT_SEMI = 11; + TT_JAVADOC_OPEN = 12; + TT_WS = 13; + +implementation +end. diff --git a/doc/grammars/multiLexer/JavaTokens.txt b/doc/grammars/multiLexer/JavaTokens.txt new file mode 100644 index 0000000..1965254 --- /dev/null +++ b/doc/grammars/multiLexer/JavaTokens.txt @@ -0,0 +1,13 @@ +// $Delphi Parser Generator: JavaLexer.pas -> TJavaLexerTokens.txt$ +TJavaLexer +TT_EOF=1 +TT_PARAM=4 +TT_EXCEPTION=5 +TT_ID=6 +TT_STAR=7 +TT_JAVADOC_CLOSE=8 +TT_NEWLINE=9 +LT_int="int"=10 +TT_SEMI=11 +TT_JAVADOC_OPEN=12 +TT_WS=13 diff --git a/doc/grammars/multiLexer/demo.dpr b/doc/grammars/multiLexer/demo.dpr new file mode 100644 index 0000000..ac84a45 --- /dev/null +++ b/doc/grammars/multiLexer/demo.dpr @@ -0,0 +1,49 @@ +program demo; + +{$APPTYPE CONSOLE} + +uses + Classes, + SysUtils, + dpgTokenStreamSelector, + javaLexer, + javaDocLexer, + javaParser; + +var + stm : TFileStream; + lexJava : TJavaLexer; + lexJavaDoc : TJavaDocLexer; + parJava : TJavaParser; + sel : TdpgTokenStreamSelector; + +begin + if ParamCount = 1 then + begin + try + stm := TFileStream.Create( ParamStr(1), fmOpenRead); + sel := TdpgTokenStreamSelector.Create; + + lexJava := TJavaLexer.Create( stm); + lexJavaDoc := TJavaDocLexer.Create( lexJava.InputState); + + lexJava.Selector := sel; + lexJavaDoc.Selector := sel; + + sel.add( lexJava, 'main'); + sel.add( lexJavaDoc, 'docLexer'); + sel.select( 'main'); + + parJava := TJavaParser.Create( sel); + + parJava.input; + except + writeln('Exception...'); + end; + end; + + + + + { TODO -oUser -cConsole Main : Insert code here } +end. diff --git a/doc/grammars/multiLexer/javaDocLexer.g b/doc/grammars/multiLexer/javaDocLexer.g new file mode 100644 index 0000000..1e5ddb7 --- /dev/null +++ b/doc/grammars/multiLexer/javaDocLexer.g @@ -0,0 +1,76 @@ +unit JavaDocLexer; + +uses +{ + dpgTokenStreamSelector; +} + +lexer TJavaDocLexer; +options +{ + k = 2; + exportVocab = JavaDoc; + filter = true; +} + +memberdecl +{ + public + Selector : IdpgTokenStreamSelector; +} + +// ---------------------------------------------------------------------------- +// @param +// ---------------------------------------------------------------------------- +PARAM + : "@param" (' ')+ ID + ; + +// ---------------------------------------------------------------------------- +// @exception +// ---------------------------------------------------------------------------- +EXCEPTION + : "@exception" (' ')+ ID + ; + +// ---------------------------------------------------------------------------- +// identifier +// ---------------------------------------------------------------------------- +protected ID + : ('a'..'z')+ + ; + +// ---------------------------------------------------------------------------- +// Star +// +// This rule simply prevents JAVADOC_CLOSE from being called for every '*' in +// a comment. Calling JAVADOC_CLOSE will fail for simple '*' and cause an +// exception, which is slow. In other words, the grammar will work without +// this rule, but is slower. +// ---------------------------------------------------------------------------- +STAR + : '*' { _ttype := TT_SKIP; } + ; + +// ---------------------------------------------------------------------------- +// JavaDocClose +// ---------------------------------------------------------------------------- +JAVADOC_CLOSE + : "*/" { Selector.Pop; } + ; + +// ---------------------------------------------------------------------------- +// NewLine +// ---------------------------------------------------------------------------- +NEWLINE + : + ( + '\r' '\n' + | '\r' + | '\n' + ) + { + newLine; + _ttype := TT_SKIP; + } + ; \ No newline at end of file diff --git a/doc/grammars/multiLexer/javaLexer.g b/doc/grammars/multiLexer/javaLexer.g new file mode 100644 index 0000000..caff66b --- /dev/null +++ b/doc/grammars/multiLexer/javaLexer.g @@ -0,0 +1,68 @@ +unit JavaLexer; + +uses +{ + dpgTokenStreamSelector; +} + +lexer TJavaLexer; +options +{ + k = 2; + importVocab = JavaDoc; + exportVocab = Java; +} + +tokens +{ + "int"; +} + +memberdecl +{ + public + Selector : IdpgTokenStreamSelector; +} + +// ---------------------------------------------------------------------------- +// Simple tokens +// ---------------------------------------------------------------------------- +SEMI : ';'; + +// ---------------------------------------------------------------------------- +// JavaDocOpen +// ---------------------------------------------------------------------------- +JAVADOC_OPEN + : "/**" { Selector.Push('docLexer'); } + ; + +// ---------------------------------------------------------------------------- +// Identifier +// ---------------------------------------------------------------------------- +ID +options +{ + testLiterals = true; +} + : ('a'..'z')+ + ; + +WS + : + ( + ' ' + | '\t' + | + ( + '\r' '\n' + | '\r' + | '\n' + ) + { + newLine; + } + ) + { + _ttype := TT_SKIP; + } + ; \ No newline at end of file diff --git a/doc/grammars/multiLexer/javaParser.g b/doc/grammars/multiLexer/javaParser.g new file mode 100644 index 0000000..f46b339 --- /dev/null +++ b/doc/grammars/multiLexer/javaParser.g @@ -0,0 +1,20 @@ +unit javaParser; + +parser TJavaParser; +options +{ + k = 2; + importVocab = Java; +} + +input + : ( (javadoc)? "int" ID SEMI)+ + ; + +javadoc + : + JAVADOC_OPEN + (PARAM)? + (EXCEPTION)? + JAVADOC_CLOSE + ; \ No newline at end of file diff --git a/doc/grammars/multiLexer/javaParser.pas b/doc/grammars/multiLexer/javaParser.pas new file mode 100644 index 0000000..8754de0 --- /dev/null +++ b/doc/grammars/multiLexer/javaParser.pas @@ -0,0 +1,91 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javaparser.g +// ============================================================================ +unit javaParser; + +interface + +uses + Classes, + Contnrs, + dpgLLkParser, + dpgToken, + dpgTypes, + javaParserTokens, + SysUtils; + +type + // ========================================================================= + // Class TJavaParser declaration + // ========================================================================= + TJavaParser = class( TdpgLLkParser) + + public // Public grammar rules + procedure input ; + procedure javadoc ; + + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedToken; + +// ============================================================================ +// input +// ============================================================================ +procedure TJavaParser.input; +var + _cnt_4: integer; + +begin + _cnt_4 := 0; + + while(true) do + begin + if (( LA(1) in [LT_int,TT_JAVADOC_OPEN])) then + begin + if (( LA(1) in [TT_JAVADOC_OPEN])) then + begin + javadoc; + end; + match(LT_int); + match(TT_ID); + match(TT_SEMI); + end + + else + begin + if _cnt_4 >= 1 then + break + else + Raise EdpgMismatchedToken.Create( LT(1), [LT_int,TT_JAVADOC_OPEN], FileName); + end; + + INC(_cnt_4); + end; +end; + +// ============================================================================ +// javadoc +// ============================================================================ +procedure TJavaParser.javadoc; +begin + + match(TT_JAVADOC_OPEN); + if (( LA(1) in [TT_PARAM])) then + begin + match(TT_PARAM); + end; + if (( LA(1) in [TT_EXCEPTION])) then + begin + match(TT_EXCEPTION); + end; + match(TT_JAVADOC_CLOSE); +end; + +end. diff --git a/doc/grammars/multiLexer/javaParserTokens.pas b/doc/grammars/multiLexer/javaParserTokens.pas new file mode 100644 index 0000000..86767a1 --- /dev/null +++ b/doc/grammars/multiLexer/javaParserTokens.pas @@ -0,0 +1,25 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javaparser.g +// ============================================================================ +unit javaParserTokens; + +interface + +const + TT_EOF = 1; + TT_PARAM = 4; + TT_EXCEPTION = 5; + TT_ID = 6; + TT_STAR = 7; + TT_JAVADOC_CLOSE = 8; + TT_NEWLINE = 9; + LT_int = 10; + TT_SEMI = 11; + TT_JAVADOC_OPEN = 12; + TT_WS = 13; + +implementation +end. diff --git a/doc/grammars/multiLexer/javaParserTokens.txt b/doc/grammars/multiLexer/javaParserTokens.txt new file mode 100644 index 0000000..b11fbb9 --- /dev/null +++ b/doc/grammars/multiLexer/javaParserTokens.txt @@ -0,0 +1,13 @@ +// $Delphi Parser Generator: javaParser.pas -> TJavaParserTokens.txt$ +TJavaParser +TT_EOF=1 +TT_PARAM=4 +TT_EXCEPTION=5 +TT_ID=6 +TT_STAR=7 +TT_JAVADOC_CLOSE=8 +TT_NEWLINE=9 +LT_int="int"=10 +TT_SEMI=11 +TT_JAVADOC_OPEN=12 +TT_WS=13 diff --git a/doc/grammars/multiLexer/test.in b/doc/grammars/multiLexer/test.in new file mode 100644 index 0000000..b50f9fd --- /dev/null +++ b/doc/grammars/multiLexer/test.in @@ -0,0 +1,20 @@ +/** a javadoc comment + * @param foo + * @exception bar + * Just a little text for a comment + */ +int abc; + +/** a javadoc comment + * @param foo + * @exception bar + * Just a little text for a comment + */ +int zzz; + +/** a javadoc comment + * @param foo + * @exception bar + * Just a little text for a comment + */ +int xxx; diff --git a/doc/grammars/pascal/readme.txt b/doc/grammars/pascal/readme.txt new file mode 100644 index 0000000..23d3a5a --- /dev/null +++ b/doc/grammars/pascal/readme.txt @@ -0,0 +1,10 @@ +To build a project you must first compile the grammars. + +After the compilation the project can be opened in delphi. Be sure that the dpg +runtime library is in the delphi library path. (In the project settings, +or in the environment settings). + +Have fun... + +ps.: I'm not sure that the grammar is correct, or not... + This is only for showing dpg features... \ No newline at end of file diff --git a/doc/grammars/pascal/tools/ast/ast.pas b/doc/grammars/pascal/tools/ast/ast.pas new file mode 100644 index 0000000..58e3b52 --- /dev/null +++ b/doc/grammars/pascal/tools/ast/ast.pas @@ -0,0 +1,359 @@ +{ + * A Child-Sibling Tree. + * + * A tree with PLUS at the root and with two children 3 and 4 is + * structured as: + * + * PLUS + * | + * 3 -- 4 + * + * and can be specified easily in LISP notation as + * + * (PLUS 3 4) + * + * where every '(' starts a new subtree. + * + * These trees are particular useful for translators because of + * the flexibility of the children lists. They are also very easy + * to walk automatically, whereas trees with specific children + * reference fields can't easily be walked automatically. + * + * This class contains the basic support for an AST. + * Most people will create ASTs that are subclasses of + * BaseAST or of CommonAST. + */ +} +unit ast; + +interface +uses + Classes, + Generics.Collections; +// dpgrtl.Token; + + +type + TAST = class; + TASTList = TList; + + TAST = class + protected + fDown : TAST; + fRight : TAST; + + fAstText : AnsiString; + fAstType : integer; + fAstLine : integer; + fAstColumn : integer; + + private + fVerbose : boolean; // verbose string conversion + fTokenNames : TStringList; + + private + procedure DoFindAll( NodeToSearch : TAST; + // v : Vector; + Target : TAST; + PartialMatch : boolean); + + protected + function GetNumberofChildren: integer; + + function GetEquals( Node : TAST): boolean; virtual; + function GetEqualsList( Node : TAST): boolean; virtual; + function GetEqualsListPartial( Node : TAST): boolean; virtual; + function GetEqualsTree( Node : TAST): boolean; virtual; + function GetEqualsTreePartial( Node : TAST): boolean; virtual; + + function GetTokenNames : TStringList; + + procedure SetVerbose( Verbose : boolean; + Names : TStringList); + + public + procedure Initialize( AstType : integer; + AstText : AnsiString); overload; virtual; abstract; + + procedure Initialize( Node : TAST); overload; virtual; abstract; +// procedure Initialize( Token : TToken); overload; virtual; abstract; + + procedure AddChild( node: TAST); + procedure RemoveChildren; + + public + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + public + property NumberOfChildren : integer read GetNumberofChildren; + + property NextSibling : TAST read fRight write fRight; + property FirstChild : TAST read fDown write fDown; + + property AstText : AnsiString read fAstText write fAstText; + property AstType : integer read fAstType write fAstType; + property AstLine : integer read fAstLine write fAstLine; + property AstColumn : integer read fAstColumn write fAstColumn; + + property Equals [n: TAST]: boolean read GetEquals; + property EqualsList [n: TAST]: boolean read GetEqualsList; + property EqualsListPartial [n: TAST]: boolean read GetEqualsListPartial; + property EqualsTree [n: TAST]: boolean read GetEqualsTree; + property EqualsTreePartial [n: TAST]: boolean read GetEqualsTreepartial; + end; + + TASTClass = class of TAST; + + +implementation + +{ TastBase } + +procedure TAST.AfterConstruction; +begin + inherited; + fTokenNames := TStringList.Create; +end; + +procedure TAST.BeforeDestruction; +begin + fTokenNames.Free; + inherited; +end; + +// ================================================================================================ +// DoFindAll +// ================================================================================================ +procedure TAST.DoFindAll(NodeToSearch, Target: TAST; PartialMatch: boolean); +var + sibling : TAST; + child : TAST; + +begin + // start walking sibling lists, looking for matches + sibling := NodeToSearch; + + while Assigned(sibling) do + begin + if ( PartialMatch and sibling.EqualsTreePartial[Target]) or + ( not PartialMatch and sibling.EqualsTree[Target]) then + // v.appendelement(sibling) + ; + + if Assigned( sibling.FirstChild) then + DoFindAll( sibling.FirstChild, {v,} Target, PartialMatch); + + sibling := sibling.NextSibling + end; + +end; + + +// ================================================================================================ +// Get Number of Children +// ================================================================================================ +function TAST.GetNumberofChildren: integer; +var + t: TAST; + n: integer; + +begin + t := fDown; + n := 0; + + if Assigned(t) then + begin + INC(n); + + while Assigned(t.fRight) do + begin + t := t.fRight; + INC(n) + end; + end; + + result := n +end; + +// ================================================================================================ +// Get Equals +// ================================================================================================ +function TAST.GetEquals(Node: TAST): boolean; +begin + if Assigned(Node) + then result := (Node.fAstText = fAstText) and (Node.fAstType = fAstType) + else result := false +end; + +// ================================================================================================ +// Get Equals List +// ================================================================================================ +function TAST.GetEqualsList(Node: TAST): boolean; +var + sibling: TAST; + +begin + result := false; + + if Assigned(Node) then + begin + sibling := self; + + while Assigned(sibling) and Assigned(Node) do + begin + // as a quick optimization, check roots firt + if not sibling.Equals[Node] then + break; + + // if roots match, do full list match test on children + if Assigned( sibling.FirstChild) then + begin + if not sibling.FirstChild.EqualsList[Node.FirstChild] then + break + end + + // sibling has no kids, make sure Node doesn't either + else if Assigned(Node.FirstChild) then + break; + + sibling := sibling .NextSibling; + Node := Node .NextSibling; + end; + + if not Assigned(sibling) and not Assigned(Node) then + result := true + end; +end; + +// ================================================================================================ +// Get Equals List Partial +// +// Is Node a subtree of this list ? The siblings of the root are NOT ignored. +// ================================================================================================ +function TAST.GetEqualsListPartial(Node: TAST): boolean; +var + sibling: TAST; + +begin + result := false; + + if Assigned(Node) then + begin + sibling := self; + + while Assigned(sibling) and Assigned(Node) do + begin + // as a quick optimization, check roots firt + if not sibling.Equals[Node] then + break; + + // if roots match, do partial list match test on children + if Assigned( sibling.FirstChild) then + if not sibling.FirstChild.EqualsListPartial[Node.FirstChild] then + break + end; + + if not Assigned(sibling) and Assigned(Node) + then result := false + else result := true + end; +end; + +// ================================================================================================ +// Get Equals Tree +// +// Is the tree rooted at *self* equals to *Node* ? +// The sibling of *self* are ignored. +// ================================================================================================ +function TAST.GetEqualsTree(Node: TAST): boolean; +begin + result := false; + + if Equals[Node] then + begin + // if roots match, do full list match test on children + if Assigned(FirstChild) then + begin + if not FirstChild.EqualsList[Node.FirstChild] then + exit; + end + + // No kids, make sure *Node* hasn't either + else if Assigned(Node.FirstChild) then + exit; + end; + + result := true +end; + +// ================================================================================================ +// Get Equals Tree Partial +// ================================================================================================ +function TAST.GetEqualsTreePartial(Node: TAST): boolean; +begin + result := false; + + if Equals[Node] then + if Assigned(FirstChild) then + if not FirstChild.EqualsListPartial[Node] then + exit; + + result := true +end; + +// ================================================================================================ +// Get Token Names +// ================================================================================================ +function TAST.GetTokenNames: TStringList; +begin + result := TStringList.Create; + result.AddStrings(fTokenNames); +end; + +// ================================================================================================ +// Set Verbose +// ================================================================================================ +procedure TAST.SetVerbose(Verbose: boolean; Names: TStringList); +begin + fVerbose := Verbose; + fTokenNames.Clear; + ftokenNames.AddStrings(Names); +end; + +// ================================================================================================ +// AddChild +// ================================================================================================ +procedure TAST.AddChild(node: TAST); +var + n: TAST; + +begin + if Assigned(node) then + begin + n := fDown; + + if Assigned(n) then + begin + while Assigned(n.fRight) do + n := n.fRight; + + n.fRight := node + end + + else + fDown := node + end; +end; + +// ================================================================================================ +// Remove Children +// ================================================================================================ +procedure TAST.RemoveChildren; +begin + fDown := nil +end; + + +end. + diff --git a/doc/grammars/pascal/tools/ast/astProgram.pas b/doc/grammars/pascal/tools/ast/astProgram.pas new file mode 100644 index 0000000..75a9da0 --- /dev/null +++ b/doc/grammars/pascal/tools/ast/astProgram.pas @@ -0,0 +1,12 @@ +unit astProgram; + +interface + +type + TastProgram = class + + end; + +implementation + +end. diff --git a/doc/grammars/pascal/wirth/block.gif b/doc/grammars/pascal/wirth/block.gif new file mode 100644 index 0000000000000000000000000000000000000000..66f0d1f3e736a5faa046efe9ae28f00da6ef6771 GIT binary patch literal 14973 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 M+o1414+aKn09}83<^TWy literal 0 HcmV?d00001 diff --git a/doc/grammars/pascal/wirth/idconst.gif b/doc/grammars/pascal/wirth/idconst.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ba07c48dadd1b01b6f6477cea5541593b23fdf7 GIT binary patch literal 11694 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 LQdo5s1A{dHI{dTM literal 0 HcmV?d00001 diff --git a/doc/grammars/pascal/wirth/stmt.gif b/doc/grammars/pascal/wirth/stmt.gif new file mode 100644 index 0000000000000000000000000000000000000000..a0c086ad30253cf3de50378790a45c5129a5ab33 GIT binary patch literal 21053 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 J#>v274FGXy%rXD~ literal 0 HcmV?d00001 diff --git a/doc/grammars/pascal/wirth/test/wpTest.dpr b/doc/grammars/pascal/wirth/test/wpTest.dpr new file mode 100644 index 0000000..feffe20 --- /dev/null +++ b/doc/grammars/pascal/wirth/test/wpTest.dpr @@ -0,0 +1,38 @@ +program wpTest; + +{$APPTYPE CONSOLE} + +uses + Classes, + SysUtils, + wpLex in '..\wpLex.pas', + wpPar in '..\wpPar.pas', + astProgram in '..\..\tools\ast\astProgram.pas', + ast in '..\..\tools\ast\ast.pas'; + +var + stm : TFileStream; + lex : TwpLex; + par : TwpPar; + +begin + try + stm := TFileStream.Create('x.pas', fmOpenRead); + stm.Seek(0, soFromBeginning); + + lex := TwpLex.Create(stm); + par := TwpPar.Create(lex); + + par.prg; + + stm.Free; + lex.Free; + par.Free; + + + + except + on E: Exception do + Writeln(E.ClassName, ': ', E.Message); + end; +end. diff --git a/doc/grammars/pascal/wirth/test/wpTest.dproj b/doc/grammars/pascal/wirth/test/wpTest.dproj new file mode 100644 index 0000000..2382475 --- /dev/null +++ b/doc/grammars/pascal/wirth/test/wpTest.dproj @@ -0,0 +1,107 @@ + + + {E509B25A-366D-449B-B4C6-013162829AAF} + 12.0 + wpTest.dpr + Debug + DCC32 + + + true + + + true + Base + true + + + true + Base + true + + + wpTest.exe + 00400000 + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias) + x86 + false + false + false + false + false + + + false + RELEASE;$(DCC_Define) + 0 + false + + + DEBUG;$(DCC_Define) + + + + MainSource + + + + + + + Base + + + Cfg_2 + Base + + + Cfg_1 + Base + + + + + Delphi.Personality.12 + + + + + wpTest.dpr + + + False + True + False + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1031 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + 12 + + diff --git a/doc/grammars/pascal/wirth/test/x.pas b/doc/grammars/pascal/wirth/test/x.pas new file mode 100644 index 0000000..9ee1f08 --- /dev/null +++ b/doc/grammars/pascal/wirth/test/x.pas @@ -0,0 +1,13 @@ +program prg1 (input,output); + +label 1,4,5; + +const + a = 3.14; + b = 'hello'; + c = d; + asd = 12345; + +begin + +end. diff --git a/doc/grammars/pascal/wirth/type.gif b/doc/grammars/pascal/wirth/type.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc5a50be7f9ef2b3f535d457a70cdc1d5834db64 GIT binary patch literal 16095 zcmZ?wbh9u|JjHmB=@SFP|Ns9P7#Pl+IWu$S%(S#LV`F0mFwg;!AT0q0yr2ye%~eG!5U{YThP4t{f|9zPo_Ct}G}u9utD|Cv^r*>g)7q&Y95Hv#hsmXp?#;N&{y`AZkpmF>KI<*M20W5*8OJ{q+5P?tb&*`8zfGCYc}y?*mn zrI{(C@6%HE`rgA2`Yx>CSnIfUan7Awq~Yc%hM!KUITT_)@a4<>Ml z{OdmF+N$8(bwy#Nn5Sll!c3Wyo0gvD;B$=0`L=1<+1VDwukM`Oy!`xphh{EWuPrMs zF7}wL6?WIx*cTat7o!-UJS0d{z#4Y3nFKxm%O;_V3!@#yK5`ojFeAr?0cjh^4CbkY|6r#6(6gz06 z$?VwSSj_eJiQezaKN;UWHs_e5wc+mCviGb9y33{K+5AxEn{BErA6fhR`@6@7=j-qP z_uF-U;0*oZ)Z~BijLWxdikIj;v+$Bcp5kZMinI#$iAfJN6+D~68(1fZvrKA}<=yRb zNzu5aRpU{I$}|s7orx<%=b0zA277rfe6xt(i+4_Nf>ixp4==lO5|u9Jt{3uYr}_!u^jpFg?B-5=+vUuiYkJvHHsVv; z>$k1fB?9{%3QX3yJ$uDjSGn{LegVtZ&OBnd^{rV_)PI}uyn@Fn-|yC}U3>Xn&E%=y zeH+;CO}$?zeec!-GtqTB!a836{gK)8@A{J;Pr_aOD#D5r{Tk2s=RZ2Cwdq~iDn-}J zIl5k1hFMde^`;wLk4jx$V7hAQ`VXx8x28`#f35OJ@+q0k%O~#U%5Mp%DoE31NH`nE zShh#(By&Bx@>Sm>51;CUAZVYWjNOV}~Cy?zGy7uy{} zC){VcW?EtI)F84WUhT*Boz@abRopWs@Nif(fBU<>O0+;h_+F~HUdy8LX$S8A+p*mG z?_32DjvV3h9}YO2mb}nBuR+3nOKX$RF^49F2fb{6ma~X&TT&PK;Qp@{4Tr>-a^qwZ zuCr$RU=(?^hSB;-6K~|CHA+7?!xlDha!r?Liqh@*mmrj(v^z!d2N+PF$67W@PEC6*=stcgfXjD`zuf zh`XfZh7+j@K^!46C*P{gTwCZXXizkhWqwq;YXC=+#L2}iAHGOvxo&ZCV$QsvdauZ4 zJ!5-(sz*|<%7w!U3>Piam&7l66gcsC%~QQSEkZYL>@ZmzD4<;Y#6zdc-805hOK_$P zhloxozdxst=$!|B<}6eC(#o2qUEO(6!OeKLiBNIxi#?|oeY&B0F%sP2lZ$ZtNL9^0(Z|SxT~~uC0O>Fx*Spc81TuoV$qhqeVp+&Qjac} zGO=m+E|KH9__1M15n-Vk26+}8z0IzgigTV{GmLr36K$Y<#LwYrs_plryv1e>Tc(Qm?{%H< zHg>)A`9&9*_O*XG5Wl5_C%DvMn%IO{?H{~Ze#)uru6poP`RmJAPK&fX2cGz+9$A#Y zv0Qlnr@OMMVm6MyHZ9(v_;Rf-&l^6W?aT*FFY4;~oZ%B&&wNBd@Z%4yXAesk{7^Oj z<~66_L6XbW8&U>!&-+a$DAWng*yOy-t$+2z$J0zKS~fk`wy>HFP;|O80b|b*XpSO12+WOp@wLE^+NP@eo?O zX0x2><;ilU?e@A^txKvlaL2t>zEbmI+SXZ@TDQrpxcS=e?6L_n-SaqBy6?$qaap1M zdvBCS=b35q^fJRG_nIab=L-LpdnCYrG;rEJ=Xntg)AgqMZo3eYu{lXT<$CbLOi>cqVuOqyqp)^bg?wJ*Jg1xf=rW`e>PoUTG!k3 z+zqt6{bOn%U-LL(jd+xKE z&it+Y`K#9$2W-!NaBt_0`EHH>UN{S0nC@WPvDJR3e1qcsyoA5pjd}NvGj1&w%zY*~ zGmZOETE*JOvVl$&H?PTGEoNE%HQVWnx^9#2goT@GucaJqFCb0`MajX?+zTU>NIFKhwnQPqxZM~-4z)f1Ef_cY^6$J~$eN<&_7YRLd zh-EfaUlF1+?~2T=kCKc}H6DwzToJbr+Z0f^gk$wlrAdn-=QnD4hLB+aA(b$WCe}lKP8_->jpAZc|Eb;$Q9NMe%gP$ycSA{O2~U24)cM3*JrB=s z=H{E&xKAzgJ=@S#WFfGxAj;L)>(+(lcOj9?*Ht}ksO{9~IaJU+Er2aisrj@;*QyKr z8ZX@58kWC*mXmcwR)a}pi*UW`qT2n>Y?ipTObt-&5RfcpmpsWR`0)YvyD2WuZm?Bv zjPUd*{v^P6?|`IhaaUqd+wqLnYUgYI%(l^#tZ6t0>T+RU+O%L^{Q#s zt+!};S#G(@d{SuJB;(9Fo6Zz@g_!x1Cwym{?Dh{=xRkn*x@rPY>GIclwKMh9-w$(~Jp`(o-7a3dLtm ztDHGw=FC|;XU@4fbKcLH3nXVPvYfRfa@MlSSu1AFTD5c5nwzuM{hYNya`q<6*;^uK zZ>yZWW9IB#J7@2?IeXvF*#{)&9I~8qBy!HN$~oI5^-r9fxv4=eIy0hS$DDc1(JMZC z&cCGSqB-}5plf=gZT<(}Tau;yO;*l9{L2a=9(GzPO}1Gq=&IpZ^6#akrPw9+`6YT` zAEtdgDXy4W`!iGKn^@0Z$puVS3s|BSuvIPKn6-dw*8-kf3;2F55Rh6ZWVKMFi#df^ ztS&>m^rXkj3-tnN5eG%Y(vHiEg-sTnmC!p=>t^MmD-#M@GJ6eXi7OsoqKU(BpW&Xse zx9&vnOhb$Q5*68wuoDaVqz-wnRGqb^!Zg#$oa9@2k9rHVc^qO}tsPo`0)`oYLAqzqGbb zmt4KHrEL{g-VFsuC;q6LWGEF69_>v9)*Rxz1)ht;Xp#d>Y=?Us_=#1bei`u4Dm zmV)-)z^!(U;50iTxfr^6+ctqO`sLHgofA#;Mjj_p0xdD%d$=w(P9zo%3(+yez(} zz;o9kZ{|7GS<9>QmU&NG9i6oHx8=s)yIgN4Zn>Sb+1q<(_3jg!cV8%#;ZK{j^7XEr z8<&Z`a6ZdYHd$(A^TQ3()ZI^S*=YQ2@xIxq#X)+LQ!_M+lyXU^;E=|$6$Gnvh1 zh5w1}G)>Ps)#tAd+d{?UWdbRegLxFwD3Q1iYp*J?mWJx?a zBz0?3)Mq1)dr^lU+)gahRt+<jy?m$IfeEo4B9_8XlDtW%zDvwDGXDEfCiM97n&*?Xau=RjbMBP8tJCje+XW8) zo_+4`wF~JBF0Xh}s(ja8z2{_r?UHj_r}TR=`JLVL!kR^0_UyKA%ooD;vDg;7{$&c6 zJ#Mdc)%41>NK%M2*mCwdmqb{kl}~l%ja9vkJFFci?w!C> zk)u4}>XDr{_j_kQ7U8_(7TmaJS)MvmV(y%6Yt!Y#Qa_wzl4`up;(7b9<(=DWrkyz( z8Fwjm=GocjYL`uPzdG0UE{nw7gOzvB>r^eVb@_HX{OaD>{~q)nNLX@L&%yAn?aiGt z?|7`oQJkO+fZXt`1F(}g@0PY#|6(e$`#xgsUBv3zRs z1%bqu;+KA3)tPs){rdD=#bpest?!k+HyE%#E(o2mw7=!!t)J2NPM&#o{Nf|mXEO|H z%(h*esAF{HLsoOw1fkQ7Y9|+(mjBV}4-|iHd;5=DZ1lTZjS^0bYo0D(`qzAmQDB}0 z+o{O4{t-403|L*lBVIk6v+cvC$S2R*k{><`yXH{GE~*o`GESvOJI#Q-R;}g*Z%dwf zp2#ve=X|D_jMnEk5bi${skAE4Pn5_soLbcf6d``zOD?>HAPd@$GwUlk+0m zCAsZheVO1|ci7|kWwQxYj@^fEN+~*d9L*>^)lx2XK~K1^_s)_y=Kbzl-=!GLY)RcO z$o_Gis2E@A_uwm;vMh{quJf4{KVN-vt*oKV%EU~U8#P& z|6burTW|j-cPD+`qxa3LZShTQea3z!`DzLA^KZf~F6Nd<(^hzu^6|^Ad0)dUnaj@H z%47ZJa`D^yzu!3g?`r#et8M+>mBy>;U(oS?U+@1LI|c4&WqhCH_LHmd_1W(~rmz30 zfAX-{Gq;pi-#soZKV$eKM?z{^{jXh*Z$}CBX)JjEa$kZ^bH$WjvRmtaZ;PMKWhVY2 zP;i%jUs`um?e4p1O)byT zCiQH=dUYm!dFCqT;99q?+~B6-KKJIC44Tz>Tu!q@_2wFO#;AKPY2aGbxNyD33|%kP zWfk%kt5lY4GM^ONUK--ux}o%Fq38BvZClLrPBSn?i7Zo%7Fl;@;R%L=D*KhWjV`F| z%)LKvulAhVd5)#a7QEyC=b7XEQY_=9-)?b{pD*@K7M&2kh5z!k#@*~rat7(IBxb!< zpKxM@)!Tp*iU#iwHuM>nczTpvU{U2f#rDEVQ%|O)NmMuJN_f*!8McjnGaG&`JbBo0 zjb3Mur_y3+@y|hL4}3^IEhl$2MC9>Jp(m~aAzxqSOyl&L=%Ud3=A@POn(g(1Z{{vg zOqLMbWSh2XqIZd_c?hdV?dGdK#}}5leb)`0D5&Sq@m0Y8Lfck_(9JboPefg}MTcc8 z**CKG%4dV#`%1~b#fliYcC8Lviimn`yO$(FEKkTYRH%YAP@ zjm3>EQa7f^DhCF9;ndbVGwFIt=LK`=qzN}ZD~i_IFbNt3zff?zFP31wXofT24^%l^a68`Am2vQhNrKD8Xp_ZnjTj3VJ}F*Q5_;t!TmdxAH%4RvYsD-2U0HeRy=8UQQuALIM`1|{H zlpnW9PML6i3Dc*9%Zh$qj9lYt`wl9Ka%){Z@=r?QhpI%|WYO&>-PxQTHrB@aeNp8Q zVtw2dl)iEmb3$##iFX&34)!_P2@%Kb*!MbY|kD&4neG1A5ht$~e6EDr6w5&e|Nw z$K+C@U0UBH=;LPbCn|++zRb0QbE?b~685!7NHb5ry~L8mv%7Xwt64*4G(rr?16K^xY_QVaBU}hiz?tKUS%Ad7i#iJ~=yR zJ8ylmghg9I^sVx=_HYGxxwvlA>t~|;6C&=i?(edWZR!r=P3s9-R!n z>Djv|dj7RP)?4{2zIb=uzkIK~{~_n0^1L0F>MphOF+AhVRH>N2DRXJ}yTrGZMhUYN zmZ_UD2C0eER35c_bdlvw&dQcU1qv6pg**J8$k}|NIC1x+<4qSV`D_1a^>}u=M99Bs z@KQDBdX(Mb;Sy=fs6NXg>6=7?4Qn>cf3wAl?bME|Qy(2T_|ey}OITpO zno!aD;#fg3t&^?)HbfjV+x4;6Qf1QR3^o0ydmU2bb~*|3hIi^c;_cbUutcF>QLm5T z?S$5zX%c=@7SA_yu!ySY6M7!Dba9FnU;QD5k{uk!%WDfKbTTc~aDVBjF{PmYje)Rs zK;^7z$qr%Zh{b{~JDr1WeVVr8OseZ24-vyxpQaz+S!VE)<5U#i=NTt_mg!YW3dd`G zo_V1s?cR(?!DO$`vu>POX1zjFAU*5z><2vQ(T_9)vb#RddEvAC$%#&@vQ?kwe)zXX z)%>>P`Knu=XPxd^Wd8o-`MO(|<^-~=uxIxQaCo=5hFy1sllU#wMy?ABFQvpPJwI}x z>zVe#M0kZpX$qhfVF;o0UX@4hTx>3=8` zaf8Wd`^}ZUot)Aj3meNDu;h>`&V4f zSuK8gR%qIcsnbrsR!(@Xi(l`NGr=P<@>StC-PWtAx%#tir@1v%Y!PgH@8zt2Hp4*p zY_?;>`^mO9`aaovHOJ-`T1H)dQnE~#b*88RMxMU&8>TD2xg^4z z6mU|o@3ovqWEavTc$<5Z&SY7MPcplIae_Mg$)}EL;avZ8PuKdX@-Ccfv1_J**U1Ay z+m@~gRk%8Fj@G2Nybu2>T|as(?ZAQwvl)J$y%oD^)z3HH*W%0{TzRumHNGtzp z*OpnDEHb{^R>a>JyW+sMhJ02zZj->&bW7X!S-C%+Y+0y<$`HbEym?HeTz_)Fx z@%nRV>a(s*mOHX{vm4L15{ruu@-7~du2Wp3^5>!W`HK9LS6}q@+t{S=ehg)uSbgKeOa+z?P>13U)LtbeQvhj`#RnJ%vJHZ-*)8NywRTj z{m$>W+1vK#pQ-n+$$9s0^WOWPx)<91c_eN3bJE%JKeB2`@Fr$!u&@o?5A@*3lCY9 zQom$kl)6dj*((VN3cPjKldc%3$O{^WF_{Hlt9$&x=XiPbsV|ywqT%lvoW2M*I4S0B zV(0$jE@Ex&wXv~o^@IA!3en1m)}AFz7uy?kB%;l41Q^WVvXj-zQ?wV`E z%kZYykIk_H26szpM7Ho6X*jrKBw1GEo>-D0+Sqz~OHg2kpkzd)hedv8ddm{$=J(%P z%|7H`VPp#kWs`IESJ_b?I)l^ehr{G$y4DSBamV759U4nBn0x*u^6!1fcxSt|{&n}6 zj1fz}MmbIQN#iJ+a;5GDt4r+;Pvs9unM*Wg2kRLa$Y(fkmNzKa3YGbbFjX}0%xPlx zZEXAZQMJ1@^1?Iy4k6>NZ_>~1}9SgP^)iIzZJ{te)$NflqUUJ-f}9msEe;XYDL#CuEr?4id`!vLOET1H$7bXUUj;i$(mhWYxZWXi7HsLookKjL6&1y(!3j1UwY;2+U3_96}fDdIm4~F z`UlqVC@tbpTH>iyCF8`lPi?aBrGk+xi?rwtxfOX6R4i2 zpS4jxVqw6G4J9`=S1Ql%{lpS5b&3OrXpWhb&uY*7LnV5}9Y$PL_Y@_g zMZ09PNR=>OLEP#kDZSeyr>il25)j$fEE%KidRU;|aT4E42W8i%JnZbk*$z_`TPHqx zy7JMJP16@NM24k`da(a~xHi9ubyBnHqe3;??=H`Ra#uO&EOO&M%vybBn!(#mR#MK~ ztCr+=GjWA@YR9USKl!?;`Vu3bW6sKe$=j8;xO;g0FkjbvOg%$P;{3E3KQh#3{&e5$ z(6QR3JkLX?{79y0fP}N@wby-qEyW zS)sd&bIHDEv-fRi-1nw?>6(L9=d!#GpJKefjnBqXSjDOP*%gDcE0{zcPL27Xc`D2G zD+e>XkkU+TnTg#yk2vjG7~;-roT05G)X%_mA?tv5(3D=mwdbSME=R3VusN`MmHIX< zts4{F++1=$E!^iMvb}Y?QPn}EOQ+*_Yi4Q|O;vm}#cFZS>I}y?F(x))rBgfDCu+v% zY}(T!CX!Yx79Fgb6yzZ-Bpq**)%HQBy};Gx;mkKbSSNBQ@m^9dZCdxRYd4R=z8-d& z4+>Lqj<2u1#%R0Dm~Btye^#EJnTOvV;^6sLDJI1(S`=)4@PccPK#;!U!C9}xIrpd} zn~B8zUiIH)RnjFf?$@UOLRlMc@4VKi6Y@BI_Ll8j%ngkT9M>(7UhJ{EN5{%-c2U2^ zwi;uO4AV@<5E+KY{L;~<9-FLqBDwcxl5_V>zjt1z3k_DE`&r63+k}1j=@N_0`(#{| zy$hyYIc<5c*=4uL@;PTpA0B$(x_y!2GPPHnH*#99{PF%HDg2g`=bVj%iuGA#!$tRN zye$e=tU9t|m5pP|aR>X`8(+`SH&0Sn-XgW}+Ig88cNv+r-xQ=@EYDaY*eI*GnB(*c z-bI_e7fej6IsYSP@k92yRolW-auUkJ-Bu|o+|{{QT($V$<3k>@U%gf&8*iB?q~*Jx zkN1+^-%AFvmyK*Mo5Wr=tG#S7_p;UA%Qkl}+x@-lAbZ8h_KHjF6}Q?e9&@jF?Y-i2 z_ln=&D*>`sgKV#c#9j@ny&5t1YSiAVF?X-V{k@tXdoAf~kgU};x4Rswjd9JN#Z@=P zrPZF#6O>wY(&_HOg`a+2yVBEoH_#xZb5F-c=Lro_YE9RL{)&I^7ITx4PTXSLX~=il z=f=J_>3wZC)K?}POTIbp^ZE(CE7}VVH#%!bS6cR5yU{OsarWDq0&9aEH+79RWrXcf z{-1DWdF{%W@bx>kWd$0f8hXfGQJb_e`Q&EVJBMuV9ErVitoF`{xpz+O{decg-8<+0 z-nroGEiQZ4y0>25_pbh15tY=28@!jR7H|n)zN_~)w5H(hqq8R-^Dy<--s`zjwE6VC zlXLb~TAcon8~FMx`;wUZGua(pt+_veYu`&A)5A4){Jm>ug|PMRjDO~Jaa~xW7we=z z(?)l0Q{@&TjSVp;&MxYoa#7~q!`&7~t)k_n4?IxOyYzb(r=S>{X(RWSwLW_`tlVND z^k|bx&I)DSoJSV#5)QH+wU`yW@}Rez+!H6eN4vc)u-CQ6XP-~WvTj-PK<_8Fp4N%z zLrZ6W);7`84o$NER@}3gVeO{~HH9Fybzfz_ajb56UFo4b?`6z6)~!c#{1%;z5#Tt? zulw(u|A(xai*KsSYaP27&rFPZSP}PJOtfIiHIw|jz`wnXmG7$iWvw>(t}vAL?T!ib zK6;l`DpY>&^ZI=+W|zOvdU0`CZKv4kmlLfX95i{!@^s;M=B7zen_QG$u%w=Ko^k)9 zut7rV%XbH^A6fk5T>7g6EwBEHoJ(NZW~2Tn)#vo4fA#bD+){IKacQzds^iDez}_MJy&l3tKivscB{iXQ{8vgt!JLIow%lV z@#Vj=EppX*9g?4~zpX#D?)UWf?#%A;Gr1kYxSY(`G}b+Go%`Zc$opo4TGq7S6{a8U zdEfMDeCU|4LAt%|-*nIEMaQz(l-^Ew^+B@U=iS|zxw_F$x}#s5St+r9iqwBOCNZhv zdnRA+TvpTntS*({9kZRa@ZH1HmksZKc8mY4zgptMytkHnKfCMubg8fJKJ)rn*=5)G zYUBI4$Iq~Ny)H`e_&WF1mx%vg7Jew+;qYd)&zE<6Z7K1eW&T^TukW@x|8nE?Z$iJ0 zD)4_}>%JV$|22}|erH|~2iM0Gt#5Vt-_IQQQ2y)t;_Kg+pZnpn{zdWrH(Ra0tz!Q< z_xX>feLvLKf16T2ch33GS?}M^5&5P5>(lhCAN~2i793>Q*T$x57c6#mq5j98`3Jubk`hYt?%1CRv{! z#)2#Kg|{cQ?J?WUA;1J$Dg4q&!sNM7$G-%R$Qc>)USvjQzRo%nRd@L7y&zlnZPDV^ zo;|JAg5CVGMV1>YW(1_^26RN324{6F*t>0qzvppNo*)ZG{TCch!>)Rp)%<(-?ZvBy zvb&FeJ}cUwD3-6_oLDEC85Z2>*4;OeH@IU`VUc74A2%OMtL8kOIi<SrT$M7Jaupb$H}RT$q}zF1^66TWfGBf_te(a*ViW;?vnK` zbKPs=m9-_Q^Kx@jnEw@{3hmOhJrbc_CmwXT&5bW*dXo9q!^HE_&it!qo@_4@wx6sz zzcEByQ8A3eSAX$@KMix!%Pu;#KbzpU<>loS&eOwuHMSnTw3_|jlg}ycuU}hdO?<>t zr8q07D9^hf^Fnfu@cn->DGTo=7DldXH?^5Bw@sl?ntyI^;_*+BKDWdUH_Pkqv-$b? zk?ZV!u{c{r|3#cjvgLjE*;YHmY;N(7H0JOPOIdc%oxkVsZKm$MkAp=&Z`tIaY^AyN zoJ3VZfiN@Mwt^EHt(+wioP{@qZ|J@$NKtat@l;{=@5nW8^W$_1xa~aeN{Vu+#j_QQ zBQE|l_mrPrQP^v}*M)_bbxsQ#ZN&6187D`-K=JSZAuI?C6~vknxx^y~axEIRBA%>`dzzW1R`<8c zr`j9eMZOlQs+%BVy7^d%>>Are3GN#vMts-en{B70GGT|xZzm%)htt}@om-94+0LB` zQZ-|itv*~39>cX}@phwKx~x07thD(WpIy>5t15V=yX^I@-8!qLrMzz1!rZ0(TJ%>} z!?CSfuDHF~GxJKd^Uf`Db3AtE8bmMf+W5n}>#&l+8qENX-wQSfO00JJX!fV-;{*k! z1&aAfV*d-%Pn4uI<{#&*RxA|U`c`9FS<=OcMcLnV6yg`%shgv9=H?k4&Lbwu$tB$X zq@pL^y7F`8wx}E-UzOQ8-%hf-T=h~uXj-D(eCyJcjODtw&+56H^*Z3IomG6J@cLVi zb5`Y|3U@o-WNkm-zx=_s`z`L9qS7z2JPVvO@9Olx9UkWeneVqW?=F8hBc1Q~lj*$c zDoUH9|FlJI9cRdObud-Qba_IFl$r#yc6{q_DLWvjP4Zm*3FEfBWbv~%Ngy*+nV zMjtA9y-MlhyANlk*X>f?`#;xGqW=aYI`rqk~7zTOm1WrLhVp7aiL zrf=^XERIZEDYeP=(%gbNhnm~mt|o#LJy=Y1eI6cb3g0fz_OUbIi_^c1=SMW6K6aVE znD=2-$5FkikM@m+WyJS;95d2d9<@_?vE=m^M>%-?druz<6ubAhd)kQ)eftXUT%FRQ zue!;wST#pVW^Dp{$Ad!UG|4DFan5PK{{|}B%G_00_(9d9i;1Ob$wD=CBjF}np~R>o zcU%8#w$_k)G}%{2{+ZlTNpm;D2`i2qeII9j==2n!t~EVNx2xSe_5A3esR3)2>ct=R zj$SoMYF+a1EHQji#eM&z)6_+b9J-Oy=qOn!FtYq`d;18ddSQ#C0c<*GKo0M9R zQJ^BfP4tv}>AQs5h0k_2JZaGpzB;%#$j_b%4XF9(! zZ+!3Rr;&cB8b=c?HWGOjW1fZske6ucy=~-WR^V>yKr@?@&1RmH-8DyWN_s% zjF&dIEnyW1Na9Z7RGh&ZymD9c$D>WTADG2T)z!Kugcbg?xY#`NjmxnD&7iur?5Qtq zH1vsX%ha>dxu@OOoOiWgaloV0eAo0qh9;=AV+Ax|5vwq3ffqP&bN_G`yPmxHm7IF<)SYPDNQ*9t!{ zyWz>7d*(OCmR-s!&n>2fb+!LhxUp(RtL+&sld_GcUWzYWSQvJa``)L6Y>y?ld|ads z8yw@F=``bsz?75s&qXb0cKgTS$nq!MKWB|JyImw(u)>uUk5-F2-<`bBNbN|{rs$qX ziS}ffc_Ay8b7^vxXr(r4wi-;_~Ub}3y(}ZF3j~WR>*njdWnNC z4$Yi6ca_i|o{W%c^R2WQjGkZqmeBX$W%}o^J4te}%_@u!>Pq!?8b08;xMItu zbXoLr%&_#!x^woy0B?`l5gIM2`qNtNi7^6G4f2eGE*&?zt{%26F=SSV;Kt9)(uN`8 z6BAfJCC>ej;khu&W0SlVQ{K&jdi}44hN)q#B8@^GZe3eE7ClbVn5sM_*!hhz_d0bh zpGk~%p`r(_OBxpn{uT@s*07h^#60gho695%6LCSFR7HLx7fC@W=ag1;BVS%s9rGWp z35Eu#mqh(kby);TZV1A2d`E|M^A@!XNExQjgCn-tQ5r}>Mc5FaM&qtubFwH)8D1$!Sl{V z8ulBOgiW;QT5-c~K}J^hjIMPa>Pt`PF8|TBIIysw^L$0Gib+RGfbx1qsqZTBK^wYmSoD=o zZZT{$O7hUY=F#_Nhsh&}xaP-UCqDJPjpz?tkf#4Y`x<-mht&Rm84&?bnO`mnX569j z?|c9MikP1jns1-~Yu(;4K|oVh{mKM~AI=+Zn3yuje%dN7rs4eRftHfsMC}UupWp3# zH*|Jw>eF&bOWz7b*QGC&-;u(!ABvnoW69>c3CAJk2QqinSLt?D#8nGSg?-9u2QQn{5TiL~lcDHO&z8TIHD{COO)fRE3Z1r&W3Gik{V$h(ri(UT zUe3Ilp7&wq1TBf+DMAb7CeQitc{ZIPtznE&4RSAD{QvHeZRGYQu|F6T}0fR!o^CrF+TKz|nK{{*=|C!hw^srmy;9eEx$vi{a{SOM|-{E*sb+ z{4PnVZ&*F+;4&f6K((%hj|M_N%7om%Oyp-0dZwW8%VO;Wqvgz#1>MXvqjsz|TVdQC z==?Ng?P-Qd_mtNh-Ol!_%1tmeRQ}Z>r-Gza;U4FoiW-^zo0%t6&XMh4(J;T+%l2=V z)h(-y^2b+ya+Q$Otoib3zO%vd$_?Ts+a(s8t@@~%#y)*x-M9HyGdI3+N;22d(~NGE zGMXkeq2@%&BKGHrYO9k>t;4Lf&Ge+3C5^W%_`KrXq%hml(l0ZubfPP{5)H4rPOvcE zvLtL{e%I{J8ZjGog|ipeH8F20zZ4atmgIk${cN+kZM9ST*UfPp`YA>eE-7yN|48#V z%Qg*>@XTH6*8&lq6Du}$Yud_G{|~dSNR2w1Sa`o}pA0ikRAOmmcyj*H1OEcm ztqPJt%1oT!ew<{qD%8qVc7MX00=0C1c9|I;Yi_m`7P0tkO!K>4<$CvlH>xZJNirSSoo*pc}hxPmX8f+*=dKMI%&iS^I6%&tCFawmn^dN-Q}$AzW)lMb}FilvA@h(CB;?`UG~+)LfPK8yA= z>f2j(s{LNAe#*d6V#AgI&n7qDjf)Kx*T{TjI6c2gNbW}as_#6Nd;C|)*r|0dGFu#Z z`gPs2s&*djStT^PSxnmYOip`xckQ`ITkqFa_uuR_^fHf~&0(7v zuEF{0e7TSfQ?=VV8CN#n#rdmDIB5G|Ouf~UG-8Wfb(EDC@i#H9Ce?hj|CpHjTic0y5E>2So`Sy6Z6vo6hwJ?v<=)_(m@txp(OL?iwADGHdUET+EDqiY<cI!oH6(2ti3nq+`T#Pt_>#xgEataZHYJl literal 0 HcmV?d00001 diff --git a/doc/grammars/pascal/wirth/var.gif b/doc/grammars/pascal/wirth/var.gif new file mode 100644 index 0000000000000000000000000000000000000000..24655ce039c21ace0e01d0ef85573b48ad518276 GIT binary patch literal 13619 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 literal 0 HcmV?d00001 diff --git a/doc/grammars/pascal/wirth/wpLex.pas b/doc/grammars/pascal/wirth/wpLex.pas new file mode 100644 index 0000000..4a2d8de --- /dev/null +++ b/doc/grammars/pascal/wirth/wpLex.pas @@ -0,0 +1,607 @@ +unit wpLex; + +interface +uses + Classes, + SysUtils, + Generics.Collections; + + +type + TTokenType = + ( + TT_EOF, + TT_SKIP, + TT_COMMENT, + + TT_LPAREN, // ( + TT_RPAREN, // ) + TT_LBRACKET, // [ + TT_RBRACKET, // ] + + TT_STAR, // * + TT_SLASH, // / + TT_PLUS, // + + TT_MINUS, // - + + TT_LT, // < + TT_LE, // <= + TT_GT, // > + TT_GE, // >= + + TT_EQ, // = + TT_NE, // <> + + TT_COLON, // : + TT_ASSIGN, // := + + TT_DOT, // . + TT_RANGE, // .. + TT_PTR, // ^ + TT_COMMA, // , + TT_SEMI, // ; + TT_DOLLAR, // $ + TT_AT, // @ + TT_SHARP, // # + + TT_ID, + TT_UINT, + TT_UREAL, + TT_CHAR, + TT_STRING, + TT_HEX, + TT_BIN, + + LT_DO, + LT_IF, + LT_IN, + LT_OF, + LT_OR, + LT_TO, + + LT_AND, + LT_DIV, + LT_END, + LT_FOR, + LT_MOD, + LT_NIL, + LT_NOT, + LT_SET, + LT_VAR, + LT_XOR, + + LT_CASE, + LT_ELSE, + LT_FILE, + LT_GOTO, + LT_THEN, + LT_TYPE, + LT_USES, + LT_WITH, + + LT_ARRAY, + LT_BEGIN, + LT_CONST, + LT_LABEL, + LT_UNTIL, + LT_WHILE, + + LT_DOWNTO, + LT_PACKED, + LT_RECORD, + LT_REPEAT, + + LT_PROGRAM, + LT_FUNCTION, + LT_PROCEDURE + ); + + TTokenTypes = set of TTokenType; + TBlah = set of byte; + + TToken = class + TokenType : TTokenType; + TokenText : AnsiString; + TokenLine : integer; + TokenColumn : integer; + end; + + TTokenMap = TDictionary; + + + TwpLex = class + private + fBuffer : PAnsiChar; + fStart : PAnsiChar; + fForward : PAnsiChar; + + fLiterals : TTokenMap; + + fTokenLine : integer; + fTokenColumn: integer; + + private + procedure InitLiterals; + + function CheckLiteral( TokenText : AnsiString; + TokenType : TTokenType): TTokenType; + + function MakeToken( TokenText : AnsiString; + TokenType : TTokenType): TToken; + + public + function NextToken : TToken; + + public + constructor Create( Stream: TStream; Length: Int64=-1); + destructor Destroy; override; + end; + + EwpLex = Exception; + + +implementation +uses + Windows; + + +{ TwpLex } + +// @@@: Construction/destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction/destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TwpLex.Create(Stream: TStream; Length: Int64); +var + size : Int64; + token : TToken; + +begin + inherited Create; + + InitLiterals; + + if Assigned(Stream) then + begin + if Length < 0 + then size := Stream.Size - Stream.Position + else size := Length; + + fBuffer := GetMemory(size+1); + + Stream.Read( fBuffer^, size); + + fStart := fBuffer; + fForward := fBuffer; + fBuffer[size] := #0; + end; +end; + +// ================================================================================================ +// Destructor +// ================================================================================================ +destructor TwpLex.Destroy; +begin + FreeAndNil(fLiterals); + inherited; +end; + +// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Internals +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Make Token +// ================================================================================================ +function TwpLex.MakeToken(TokenText: AnsiString; TokenType: TTokenType): TToken; +begin + result := TToken.Create; + result.TokenLine := 0; + result.TokenColumn := 0; + result.TokenType := TokenType; + result.TokenText := TokenText; + +// if TokenType = TT_COMMENT +// then result.TokenText := TokenText +// else result.TokenText := UpperCase(TokenText); +end; + +// ================================================================================================ +// Init Literals +// ================================================================================================ +procedure TwpLex.InitLiterals; +begin + fLiterals := TTokenMap.Create; + + fLiterals.Add('do', LT_DO); + fLiterals.Add('if', LT_IF); + fLiterals.Add('in', LT_IN); + fLiterals.Add('of', LT_OF); + fLiterals.Add('or', LT_OR); + fLiterals.Add('to', LT_TO); + + fLiterals.Add('and', LT_AND); + fLiterals.Add('div', LT_DIV); + fLiterals.Add('end', LT_END); + fLiterals.Add('for', LT_FOR); + fLiterals.Add('mod', LT_MOD); + fLiterals.Add('nil', LT_NIL); + fLiterals.Add('not', LT_NOT); + fLiterals.Add('set', LT_SET); + fLiterals.Add('var', LT_VAR); + fLiterals.Add('xor', LT_XOR); + + fLiterals.Add('case', LT_CASE); + fLiterals.Add('else', LT_ELSE); + fLiterals.Add('file', LT_FILE); + fLiterals.Add('goto', LT_GOTO); + fLiterals.Add('then', LT_THEN); + fLiterals.Add('type', LT_TYPE); + fLiterals.Add('uses', LT_USES); + fLiterals.Add('with', LT_WITH); + + fLiterals.Add('array', LT_ARRAY); + fLiterals.Add('begin', LT_BEGIN); + fLiterals.Add('const', LT_CONST); + fLiterals.Add('label', LT_LABEL); + fLiterals.Add('until', LT_UNTIL); + fLiterals.Add('while', LT_WHILE); + + fLiterals.Add('downto', LT_DOWNTO); + fLiterals.Add('packed', LT_PACKED); + fLiterals.Add('record', LT_RECORD); + fLiterals.Add('repeat', LT_REPEAT); + + fLiterals.Add('program', LT_PROGRAM); + fLiterals.Add('function', LT_FUNCTION); + fLiterals.Add('procedure', LT_PROCEDURE); +end; + +// ================================================================================================ +// Check Literal +// ================================================================================================ +function TwpLex.CheckLiteral(TokenText: AnsiString; TokenType: TTokenType): TTokenType; +var + ttype : TTokenType; + +begin + if fLiterals.TryGetValue(TokenText, ttype) + then result := ttype + else result := TokenType +end; + +// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Interface +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Next Token +// ================================================================================================ +function TwpLex.NextToken: TToken; + + function GetTokenText: AnsiString; + begin + SetLength(result, fForward-fStart); + MoveMemory( @result[1], fStart, fForward-fStart); + end; + +var + ttext : AnsiString; + ttype : TTokenType; + +begin + result := nil; + + while true do + begin + result := nil; + fForward := fStart; + + case fForward^ of + + // id + 'a'..'z','A'..'Z','_': + begin + INC(fForward); + ttype := TT_ID; + + while fForward^ in ['a'..'z','A'..'Z','0'..'9','_'] do + INC(fForward); + + ttype := CheckLiteral( GetTokenText, ttype); + end; + + // uint or ureal + '0'..'9': + begin + INC(fForward); + ttype := TT_UINT; + + while fForward^ in ['0'..'9'] do + INC(fForward); + + // fractional part + if fForward^ = '.' then + begin + INC(fForward); + + if fForward^ in ['0'..'9'] then + begin + INC(fForward); + ttype := TT_UREAL; + + while fForward^ in ['0'..'9'] do + INC(fForward); + end + + else if fForward^ = '.' then + ttype := TT_RANGE + + else + raise EwpLex.Create('Expected 0..9 in fractional part'); + end; + + // exponential part + if ttype in [TT_UINT, TT_UREAL] then + begin + if fForward^ in ['e','E'] then + begin + INC(fForward); + ttype := TT_UREAL; + + if fForward^ in ['+','-'] then + INC(fForward); + + if fForward^ in ['0'..'9'] then + begin + INC(fForward); + + while fForward^ in ['0'..'9'] do + INC(fForward); + end + else + raise EwpLex.Create('Expected +,-,0..9 in exponential part'); + end; + end; + end; + + // <,<=,<> + '<': + begin + INC(fForward); + ttype := TT_LT; + + if fForward^ in ['=','>'] then + begin + case fForward^ of + '=': ttype := TT_LE; + '>': ttype := TT_NE; + end; + + INC(fForward); + end; + end; + + // >,>= + '>': + begin + INC(fForward); + ttype := TT_GT; + + if fForward^ = '=' then + begin + INC(fForward); + ttype := TT_GE; + end; + end; + + // :,:= + ':': + begin + INC(fForward); + ttype := TT_COLON; + + if fForward^ = '=' then + begin + INC(fForward); + ttype := TT_ASSIGN + end + end; + + // .,.. + '.': + begin + INC(fForward); + ttype := TT_DOT; + + if fForward^ = '.' then + begin + INC(fForward); + ttype := TT_RANGE; + end + end; + + // string + '''': + begin + INC(fForward); + ttype := TT_CHAR; + + while true do + begin + if fForward^ in [#10,#13,#0] then + raise EwpLex.Create('Newline/EOF found in string'); + + if fForward^ = '''' then + begin + INC(fForward); + + if fForward^ = '''' + then INC(fForward) + else break + + end + else + INC(fForward) + end; + end; + + // /,// + '/': + begin + INC(fForward); + ttype := TT_SLASH; + + if fForward^ = '/' then + begin + INC(fForward); + ttype := TT_COMMENT; + + while not (fForward^ in [#13,#10,#0]) do + INC(fForward); + end + end; + + // comment + '{': + begin + INC(fForward); + ttype := TT_COMMENT; + + while not (fForward^ in ['}',#0]) do + INC(fForward); + + if fForward^ = #0 + then raise EwpLex.Create('EOF reached in comment') + else INC( fForward); + end; + + '(': + begin + INC(fForward); + ttype := TT_LPAREN; + + if fForward^ = '*' then + begin + INC(fForward); + ttype := TT_COMMENT; + + while true do + begin + if fForward^ = #0 then + raise EwpLex.Create('EOF reached in comment'); + + if fForward^ = '*' then + begin + INC(fForward); + + if fForward^ = ')' then + begin + INC(fForward); + break; + end; + end + end + end + end; + + // hex number + '$': + begin + INC(fForward); + + if fForward^ in ['0'..'9','a'..'f','A'..'F'] then + begin + INC(fForward); + ttype := TT_HEX; + + while fForward^ in ['0'..'9','a'..'f','A'..'F'] do + INC(fForward); + end + + else + raise EwpLex.Create('Expected hexadecimal digit'); + end; + + '%': + begin + INC(fForward); + + if fForward^ in ['0'..'1'] then + begin + INC(fForward); + ttype := TT_BIN; + + while fForward^ in ['0'..'1'] do + INC(fForward); + end + + else + raise EwpLex.Create('Expected binary digit'); + end; + + else + case fForward^ of + ')': begin ttype := TT_RPAREN; INC(fForward) end; + '[': begin ttype := TT_LBRACKET; INC(fForward) end; + ']': begin ttype := TT_RBRACKET; INC(fForward) end; + + '*': begin ttype := TT_STAR; INC(fForward) end; + '+': begin ttype := TT_PLUS; INC(fForward) end; + '-': begin ttype := TT_MINUS; INC(fForward) end; + + '=': begin ttype := TT_EQ; INC(fForward) end; + + '^': begin ttype := TT_PTR; INC(fForward) end; + ';': begin ttype := TT_SEMI; INC(fForward) end; + ',': begin ttype := TT_COMMA; INC(fForward) end; + '$': begin ttype := TT_DOLLAR; INC(fForward) end; + + '@': begin ttype := TT_AT; INC(fForward) end; + '#': begin ttype := TT_SHARP; INC(fForward) end; + + #9 : begin ttype := TT_SKIP; INC(fForward) end; + #10: begin ttype := TT_SKIP; INC(fForward) end; + #13: begin ttype := TT_SKIP; INC(fForward) end; + #32: begin ttype := TT_SKIP; INC(fForward) end; + + // EOF + #0 : ttype := TT_EOF; + + else + raise EwpLex.Create('Invalid character '+fForward^); + end + end; + + if ttype <> TT_SKIP then + begin + ttext := GetTokenText; + result := MakeToken( ttext, ttype); + fStart := fForward; + + break; + end; + + fStart := fForward; + end; +end; + +end. diff --git a/doc/grammars/pascal/wirth/wpPar.pas b/doc/grammars/pascal/wirth/wpPar.pas new file mode 100644 index 0000000..9351f8c --- /dev/null +++ b/doc/grammars/pascal/wirth/wpPar.pas @@ -0,0 +1,418 @@ +unit wpPar; + +interface +uses + SysUtils, + Generics.Collections, + wpLex; + +type + TStringMap = TDictionary; + + + TwpPar = class + private + fLex : TwpLex; + + fConstants : TStringMap; + fTypes : TStringMap; + + protected + function Match( ttype : TTokenType; dispose: boolean=true):TToken; overload; + function Match( ttypes : TTokenTypes; dispose: boolean=true):TToken; overload; + + protected + procedure block; + procedure constant; + procedure uconstant; + procedure typedef; + + public + procedure prg; + + public + constructor Create( Lexer: TwpLex); + destructor Destroy; override; + end; + + EwpPar = Exception; + + +implementation + +{ TwpPar } + + + +// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TwpPar.Create(Lexer: TwpLex); +begin + inherited Create; + + fLex := Lexer; + fConstants := TStringMap.Create; + fTypes := TStringMap.Create; +end; + +// ================================================================================================ +// Destructor +// ================================================================================================ +destructor TwpPar.Destroy; +begin + fConstants .Free; + fTypes .Free; + + inherited +end; + + + +// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Internals +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// +// ================================================================================================ +function TwpPar.Match(ttype: TTokenType; dispose: boolean): TToken; +var + t: TToken; + +begin + result := nil; + t := fLex.NextToken; + + if t.TokenType = ttype then + if dispose + then t.Free + else result := t + + else + raise EwpPar.Create('Unexpected token') +end; + +// ================================================================================================ +// +// ================================================================================================ +function TwpPar.Match(ttypes: TTokenTypes; dispose: boolean): TToken; +var + t: TToken; + +begin + result := nil; + t := fLex.NextToken; + + if t.TokenType in ttypes then + if dispose + then t.Free + else result := t + else + raise EwpPar.Create('Unexpected token') +end; + +// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Interface +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Program +// ================================================================================================ +procedure TwpPar.prg; +var + t : TToken; + +begin + if Assigned( fLex) then + begin + Match(LT_PROGRAM); + Match(TT_ID); + Match(TT_LPAREN); + + t := fLex.NextToken; + + // id [, id]* + if t.TokenType = TT_ID then + begin + t.Free; + t := fLex.NextToken; + + while t.TokenType = TT_COMMA do + begin + t.Free; + Match(TT_ID); + t := fLex.NextToken; + end; + end; + + if t.TokenType <> TT_RPAREN then + raise EwpPar.Create('")" expected'); + + Match(TT_SEMI); + block; + Match(TT_DOT) + end; +end; + + +// ================================================================================================ +// block +// ================================================================================================ +procedure TwpPar.block; +var + token : TToken; + ttype : TTokenType; + start : TTokenTypes; + start2: TTokenTypes; + +begin + start := [LT_LABEL,LT_CONST,LT_TYPE,LT_VAR,LT_PROCEDURE,LT_FUNCTION,LT_BEGIN]; + start2:= [LT_LABEL,LT_CONST,LT_TYPE,LT_VAR,LT_PROCEDURE,LT_FUNCTION]; + token := fLex.NextToken; + + if token.TokenType in start then + begin + while token.TokenType in start2 do + begin + case token.TokenType of + // ------------------------------------------------------ + // Label + // ------------------------------------------------------ + LT_LABEL: + while true do + begin + Match( TT_UINT); + + token := fLex.NextToken; + ttype := token.TokenType; + + token.Free; + + case ttype of + TT_COMMA : ; + TT_SEMI : begin token := fLex.NextToken; break end; + else raise EwpPar.Create('Expected: ,;'); + end; + end; + + // ------------------------------------------------------ + // Const + // ------------------------------------------------------ + LT_CONST: + begin + token := fLex.NextToken; + ttype := token.TokenType; + + while ttype = TT_ID do + begin + token.Free; + Match(TT_EQ); + constant; + Match(TT_SEMI); + + token := flex.NextToken; + ttype := token.TokenType; + end; + end; + + // ------------------------------------------------------ + // Type + // ------------------------------------------------------ + LT_TYPE: + begin + token := fLex.NextToken; + ttype := token.TokenType; + + while ttype = TT_ID do + begin + token.Free; + Match(TT_EQ); + typedef; + Match(TT_SEMI); + + token := flex.NextToken; + ttype := token.TokenType; + end; + end; + + LT_VAR: + begin + + end; + + LT_PROCEDURE: + begin + + end; + + LT_FUNCTION: + begin + + end; + end; + +// token := fLex.NextToken + end; + + if token.TokenType = LT_BEGIN then + begin + + Match(LT_END) + end + + else + raise EwpPar.Create('Expected: Begin'); + end + + else + raise EwpPar.Create('Expected: label, const, type, var, procedure, function, begin'); +end; + + +// ================================================================================================ +// Constant +// ================================================================================================ +procedure TwpPar.constant; +var + token: TToken; + ttype: TTokenType; + +begin + token := fLex.NextToken; + ttype := token.TokenType; + + if ttype in [TT_PLUS,TT_MINUS,TT_ID,TT_UINT,TT_UREAL] then + begin + if ttype in [TT_PLUS,TT_MINUS] then + begin + token.Free; + + token := fLex.NextToken; + ttype := token.TokenType; + end; + + token.Free; + + case ttype of + TT_ID : ; + TT_UINT : ; + TT_UREAL : ; + else raise EwpPar.Create('Expected: id,int,real') + end + end + + else if ttype in [TT_CHAR, TT_STRING] then + begin + token.Free; + end + + else + raise EwpPar.Create('Expected: +,-,id,int,real,string'); +end; + +// ================================================================================================ +// Unsigned constant +// ================================================================================================ +procedure TwpPar.uconstant; +var + token: TToken; + ttype: TTokenType; + +begin + token := fLex.NextToken; + ttype := token.TokenType; + + token.Free; + + case token.TokenType of + TT_ID : ; + TT_UINT : ; + TT_UREAL : ; + LT_NIL : ; + TT_STRING: ; + else raise EwpPar.Create('Expected: id,int,real,nil,string') + end; +end; + +// ================================================================================================ +// Type +// ================================================================================================ +procedure TwpPar.typedef; +var + token: TToken; + ttype: TTokenType; + ttext: AnsiString; + + f_const : TTokenTypes; + +begin + token := fLex.NextToken; + ttype := token.TokenType; + ttext := token.TokenText; + + token.Free; + + // --------------------------------------------------------------- + // TT_ID + // + // Identifier can be an existing type identifier, or an existing + // constant identifier. If it is contant identifier, then it must + // be a range specification. + // --------------------------------------------------------------- + if ttype = TT_ID then + begin + // -------------------------------------------------- + // constant .. constant + // -------------------------------------------------- + if fConstants.ContainsKey(ttext) then + begin + Match(TT_RANGE); + + token := fLex.NextToken; + ttype := token.TokenType; + ttext := token.TokenText; + + token.Free; + end + + // -------------------------------------------------- + // type identifier + // -------------------------------------------------- + else if fTypes.ContainsKey(ttext) then + begin + + end + + // -------------------------------------------------- + // Not an constant or type identifier + // -------------------------------------------------- + else + EwpPar.Create('Expected a type or constant identifier' ); + end; + + +end; + + + +end. diff --git a/doc/grammars/pascal/wp.dpr b/doc/grammars/pascal/wp.dpr new file mode 100644 index 0000000..8cea72a --- /dev/null +++ b/doc/grammars/pascal/wp.dpr @@ -0,0 +1,42 @@ +program wp; + +{$APPTYPE CONSOLE} + +uses + Classes, + SysUtils, + dpgRTL, + + wpParser in 'wpParser.pas', + wpLexer in 'wpLexer.pas'; + +var + stm: TFileStream; + lex: TwpLexer; + par: TwpParser; + +begin + if ParamCount <> 1 then + begin + writeln('usage: wp '); + exit; + end; + + stm := nil; + par := nil; + + try + stm := TFileStream.Create( ParamStr(1), fmOpenRead); + lex := TwpLexer.Create( stm); + par := TwpParser.Create(lex); + + par.prog; + except + on e: EdpgMismatchedChar do writeln('SyntaxError: ' + IntToStr(e.Line)); + on e: EdpgMismatchedToken do writeln('SyntaxError: ' + IntToStr(e.FoundToken.TokenLine)); + else writeln('Syntax error'); + end; + + if stm <> nil then stm.free; + if par <> nil then par.free; +end. diff --git a/doc/grammars/pascal/wpLexer.g b/doc/grammars/pascal/wpLexer.g new file mode 100644 index 0000000..b4f7784 --- /dev/null +++ b/doc/grammars/pascal/wpLexer.g @@ -0,0 +1,237 @@ +unit wpLexer; + +lexer TwpLexer; +options +{ + exportVocab=wpLexer; + caseSensitive=false; + testLiterals=false; + k=2; +} + +tokens +{ + "do"; + "if"; + "in"; + "of"; + "or"; + "to"; + + "and"; + "div"; + "end"; + "for"; + "mod"; + "nil"; + "not"; + "set"; + "var"; + "xor"; + + "case"; + "else"; + "file"; + "goto"; + "then"; + "type"; + "uses"; + "with"; + + "array"; + "begin"; + "const"; + "label"; + "until"; + "while"; + + "downto"; + "packed"; + "record"; + "repeat"; + + "program"; + "function"; + "procedure"; + + STRING; + CHAR; +} + +// ============================================================================ +// Simple tokens +// ============================================================================ +LPAREN : '('; +RPAREN : ')'; + +LBRACKET : '['; +RBRACKET : ']'; + +COMMA : ','; +COLON : ':'; +SEMI : ';'; + +DOT : '.'; +RANGE : ".."; + +ASSIGN : ":="; + +EQ : '='; +GT : '>'; +LT : '<'; +GE : ">="; +LE : "<="; +NE : "<>"; + +PLUS : '+'; +MINUS : '-'; + +STAR : '*'; +SLASH : '/'; + +PTR : '^'; + +// ============================================================================ +// Identifier +// ============================================================================ +ID +options +{ + testLiterals=true; +} + : LETTER (LETTER | DIGIT)* ; + +// ============================================================================ +// Int or real +// ============================================================================ +UINT_OR_REAL + : (UINT RANGE) => UINT { _ttype := TT_UINT; } + | (UINT DOT) => UREAL { _ttype := TT_UREAL; } + | (UINT ('E'|'e')) => UREAL { _ttype := TT_UREAL; } + | UINT { _ttype := TT_UINT; } + ; + +// ============================================================================ +// Protected rules +// ============================================================================ +protected +LETTER : 'a'..'z' | 'A'..'Z' | '_'; + +// ============================================================================ +// Int +// ============================================================================ +protected +UINT + : (DIGIT)+ + ; + +// ============================================================================ +// Real +// ============================================================================ +protected +UREAL + : UINT ('.' UINT)? ( ('e' | 'E') ('+'|'-')? UINT)? + ; + +// ============================================================================ +// Digit +// ============================================================================ +protected +DIGIT + : '0'..'9' + ; + +// ============================================================================ +// String or char +// ============================================================================ +STRING_OR_CHAR + : '\'' (~'\'' | '\'' '\'')* '\'' + { + if TokenText = '''''' then _ttype := TT_STRING + else if TokenText = '''''''''' then _ttype := TT_CHAR + else if Length( TokenText) > 3 then _ttype := TT_STRING + else _ttype := TT_CHAR; + } + ; + +// ============================================================================ +// Single line comment +// ============================================================================ +SLCOMMENT + : + "//" + ( ~( '\r' | '\n') )* + ( + '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + ) + { + _ttype := TT_SKIP; + } + ; + +// ============================================================================ +// Multi line comment version 1 +// Nested comments aren't allowed! +// ============================================================================ +MLCOMMENT1 + : + "(*" + ( + options + { + greedy = false; + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | . + )* + "*)" + { + _ttype := TT_SKIP; + } + ; + +// ============================================================================ +// Multi line comment version 2 +// Nested comments aren't allowed! +// ============================================================================ +MLCOMMENT2 + : + "{" + ( + options + { + greedy = false; + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | . + )* + "}" + { + _ttype := TT_SKIP; + } + ; + +// ============================================================================ +// White space +// ============================================================================ +WS + : + ( + '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | '\t' { tab; } + | ' ' + ) + { + _ttype := TT_SKIP; + } + ; diff --git a/doc/grammars/pascal/wpParser.g b/doc/grammars/pascal/wpParser.g new file mode 100644 index 0000000..4e2fa70 --- /dev/null +++ b/doc/grammars/pascal/wpParser.g @@ -0,0 +1,368 @@ +unit wpParser; + +parser TwpParser; +options +{ + importVocab = wpLexer; + k = 2; +} + +// ============================================================================ +// prog +// ============================================================================ +prog + : "program" id (LPAREN id (COLON id)* RPAREN)? SEMI block DOT + ; + +// ============================================================================ +// block +// ============================================================================ +block + : declarations compoundStmt + ; + +// ============================================================================ +// declarations +// ============================================================================ +declarations + : + ( "label" UINT (COMMA UINT)* SEMI )? + ( "const" (id EQ constant SEMI)+ )? + ( "type" (id EQ typeSpec SEMI)+ )? + ( "var" (id (COMMA id)* COLON typeSpec SEMI)+ )? + + ( + "procedure" id parameterList SEMI block SEMI + | "function" id parameterList COLON id SEMI block SEMI + )* + ; + +// ============================================================================ +// statement +// ============================================================================ +statement + : (UINT COLON)? + ( + (variable ASSIGN) => assignmentStmt + | procedureCall + | compoundStmt + | ifStmt + | caseStmt + | whileStmt + | repeatStmt + | forStmt + | withStmt + | gotoStmt + )? + ; + +// ============================================================================ +// assignmentStmt +// ============================================================================ +assignmentStmt + : variable ASSIGN expression + ; + +// ============================================================================ +// procedureCall +// ============================================================================ +procedureCall + : id (LPAREN expression (widthSpec)? (COMMA expression (widthSpec)? )* RPAREN)? + ; + +// ============================================================================ +// widthSpec +// ============================================================================ +widthSpec + : (COLON UINT) (COLON UINT)? + ; + + +// ============================================================================ +// compoundStmt +// ============================================================================ +compoundStmt + : "begin" (statement (SEMI statement)*)? "end" + ; + +// ============================================================================ +// ifStmt +// ============================================================================ +ifStmt + : "if" expression "then" statement + ( + ("else") => "else" statement + | + ) + ; + +// ============================================================================ +// caseStmt +// ============================================================================ +caseStmt + : "case" expression "of" + ( caseStmtItem (SEMI caseStmtItem)* )? + "end" + ; + +// ============================================================================ +// caseStmtItem +// ============================================================================ +caseStmtItem + : constant (COMMA constant)* COLON statement + ; + +// ============================================================================ +// whileStmt +// ============================================================================ +whileStmt + : "while" expression "do" statement + ; + +// ============================================================================ +// repeatStmt +// ============================================================================ +repeatStmt + : "repeat" (statement (SEMI statement)*)? "until" expression + ; + +// ============================================================================ +// forStmt +// ============================================================================ +forStmt + : "for" id ASSIGN expression ("to" | "downto") expression "do" statement + ; + +// ============================================================================ +// withStmt +// ============================================================================ +withStmt + : "with" variable (COMMA variable)* "do" statement + ; + +// ============================================================================ +// gotoStmt +// ============================================================================ +gotoStmt + : "goto" UINT + ; + + +// ============================================================================ +// parameterList +// ============================================================================ +parameterList + : ( + LPAREN + parameter (SEMI parameter)* + RPAREN + )? + ; + +// ============================================================================ +// parameter +// ============================================================================ +parameter + : ("var" | "function")? id (COMMA id)* COLON typeId + | "procedure" id (COMMA id)* + ; + + +// ============================================================================ +// expression +// ============================================================================ +expression + : simpleExpression (relOp simpleExpression)* + ; + +// ============================================================================ +// simpleExpression +// ============================================================================ +simpleExpression + : (PLUS|MINUS)? term (addOp term)* + ; + +// ============================================================================ +// term +// ============================================================================ +term + : factor (mulOp factor)* + ; + +// ============================================================================ +// factor +// ============================================================================ +factor + : uNumber + | "nil" + | CHAR + | STRING + | (id LPAREN) => procedureCall + | variable + | LPAREN expression RPAREN + | "not" factor + | LBRACKET (expression (RANGE expression)? (COMMA expression (RANGE expression)? )* )? RBRACKET + ; + +// ============================================================================ +// variable +// ============================================================================ +variable + : variableId + ( + LBRACKET expression (COMMA expression)* RBRACKET + | DOT fieldId + | PTR + )* + ; + +// ============================================================================ +// fieldList +// ============================================================================ +fieldList + : simpleFieldList (simpleFieldList)* (variantFieldList)? + | + ; + +// ============================================================================ +// simpleFieldList +// ============================================================================ +simpleFieldList + : id (COMMA id)* COLON typeSpec + ; + +// ============================================================================ +// caseFieldList +// ============================================================================ +variantFieldList + : "case" (id COLON)? typeId "of" + constant (COMMA constant)* COLON LPAREN fieldList RPAREN + (SEMI constant (COMMA constant)* COLON LPAREN fieldList RPAREN)* + ; + +// ============================================================================ +// typeSpecification +// ============================================================================ +typeSpec + : simpleType + | PTR typeId + | ("packed")? + ( + "array" LBRACKET simpleType (COMMA simpleType)* RBRACKET "of" typeSpec + | "file" "of" typeSpec + | "set" "of" simpleType + | "record" fieldList "end" + ) + ; + +// ============================================================================ +// simpleType +// ============================================================================ +simpleType + : (constant RANGE) => constant RANGE constant + | typeId + | LPAREN id (COMMA id)* RPAREN + ; + +// ============================================================================ +// constant +// ============================================================================ +constant + : (PLUS | MINUS)? (constantId | uNumber) + | CHAR + ; + +// ============================================================================ +// unsignedConstant +// ============================================================================ +uConstant + : constantId + | uNumber + | "nil" + | CHAR + ; + +// ============================================================================ +// unumber +// ============================================================================ +uNumber + : UINT + | UREAL + ; + +// ============================================================================ +// uint +// ============================================================================ +uInt + : UINT; + +// ============================================================================ +// fieldId +// ============================================================================ +fieldId + : id + ; + +// ============================================================================ +// variableId +// ============================================================================ +variableId + : id + ; + +// ============================================================================ +// typeId +// ============================================================================ +typeId + : id + ; + +// ============================================================================ +// constantId +// ============================================================================ +constantId + : id + ; + +// ============================================================================ +// id +// ============================================================================ +id + : ID + ; + +// ============================================================================ +// relOp +// ============================================================================ +relOp + : GT + | LT + | GE + | LE + | NE + | EQ + | "in" + ; + +// ============================================================================ +// addOp +// ============================================================================ +addOp + : PLUS + | MINUS + | "or" + | "xor" + ; + +// ============================================================================ +// mulOp +// ============================================================================ +mulOp + : STAR + | SLASH + | "div" + | "mod" + | "and" + ; + + diff --git a/doc/tutorial/calc/calc.dpr b/doc/tutorial/calc/calc.dpr new file mode 100644 index 0000000..0c90e80 --- /dev/null +++ b/doc/tutorial/calc/calc.dpr @@ -0,0 +1,36 @@ +program calc; + +{$APPTYPE CONSOLE} + +uses + Classes, + SysUtils, + calcLexer in 'calcLexer.pas', + calcParser in 'calcParser.pas'; + +var + stm: TFileStream; + lex: TcalcLexer; + par: TcalcParser; + +begin + if ParamCount <> 1 then + begin + writeln('usage: calc '); + exit; + end + else + begin + try + stm := TFileStream.Create( ParamStr(1), fmOpenRead); + lex := TcalcLexer.Create(stm); + par := TcalcParser.Create(lex); + + par.calc; + except + end; + end; + + stm.Free; + par.Free; +end. diff --git a/doc/tutorial/calc/calc.txt b/doc/tutorial/calc/calc.txt new file mode 100644 index 0000000..fb388c7 --- /dev/null +++ b/doc/tutorial/calc/calc.txt @@ -0,0 +1,5 @@ +1+2+3+4+5+6+7+8+9; +(((((2+3))))); +(-1*(-2*(-3*(-4+ -5)))); +(-1*(-2*(-3*(-4+ 5)))); +7 * -(-9); \ No newline at end of file diff --git a/doc/tutorial/calc/calcLexer.g b/doc/tutorial/calc/calcLexer.g new file mode 100644 index 0000000..bfc7a1c --- /dev/null +++ b/doc/tutorial/calc/calcLexer.g @@ -0,0 +1,49 @@ +// ============================================================================ +// Demo lexer for four operator calculator +// ============================================================================ +unit calcLexer; + +lexer TcalcLexer; +options +{ + exportVocab = calcLexer; +} + +// ============================================================================ +// Simple tokens +// ============================================================================ +LPAREN : '('; +RPAREN : ')'; + +PLUS : '+'; +MINUS : '-'; +STAR : '*'; +SLASH : '/'; + +SEMI : ';'; + +// ============================================================================ +// INT +// ============================================================================ +INT : ('0'..'9')+; + +// ============================================================================ +// White space +// ============================================================================ +WS + : + ( + options + { + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | '\t' { tab; } + | ' ' + ) + { + _ttype := TT_SKIP; + } + ; diff --git a/doc/tutorial/calc/calcLexer.pas b/doc/tutorial/calc/calcLexer.pas new file mode 100644 index 0000000..c292243 --- /dev/null +++ b/doc/tutorial/calc/calcLexer.pas @@ -0,0 +1,430 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0d +// Grammar: calcLexer +// ============================================================================ +unit calcLexer; + +interface + +uses + calcLexerTokens, + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTypes, + SysUtils; + +type + // ========================================================================= + // Class TcalcLexer declaration + // ========================================================================= + TcalcLexer = class( TdpgLexer) + + protected // Public grammar rules ("rescoped") + procedure mLPAREN ( pCreate: boolean); + procedure mRPAREN ( pCreate: boolean); + procedure mPLUS ( pCreate: boolean); + procedure mMINUS ( pCreate: boolean); + procedure mSTAR ( pCreate: boolean); + procedure mSLASH ( pCreate: boolean); + procedure mSEMI ( pCreate: boolean); + procedure mINT ( pCreate: boolean); + procedure mWS ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mLPAREN +// ============================================================================ +procedure TcalcLexer.mLPAREN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_LPAREN; + + match('('); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mRPAREN +// ============================================================================ +procedure TcalcLexer.mRPAREN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_RPAREN; + + match(')'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mPLUS +// ============================================================================ +procedure TcalcLexer.mPLUS( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_PLUS; + + match('+'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mMINUS +// ============================================================================ +procedure TcalcLexer.mMINUS( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_MINUS; + + match('-'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mSTAR +// ============================================================================ +procedure TcalcLexer.mSTAR( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_STAR; + + match('*'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mSLASH +// ============================================================================ +procedure TcalcLexer.mSLASH( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_SLASH; + + match('/'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mSEMI +// ============================================================================ +procedure TcalcLexer.mSEMI( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_SEMI; + + match(';'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mINT +// ============================================================================ +procedure TcalcLexer.mINT( pCreate: boolean); +var + _begin: integer; + _cnt_10: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_INT; + + _cnt_10 := 0; + + while(true) do + begin + if (( LA(1) in ['0'..'9'])) then + begin + match( ['0'..'9']); + end + + else + begin + if _cnt_10 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), ['0'..'9'], FileName, Line, Column); + end; + + INC(_cnt_10); + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mWS +// ============================================================================ +procedure TcalcLexer.mWS( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_WS; + + if (( LA(1) in [#13])) then + begin + match(#13); + match(#10); + newLine; + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; + end + + else if (( LA(1) in [#9])) then + begin + match(#9); + tab; + end + + else if (( LA(1) in [' '])) then + begin + match(' '); + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#9..#10,#13,' '], FileName, Line, Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function TcalcLexer.NextToken : IdpgToken; +var + _first : TdpgCharSet; + +begin + _first := [#9..#10,#13,' ','('..'+','-','/'..'9',';']; + + while( true) do + begin + ResetText; + + try + if (( LA(1) in ['('])) then + begin + mLPAREN(true); + result := fReturnToken; + end + + else if (( LA(1) in [')'])) then + begin + mRPAREN(true); + result := fReturnToken; + end + + else if (( LA(1) in ['+'])) then + begin + mPLUS(true); + result := fReturnToken; + end + + else if (( LA(1) in ['-'])) then + begin + mMINUS(true); + result := fReturnToken; + end + + else if (( LA(1) in ['*'])) then + begin + mSTAR(true); + result := fReturnToken; + end + + else if (( LA(1) in ['/'])) then + begin + mSLASH(true); + result := fReturnToken; + end + + else if (( LA(1) in [';'])) then + begin + mSEMI(true); + result := fReturnToken; + end + + else if (( LA(1) in ['0'..'9'])) then + begin + mINT(true); + result := fReturnToken; + end + + else if (( LA(1) in [#9..#10,#13,' '])) then + begin + mWS(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + Raise EdpgMismatchedChar.Create(LA(1), _first, FileName, Line, Column); + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + Raise; + end; + end; +end; + +end. diff --git a/doc/tutorial/calc/calcLexerTokens.pas b/doc/tutorial/calc/calcLexerTokens.pas new file mode 100644 index 0000000..3ba0e97 --- /dev/null +++ b/doc/tutorial/calc/calcLexerTokens.pas @@ -0,0 +1,24 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0d +// Grammar: calcLexer +// ============================================================================ +unit calcLexerTokens; + +interface + +const + TT_EOF = 1; + TT_LPAREN = 4; + TT_RPAREN = 5; + TT_PLUS = 6; + TT_MINUS = 7; + TT_STAR = 8; + TT_SLASH = 9; + TT_SEMI = 10; + TT_INT = 11; + TT_WS = 12; + +implementation +end. diff --git a/doc/tutorial/calc/calcLexerTokens.txt b/doc/tutorial/calc/calcLexerTokens.txt new file mode 100644 index 0000000..e1bf466 --- /dev/null +++ b/doc/tutorial/calc/calcLexerTokens.txt @@ -0,0 +1,12 @@ +// $Delphi Parser Generator: calcLexer -> calcLexerTokens.txt$ +TcalcLexer +TT_EOF=1 +TT_LPAREN=4 +TT_RPAREN=5 +TT_PLUS=6 +TT_MINUS=7 +TT_STAR=8 +TT_SLASH=9 +TT_SEMI=10 +TT_INT=11 +TT_WS=12 diff --git a/doc/tutorial/calc/calcParser.g b/doc/tutorial/calc/calcParser.g new file mode 100644 index 0000000..ed1db46 --- /dev/null +++ b/doc/tutorial/calc/calcParser.g @@ -0,0 +1,93 @@ +// ============================================================================ +// Demo parser for four operator calculator +// ============================================================================ +unit calcParser; + +parser TcalcParser; +options +{ + importVocab = calcLexer; + exportVocab = calcParser; +// k = 2; +} + +// ============================================================================ +// calc +// ============================================================================ +calc +local +{ + v: integer; +} + : (v=expression SEMI {writeln(v);} )+ + ; + + +// ============================================================================ +// expression +// ============================================================================ +expression returns [integer] + : result=simpleExpression + ; + +// ============================================================================ +// simpleExpression +// ============================================================================ +simpleExpression returns [integer] +local +{ + v : integer; +} + : result=term + ( + PLUS v=term { result := result + v; } + | MINUS v=term { result := result - v; } + )* + ; + +// ============================================================================ +// term +// ============================================================================ +term returns [integer] +local +{ + v : integer; +} + : result=factor + ( + STAR v=factor { result := result * v; } + | SLASH v=factor { result := result div v; } + )* + ; + +// ============================================================================ +// factor +// ============================================================================ +factor returns [integer] +local +{ + s: integer; +} +{ + s := 1; +} + : + ( + PLUS { s := 1; } + | MINUS { s := -1; } + )? + ( + result=uInt + | LPAREN result=expression RPAREN + ) + { + result := s * result; + } + ; + +// ============================================================================ +// uInt +// ============================================================================ +uInt returns [integer] + : x:INT { result := StrToInt( x.TokenText); } + ; diff --git a/doc/tutorial/calc/calcParser.pas b/doc/tutorial/calc/calcParser.pas new file mode 100644 index 0000000..f6c5990 --- /dev/null +++ b/doc/tutorial/calc/calcParser.pas @@ -0,0 +1,203 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0d +// Grammar: calcParser +// ============================================================================ +unit calcParser; + +interface + +uses + calcParserTokens, + Classes, + Contnrs, + dpgLLkParser, + dpgToken, + dpgTypes, + SysUtils; + +type + // ========================================================================= + // Class TcalcParser declaration + // ========================================================================= + TcalcParser = class( TdpgLLkParser) + + public // Public grammar rules + procedure calc ; + procedure expression ; + procedure simpleExpression ; + procedure term ; + procedure factor ; + procedure uInt ; + + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedToken; + +// ============================================================================ +// calc +// ============================================================================ +procedure TcalcParser.calc; +var + _cnt_16: integer; + v: integer; + +begin + + _cnt_16 := 0; + + while(true) do + begin + if (( LA(1) in [TT_LPAREN,TT_PLUS..TT_MINUS,TT_INT])) then + begin + expression; + match(TT_SEMI); + writeln(v); + end + + else + begin + if _cnt_16 >= 1 then + break + else + Raise EdpgMismatchedToken.Create( LT(1), [TT_LPAREN,TT_PLUS..TT_MINUS,TT_INT], FileName); + end; + + INC(_cnt_16); + end; +end; + +// ============================================================================ +// expression +// ============================================================================ +procedure TcalcParser.expression; +begin + + simpleExpression; +end; + +// ============================================================================ +// simpleExpression +// ============================================================================ +procedure TcalcParser.simpleExpression; +var + v : integer; + +begin + + term; + + while(true) do + begin + if (( LA(1) in [TT_PLUS])) then + begin + match(TT_PLUS); + term; + result := result + v; + end + + else if (( LA(1) in [TT_MINUS])) then + begin + match(TT_MINUS); + term; + result := result - v; + end + + else + break; + end; + +end; + +// ============================================================================ +// term +// ============================================================================ +procedure TcalcParser.term; +var + v : integer; + +begin + + factor; + + while(true) do + begin + if (( LA(1) in [TT_STAR])) then + begin + match(TT_STAR); + factor; + result := result * v; + end + + else if (( LA(1) in [TT_SLASH])) then + begin + match(TT_SLASH); + factor; + result := result div v; + end + + else + break; + end; + +end; + +// ============================================================================ +// factor +// ============================================================================ +procedure TcalcParser.factor; +var + s: integer; + +begin + + s := 1; + + if (( LA(1) in [TT_PLUS])) then + begin + match(TT_PLUS); + s := 1; + end + + else if (( LA(1) in [TT_MINUS])) then + begin + match(TT_MINUS); + s := -1; + end; + if (( LA(1) in [TT_INT])) then + begin + uInt; + end + + else if (( LA(1) in [TT_LPAREN])) then + begin + match(TT_LPAREN); + expression; + match(TT_RPAREN); + end + + else + Raise EdpgMismatchedToken.Create( LT(1), [TT_LPAREN,TT_INT], FileName); + result := s * result; +end; + +// ============================================================================ +// uInt +// ============================================================================ +procedure TcalcParser.uInt; +var + x: IdpgToken; + +begin + + x := LT(1); + match(TT_INT); + result := StrToInt( x.TokenText); +end; + +end. diff --git a/doc/tutorial/calc/calcParserTokens.pas b/doc/tutorial/calc/calcParserTokens.pas new file mode 100644 index 0000000..e62c38c --- /dev/null +++ b/doc/tutorial/calc/calcParserTokens.pas @@ -0,0 +1,24 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0d +// Grammar: calcParser +// ============================================================================ +unit calcParserTokens; + +interface + +const + TT_EOF = 1; + TT_LPAREN = 4; + TT_RPAREN = 5; + TT_PLUS = 6; + TT_MINUS = 7; + TT_STAR = 8; + TT_SLASH = 9; + TT_SEMI = 10; + TT_INT = 11; + TT_WS = 12; + +implementation +end. diff --git a/doc/tutorial/calc/calcParserTokens.txt b/doc/tutorial/calc/calcParserTokens.txt new file mode 100644 index 0000000..c791ee4 --- /dev/null +++ b/doc/tutorial/calc/calcParserTokens.txt @@ -0,0 +1,12 @@ +// $Delphi Parser Generator: calcParser -> calcParserTokens.txt$ +TcalcParser +TT_EOF=1 +TT_LPAREN=4 +TT_RPAREN=5 +TT_PLUS=6 +TT_MINUS=7 +TT_STAR=8 +TT_SLASH=9 +TT_SEMI=10 +TT_INT=11 +TT_WS=12 diff --git a/doc/tutorial/calc/readme.txt b/doc/tutorial/calc/readme.txt new file mode 100644 index 0000000..e488282 --- /dev/null +++ b/doc/tutorial/calc/readme.txt @@ -0,0 +1,11 @@ +To build demo project you must first compile the grammars. +This grammar CAN NOT! be compiled with the demo version of dpg. + +1. dpg calcLexer.g +2. dpg calcParser.g + +After the compilation the project can be opened in delphi. Be sure that the dpg +runtime library is in the delphi library path. (In the project settings, +or in the environment settings). + +Have fun... \ No newline at end of file diff --git a/doc/tutorial/hoc/hoc 1/hocLexer.g b/doc/tutorial/hoc/hoc 1/hocLexer.g new file mode 100644 index 0000000..b36fd77 --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocLexer.g @@ -0,0 +1,91 @@ +unit hocLexer; + +// ============================================================================ +// Lexer class declaration +// ============================================================================ +lexer ThocLexer; + +// ---------------------------------------------------------------------------- +// Lexer options +// ---------------------------------------------------------------------------- +options +{ + k = 2; + exportVocab = hocLexer; + caseSensitive = false; +} + +// ============================================================================ +// Begin rule definitions +// +// Remember: All lexer rule names must begin with UPPERCASE letter! +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Simple tokens +// ---------------------------------------------------------------------------- +LPAREN : '('; +RPAREN : ')'; + +PLUS : '+'; +MINUS : '-'; +STAR : '*'; +SLASH : '/'; + +// ---------------------------------------------------------------------------- +// NUMBER +// ---------------------------------------------------------------------------- +UNUMBER + : UINT ('.' UINT)? + ; + +// ---------------------------------------------------------------------------- +// UINT +// ---------------------------------------------------------------------------- +protected +UINT + : (DIGIT)+ + ; + +// ---------------------------------------------------------------------------- +// DIGIT +// ---------------------------------------------------------------------------- +protected +DIGIT + : '0'..'9' + ; + +// ---------------------------------------------------------------------------- +// NEWLINE +// ---------------------------------------------------------------------------- +NEWLINE + : + ( + options + { + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + ) + ; + +// ---------------------------------------------------------------------------- +// WHITESPACE +// ---------------------------------------------------------------------------- +WHITESPACE + : + ( + ' ' + | '\t' { tab; } + ) + { + _ttype := TT_SKIP; + } + ; + +// ============================================================================ +// End rule definitions +// ============================================================================ + diff --git a/doc/tutorial/hoc/hoc 1/hocLexer.pas b/doc/tutorial/hoc/hoc 1/hocLexer.pas new file mode 100644 index 0000000..960398b --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocLexer.pas @@ -0,0 +1,505 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0r +// Grammar: hocLexer +// ============================================================================ +unit hocLexer; + +interface + +uses + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTypes, + hocLexerTokens, + SysUtils; + +type + // ========================================================================= + // Class ThocLexer declaration + // ========================================================================= + ThocLexer = class( TdpgLexer) + + protected // Internals + procedure initialize; override; + + protected // Protected grammar rules + procedure mUINT ( pCreate: boolean); + procedure mDIGIT ( pCreate: boolean); + + protected // Public grammar rules ("rescoped") + procedure mLPAREN ( pCreate: boolean); + procedure mRPAREN ( pCreate: boolean); + procedure mPLUS ( pCreate: boolean); + procedure mMINUS ( pCreate: boolean); + procedure mSTAR ( pCreate: boolean); + procedure mSLASH ( pCreate: boolean); + procedure mUNUMBER ( pCreate: boolean); + procedure mNEWLINE ( pCreate: boolean); + procedure mWHITESPACE ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mLPAREN +// ============================================================================ +procedure ThocLexer.mLPAREN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_LPAREN; + + match('('); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mRPAREN +// ============================================================================ +procedure ThocLexer.mRPAREN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_RPAREN; + + match(')'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mPLUS +// ============================================================================ +procedure ThocLexer.mPLUS( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_PLUS; + + match('+'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mMINUS +// ============================================================================ +procedure ThocLexer.mMINUS( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_MINUS; + + match('-'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mSTAR +// ============================================================================ +procedure ThocLexer.mSTAR( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_STAR; + + match('*'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mSLASH +// ============================================================================ +procedure ThocLexer.mSLASH( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_SLASH; + + match('/'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mUNUMBER +// ============================================================================ +procedure ThocLexer.mUNUMBER( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_UNUMBER; + + mUINT(false); + if (( LA(1) in ['.'])) then + begin + match('.'); + mUINT(false); + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mUINT +// ============================================================================ +procedure ThocLexer.mUINT( pCreate: boolean); +var + _begin: integer; + _cnt_40: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_UINT; + + _cnt_40 := 0; + + while(true) do + begin + if (( LA(1) in ['0'..'9'])) then + begin + mDIGIT(false); + end + + else + begin + if _cnt_40 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), ['0'..'9'], FileName, Line, Column); + end; + + INC(_cnt_40); + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mDIGIT +// ============================================================================ +procedure ThocLexer.mDIGIT( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_DIGIT; + + match( ['0'..'9']); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mNEWLINE +// ============================================================================ +procedure ThocLexer.mNEWLINE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_NEWLINE; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + newLine; + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#10,#13], FileName, Line, Column); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mWHITESPACE +// ============================================================================ +procedure ThocLexer.mWHITESPACE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_WHITESPACE; + + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else if (( LA(1) in [#9])) then + begin + match(#9); + tab; + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#9,' '], FileName, Line, Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function ThocLexer.NextToken : IdpgToken; +var + _first : TdpgCharSet; + +begin + _first := [#9..#10,#13,' ','('..'+','-','/'..'9']; + + while( true) do + begin + ResetText; + + try + if (( LA(1) in ['('])) then + begin + mLPAREN(true); + result := fReturnToken; + end + + else if (( LA(1) in [')'])) then + begin + mRPAREN(true); + result := fReturnToken; + end + + else if (( LA(1) in ['+'])) then + begin + mPLUS(true); + result := fReturnToken; + end + + else if (( LA(1) in ['-'])) then + begin + mMINUS(true); + result := fReturnToken; + end + + else if (( LA(1) in ['*'])) then + begin + mSTAR(true); + result := fReturnToken; + end + + else if (( LA(1) in ['/'])) then + begin + mSLASH(true); + result := fReturnToken; + end + + else if (( LA(1) in ['0'..'9'])) then + begin + mUNUMBER(true); + result := fReturnToken; + end + + else if (( LA(1) in [#10,#13])) then + begin + mNEWLINE(true); + result := fReturnToken; + end + + else if (( LA(1) in [#9,' '])) then + begin + mWHITESPACE(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + Raise EdpgMismatchedChar.Create(LA(1), _first, FileName, Line, Column); + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + Raise; + end; + end; +end; + +// ---------------------------------------------------------------------------- +// InitLiterals +// ---------------------------------------------------------------------------- +procedure ThocLexer.initialize; +begin + fCaseSensitive := false; + fLiterals.CaseSensitive := false; + +end; + +end. diff --git a/doc/tutorial/hoc/hoc 1/hocLexerTokens.pas b/doc/tutorial/hoc/hoc 1/hocLexerTokens.pas new file mode 100644 index 0000000..5670b01 --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocLexerTokens.pas @@ -0,0 +1,26 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0r +// Grammar: hocLexer +// ============================================================================ +unit hocLexerTokens; + +interface + +const + TT_EOF = 1; + TT_LPAREN = 4; + TT_RPAREN = 5; + TT_PLUS = 6; + TT_MINUS = 7; + TT_STAR = 8; + TT_SLASH = 9; + TT_UNUMBER = 10; + TT_UINT = 11; + TT_DIGIT = 12; + TT_NEWLINE = 13; + TT_WHITESPACE = 14; + +implementation +end. diff --git a/doc/tutorial/hoc/hoc 1/hocLexerTokens.txt b/doc/tutorial/hoc/hoc 1/hocLexerTokens.txt new file mode 100644 index 0000000..ba67c9d --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocLexerTokens.txt @@ -0,0 +1,14 @@ +// $Delphi Parser Generator: hocLexer -> hocLexerTokens.txt$ +ThocLexer +TT_EOF=1 +TT_LPAREN=4 +TT_RPAREN=5 +TT_PLUS=6 +TT_MINUS=7 +TT_STAR=8 +TT_SLASH=9 +TT_UNUMBER=10 +TT_UINT=11 +TT_DIGIT=12 +TT_NEWLINE=13 +TT_WHITESPACE=14 diff --git a/doc/tutorial/hoc/hoc 1/hocParser.g b/doc/tutorial/hoc/hoc 1/hocParser.g new file mode 100644 index 0000000..987cd76 --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocParser.g @@ -0,0 +1,101 @@ +unit hocParser; + +// ============================================================================ +// Parser class declaration +// ============================================================================ +parser ThocParser; + +// ---------------------------------------------------------------------------- +// Parser options +// ---------------------------------------------------------------------------- +options +{ + k = 2; + importVocab = hocLexer; + exportVocab = hocParser; +} + +// ============================================================================ +// Begin rule definitions +// +// Remember: All parser rule names must begin with LOWERCASE letter! +// ============================================================================ + +// ---------------------------------------------------------------------------- +// prog +// ---------------------------------------------------------------------------- +prog +local +{ + val : double; +} + : + ( + ( + val = expression + )? + + NEWLINE + )* + ; + +// ---------------------------------------------------------------------------- +// expression +// ---------------------------------------------------------------------------- +expression returns [double] +local +{ + val : double; +} + : result = term + ( + PLUS val = term { result := result + val; } + | MINUS val = term { result := result - val; } + )* + ; + +// ---------------------------------------------------------------------------- +// term +// ---------------------------------------------------------------------------- +term returns [double] +local +{ + val : double; +} + : result = factor + ( + STAR val = factor { result := result * val; } + | SLASH val = factor { result := result / val; } + )* + ; + +// ---------------------------------------------------------------------------- +// factor +// ---------------------------------------------------------------------------- +factor returns [double] + : result = uNumber + | LPAREN result = expression RPAREN + ; + +// ---------------------------------------------------------------------------- +// uNumber +// ---------------------------------------------------------------------------- +uNumber returns [double] + : n:UNUMBER + { + result := StrToIntDef( n.TokenText); + } + ; + +// ============================================================================ +// End rule definitions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// This section is used for generating member defintions in the unit 'hocParser'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +memberdef +{ +} + diff --git a/doc/tutorial/hoc/hoc 1/hocParser.pas b/doc/tutorial/hoc/hoc 1/hocParser.pas new file mode 100644 index 0000000..715a208 --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocParser.pas @@ -0,0 +1,170 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0r +// Grammar: hocParser +// ============================================================================ +unit hocParser; + +interface + +uses + Classes, + Contnrs, + dpgLLkParser, + dpgToken, + dpgTypes, + hocParserTokens, + SysUtils; + +type + // ========================================================================= + // Class ThocParser declaration + // ========================================================================= + ThocParser = class( TdpgLLkParser) + + public // Public grammar rules + procedure prog ; + function expression : double; + function term : double; + function factor : double; + function uNumber : double; + + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedToken; + +// ============================================================================ +// prog +// ============================================================================ +procedure ThocParser.prog; +var + val : double; + +begin + + + while(true) do + begin + if (( LA(1) in [TT_LPAREN,TT_UNUMBER,TT_NEWLINE])) then + begin + if (( LA(1) in [TT_LPAREN,TT_UNUMBER])) then + begin + val := expression; + end; + match(TT_NEWLINE); + end + + else + break; + end; + +end; + +// ============================================================================ +// expression +// ============================================================================ +function ThocParser.expression: double; +var + val : double; + +begin + + result := term; + + while(true) do + begin + if (( LA(1) in [TT_PLUS])) then + begin + match(TT_PLUS); + val := term; + result := result + val; + end + + else if (( LA(1) in [TT_MINUS])) then + begin + match(TT_MINUS); + val := term; + result := result - val; + end + + else + break; + end; + +end; + +// ============================================================================ +// term +// ============================================================================ +function ThocParser.term: double; +var + val : double; + +begin + + result := factor; + + while(true) do + begin + if (( LA(1) in [TT_STAR])) then + begin + match(TT_STAR); + val := factor; + result := result * val; + end + + else if (( LA(1) in [TT_SLASH])) then + begin + match(TT_SLASH); + val := factor; + result := result / val; + end + + else + break; + end; + +end; + +// ============================================================================ +// factor +// ============================================================================ +function ThocParser.factor: double; +begin + + if (( LA(1) in [TT_UNUMBER])) then + begin + result := uNumber; + end + + else if (( LA(1) in [TT_LPAREN])) then + begin + match(TT_LPAREN); + result := expression; + match(TT_RPAREN); + end + + else + Raise EdpgMismatchedToken.Create( LT(1), [TT_LPAREN,TT_UNUMBER], FileName); +end; + +// ============================================================================ +// uNumber +// ============================================================================ +function ThocParser.uNumber: double; +var + n: IdpgToken; + +begin + + n := LT(1); + match(TT_UNUMBER); + result := StrToIntDef( n.TokenText); +end; + +end. diff --git a/doc/tutorial/hoc/hoc 1/hocParserTokens.pas b/doc/tutorial/hoc/hoc 1/hocParserTokens.pas new file mode 100644 index 0000000..228cdc3 --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocParserTokens.pas @@ -0,0 +1,26 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.1.0r +// Grammar: hocParser +// ============================================================================ +unit hocParserTokens; + +interface + +const + TT_EOF = 1; + TT_LPAREN = 4; + TT_RPAREN = 5; + TT_PLUS = 6; + TT_MINUS = 7; + TT_STAR = 8; + TT_SLASH = 9; + TT_UNUMBER = 10; + TT_UINT = 11; + TT_DIGIT = 12; + TT_NEWLINE = 13; + TT_WHITESPACE = 14; + +implementation +end. diff --git a/doc/tutorial/hoc/hoc 1/hocParserTokens.txt b/doc/tutorial/hoc/hoc 1/hocParserTokens.txt new file mode 100644 index 0000000..f64cf94 --- /dev/null +++ b/doc/tutorial/hoc/hoc 1/hocParserTokens.txt @@ -0,0 +1,14 @@ +// $Delphi Parser Generator: hocParser -> hocParserTokens.txt$ +ThocParser +TT_EOF=1 +TT_LPAREN=4 +TT_RPAREN=5 +TT_PLUS=6 +TT_MINUS=7 +TT_STAR=8 +TT_SLASH=9 +TT_UNUMBER=10 +TT_UINT=11 +TT_DIGIT=12 +TT_NEWLINE=13 +TT_WHITESPACE=14 diff --git a/doc/tutorial/old/filter/filter.g b/doc/tutorial/old/filter/filter.g new file mode 100644 index 0000000..fcddd47 --- /dev/null +++ b/doc/tutorial/old/filter/filter.g @@ -0,0 +1,43 @@ +unit filter; + +lexer Tfilter; +options +{ + k = 2; + filter = true; +} + +// ---------------------------------------------------------------------------- +// Paragraph +// ---------------------------------------------------------------------------- +P + : "

" + ; + +// ---------------------------------------------------------------------------- +// Break +// ---------------------------------------------------------------------------- +BR + : "
" + ; + +// ---------------------------------------------------------------------------- +// Newline +// ---------------------------------------------------------------------------- +NEWLINE + : + ( + '\r' '\n' { newLine; _ttype := TT_SKIP; } + | '\r' { newLine; _ttype := TT_SKIP; } + | '\n' { newLine; _ttype := TT_SKIP; } + ) + ; + +// ---------------------------------------------------------------------------- +// Tab +// ---------------------------------------------------------------------------- +TAB + : '\t' { tab; _ttype := TT_SKIP; } + ; + + diff --git a/doc/tutorial/old/filter/filter.pas b/doc/tutorial/old/filter/filter.pas new file mode 100644 index 0000000..94c5345 --- /dev/null +++ b/doc/tutorial/old/filter/filter.pas @@ -0,0 +1,234 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.78r +// Grammar: filter.g +// ============================================================================ +unit filter; + +interface + +uses + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTypes, + filterTokens, + SysUtils; + +type + // ========================================================================= + // Class Tfilter declaration + // ========================================================================= + Tfilter = class( TdpgLexer) + + protected // Public grammar rules ("rescoped") + procedure mP ( pCreate: boolean); + procedure mBR ( pCreate: boolean); + procedure mNEWLINE ( pCreate: boolean); + procedure mTAB ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mP +// ============================================================================ +procedure Tfilter.mP( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_P; + + match('

'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mBR +// ============================================================================ +procedure Tfilter.mBR( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_BR; + + match('
'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mNEWLINE +// ============================================================================ +procedure Tfilter.mNEWLINE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_NEWLINE; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + newLine; _ttype := TT_SKIP; + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; _ttype := TT_SKIP; + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; _ttype := TT_SKIP; + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#10,#13], FileName, Line, Column); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mTAB +// ============================================================================ +procedure Tfilter.mTAB( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_TAB; + + match(#9); + tab; _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function Tfilter.NextToken : IdpgToken; +begin + while( true) do + begin + ResetText; + + try + if (( LA(1) in ['<']) and (LA(2) in ['p'])) then + begin + mP(true); + result := fReturnToken; + end + + else if (( LA(1) in ['<']) and (LA(2) in ['b'])) then + begin + mBR(true); + result := fReturnToken; + end + + else if (( LA(1) in [#10,#13])) then + begin + mNEWLINE(true); + result := fReturnToken; + end + + else if (( LA(1) in [#9])) then + begin + mTAB(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + begin + consume; + continue; + end; + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + consume; + continue; + end; + end; +end; + +end. diff --git a/doc/tutorial/old/filter/filterTokens.pas b/doc/tutorial/old/filter/filterTokens.pas new file mode 100644 index 0000000..b20bca4 --- /dev/null +++ b/doc/tutorial/old/filter/filterTokens.pas @@ -0,0 +1,19 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.78r +// Grammar: filter.g +// ============================================================================ +unit filterTokens; + +interface + +const + TT_EOF = 1; + TT_P = 4; + TT_BR = 5; + TT_NEWLINE = 6; + TT_TAB = 7; + +implementation +end. diff --git a/doc/tutorial/old/filter/filterTokens.txt b/doc/tutorial/old/filter/filterTokens.txt new file mode 100644 index 0000000..a93fffe --- /dev/null +++ b/doc/tutorial/old/filter/filterTokens.txt @@ -0,0 +1,7 @@ +// $Delphi Parser Generator: filter.pas -> TfilterTokens.txt$ +Tfilter +TT_EOF=1 +TT_P=4 +TT_BR=5 +TT_NEWLINE=6 +TT_TAB=7 diff --git a/doc/tutorial/old/multiLexer/JavaDocLexer.pas b/doc/tutorial/old/multiLexer/JavaDocLexer.pas new file mode 100644 index 0000000..2652451 --- /dev/null +++ b/doc/tutorial/old/multiLexer/JavaDocLexer.pas @@ -0,0 +1,367 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javadoclexer.g +// ============================================================================ +unit JavaDocLexer; + +interface + +uses + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTokenStreamSelector, + dpgTypes, + JavaDocTokens, + SysUtils; + +type + // ========================================================================= + // Class TJavaDocLexer declaration + // ========================================================================= + TJavaDocLexer = class( TdpgLexer) + + public + Selector : IdpgTokenStreamSelector; + + protected // Protected grammar rules + procedure mID ( pCreate: boolean); + + protected // Public grammar rules ("rescoped") + procedure mPARAM ( pCreate: boolean); + procedure mEXCEPTION ( pCreate: boolean); + procedure mSTAR ( pCreate: boolean); + procedure mJAVADOC_CLOSE ( pCreate: boolean); + procedure mNEWLINE ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mPARAM +// ============================================================================ +procedure TJavaDocLexer.mPARAM( pCreate: boolean); +var + _begin: integer; + _cnt_3: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_PARAM; + + match('@param'); + _cnt_3 := 0; + + while(true) do + begin + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else + begin + if _cnt_3 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), [' '], FileName, Line, Column); + end; + + INC(_cnt_3); + end; + mID(false); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mID +// ============================================================================ +procedure TJavaDocLexer.mID( pCreate: boolean); +var + _begin: integer; + _cnt_9: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_ID; + + _cnt_9 := 0; + + while(true) do + begin + if (( LA(1) in ['a'..'z'])) then + begin + match( ['a'..'z']); + end + + else + begin + if _cnt_9 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), ['a'..'z'], FileName, Line, Column); + end; + + INC(_cnt_9); + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mEXCEPTION +// ============================================================================ +procedure TJavaDocLexer.mEXCEPTION( pCreate: boolean); +var + _begin: integer; + _cnt_6: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_EXCEPTION; + + match('@exception'); + _cnt_6 := 0; + + while(true) do + begin + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else + begin + if _cnt_6 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), [' '], FileName, Line, Column); + end; + + INC(_cnt_6); + end; + mID(false); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mSTAR +// ============================================================================ +procedure TJavaDocLexer.mSTAR( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_STAR; + + match('*'); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mJAVADOC_CLOSE +// ============================================================================ +procedure TJavaDocLexer.mJAVADOC_CLOSE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_JAVADOC_CLOSE; + + match('*/'); + Selector.Pop; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mNEWLINE +// ============================================================================ +procedure TJavaDocLexer.mNEWLINE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_NEWLINE; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#10,#13], FileName, Line, Column); + newLine; + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function TJavaDocLexer.NextToken : IdpgToken; +var + la1 : char; + la2 : char; +begin + while( true) do + begin + ResetText; + + try + la1 := LA(1); + la2 := LA(2); + + if (( LA(1) in ['@']) and (LA(2) in ['p'])) then + begin + mPARAM(true); + result := fReturnToken; + end + + else if (( LA(1) in ['@']) and (LA(2) in ['e'])) then + begin + mEXCEPTION(true); + result := fReturnToken; + end + + else if (( LA(1) in ['*']) and (LA(2) in ['/'])) then + begin + mJAVADOC_CLOSE(true); + result := fReturnToken; + end + + else if (( LA(1) in ['*'])) then + begin + mSTAR(true); + result := fReturnToken; + end + + else if (( LA(1) in [#10,#13])) then + begin + mNEWLINE(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + begin + consume; + continue; + end; + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + consume; + continue; + end; + end; +end; + +end. diff --git a/doc/tutorial/old/multiLexer/JavaDocTokens.pas b/doc/tutorial/old/multiLexer/JavaDocTokens.pas new file mode 100644 index 0000000..8aa1885 --- /dev/null +++ b/doc/tutorial/old/multiLexer/JavaDocTokens.pas @@ -0,0 +1,21 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javadoclexer.g +// ============================================================================ +unit JavaDocTokens; + +interface + +const + TT_EOF = 1; + TT_PARAM = 4; + TT_EXCEPTION = 5; + TT_ID = 6; + TT_STAR = 7; + TT_JAVADOC_CLOSE = 8; + TT_NEWLINE = 9; + +implementation +end. diff --git a/doc/tutorial/old/multiLexer/JavaDocTokens.txt b/doc/tutorial/old/multiLexer/JavaDocTokens.txt new file mode 100644 index 0000000..10a1496 --- /dev/null +++ b/doc/tutorial/old/multiLexer/JavaDocTokens.txt @@ -0,0 +1,9 @@ +// $Delphi Parser Generator: JavaDocLexer.pas -> TJavaDocLexerTokens.txt$ +TJavaDocLexer +TT_EOF=1 +TT_PARAM=4 +TT_EXCEPTION=5 +TT_ID=6 +TT_STAR=7 +TT_JAVADOC_CLOSE=8 +TT_NEWLINE=9 diff --git a/doc/tutorial/old/multiLexer/JavaLexer.pas b/doc/tutorial/old/multiLexer/JavaLexer.pas new file mode 100644 index 0000000..206dcd5 --- /dev/null +++ b/doc/tutorial/old/multiLexer/JavaLexer.pas @@ -0,0 +1,286 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javalexer.g +// ============================================================================ +unit JavaLexer; + +interface + +uses + Classes, + Contnrs, + dpgLexer, + dpgToken, + dpgTokenStreamSelector, + dpgTypes, + JavaTokens, + SysUtils; + +type + // ========================================================================= + // Class TJavaLexer declaration + // ========================================================================= + TJavaLexer = class( TdpgLexer) + + public + Selector : IdpgTokenStreamSelector; + + protected // Internals + procedure initialize; override; + + protected // Public grammar rules ("rescoped") + procedure mSEMI ( pCreate: boolean); + procedure mJAVADOC_OPEN ( pCreate: boolean); + procedure mID ( pCreate: boolean); + procedure mWS ( pCreate: boolean); + + public + function NextToken: IdpgToken; override; + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedChar; + +// ============================================================================ +// mSEMI +// ============================================================================ +procedure TJavaLexer.mSEMI( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_SEMI; + + match(';'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mJAVADOC_OPEN +// ============================================================================ +procedure TJavaLexer.mJAVADOC_OPEN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_JAVADOC_OPEN; + + match('/**'); + Selector.Push('docLexer'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mID +// ============================================================================ +procedure TJavaLexer.mID( pCreate: boolean); +var + _begin: integer; + _cnt_5: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_ID; + + _cnt_5 := 0; + + while(true) do + begin + if (( LA(1) in ['a'..'z'])) then + begin + match( ['a'..'z']); + end + + else + begin + if _cnt_5 >= 1 then + break + else + Raise EdpgMismatchedChar.Create( LA(1), ['a'..'z'], FileName, Line, Column); + end; + + INC(_cnt_5); + end; + _ttype := testLit( _ttype); + + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ============================================================================ +// mWS +// ============================================================================ +procedure TJavaLexer.mWS( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IdpgToken; + _ttype: integer; + +begin + _begin := Length( fText) +1; + _token := nil; + _ttype := TT_WS; + + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else if (( LA(1) in [#9])) then + begin + match(#9); + end + + else if (( LA(1) in [#10,#13])) then + begin + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#10,#13], FileName, Line, Column); + newLine; + end + + else + Raise EdpgMismatchedChar.Create( LA(1), [#9..#10,#13,' '], FileName, Line, Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( fText, _begin, Length(fText)-_begin+1); + end; + + fReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function TJavaLexer.NextToken : IdpgToken; +var + _first : TdpgCharSet; + +begin + _first := [#9..#10,#13,' ','/',';','a'..'z']; + + while( true) do + begin + ResetText; + + try + if (( LA(1) in [';'])) then + begin + mSEMI(true); + result := fReturnToken; + end + + else if (( LA(1) in ['/'])) then + begin + mJAVADOC_OPEN(true); + result := fReturnToken; + end + + else if (( LA(1) in ['a'..'z'])) then + begin + mID(true); + result := fReturnToken; + end + + else if (( LA(1) in [#9..#10,#13,' '])) then + begin + mWS(true); + result := fReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TdpgToken.Create(TT_EOF); + end + + else + Raise EdpgMismatchedChar.Create(LA(1), _first, FileName, Line, Column); + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + Raise; + end; + end; +end; + +// ---------------------------------------------------------------------------- +// InitLiterals +// ---------------------------------------------------------------------------- +procedure TJavaLexer.initialize; +begin + fLiterals.Add('int', 10); +end; + +end. diff --git a/doc/tutorial/old/multiLexer/JavaTokens.pas b/doc/tutorial/old/multiLexer/JavaTokens.pas new file mode 100644 index 0000000..e4cef1e --- /dev/null +++ b/doc/tutorial/old/multiLexer/JavaTokens.pas @@ -0,0 +1,25 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javalexer.g +// ============================================================================ +unit JavaTokens; + +interface + +const + TT_EOF = 1; + TT_PARAM = 4; + TT_EXCEPTION = 5; + TT_ID = 6; + TT_STAR = 7; + TT_JAVADOC_CLOSE = 8; + TT_NEWLINE = 9; + LT_int = 10; + TT_SEMI = 11; + TT_JAVADOC_OPEN = 12; + TT_WS = 13; + +implementation +end. diff --git a/doc/tutorial/old/multiLexer/JavaTokens.txt b/doc/tutorial/old/multiLexer/JavaTokens.txt new file mode 100644 index 0000000..1965254 --- /dev/null +++ b/doc/tutorial/old/multiLexer/JavaTokens.txt @@ -0,0 +1,13 @@ +// $Delphi Parser Generator: JavaLexer.pas -> TJavaLexerTokens.txt$ +TJavaLexer +TT_EOF=1 +TT_PARAM=4 +TT_EXCEPTION=5 +TT_ID=6 +TT_STAR=7 +TT_JAVADOC_CLOSE=8 +TT_NEWLINE=9 +LT_int="int"=10 +TT_SEMI=11 +TT_JAVADOC_OPEN=12 +TT_WS=13 diff --git a/doc/tutorial/old/multiLexer/demo.dpr b/doc/tutorial/old/multiLexer/demo.dpr new file mode 100644 index 0000000..ac84a45 --- /dev/null +++ b/doc/tutorial/old/multiLexer/demo.dpr @@ -0,0 +1,49 @@ +program demo; + +{$APPTYPE CONSOLE} + +uses + Classes, + SysUtils, + dpgTokenStreamSelector, + javaLexer, + javaDocLexer, + javaParser; + +var + stm : TFileStream; + lexJava : TJavaLexer; + lexJavaDoc : TJavaDocLexer; + parJava : TJavaParser; + sel : TdpgTokenStreamSelector; + +begin + if ParamCount = 1 then + begin + try + stm := TFileStream.Create( ParamStr(1), fmOpenRead); + sel := TdpgTokenStreamSelector.Create; + + lexJava := TJavaLexer.Create( stm); + lexJavaDoc := TJavaDocLexer.Create( lexJava.InputState); + + lexJava.Selector := sel; + lexJavaDoc.Selector := sel; + + sel.add( lexJava, 'main'); + sel.add( lexJavaDoc, 'docLexer'); + sel.select( 'main'); + + parJava := TJavaParser.Create( sel); + + parJava.input; + except + writeln('Exception...'); + end; + end; + + + + + { TODO -oUser -cConsole Main : Insert code here } +end. diff --git a/doc/tutorial/old/multiLexer/javaDocLexer.g b/doc/tutorial/old/multiLexer/javaDocLexer.g new file mode 100644 index 0000000..1e5ddb7 --- /dev/null +++ b/doc/tutorial/old/multiLexer/javaDocLexer.g @@ -0,0 +1,76 @@ +unit JavaDocLexer; + +uses +{ + dpgTokenStreamSelector; +} + +lexer TJavaDocLexer; +options +{ + k = 2; + exportVocab = JavaDoc; + filter = true; +} + +memberdecl +{ + public + Selector : IdpgTokenStreamSelector; +} + +// ---------------------------------------------------------------------------- +// @param +// ---------------------------------------------------------------------------- +PARAM + : "@param" (' ')+ ID + ; + +// ---------------------------------------------------------------------------- +// @exception +// ---------------------------------------------------------------------------- +EXCEPTION + : "@exception" (' ')+ ID + ; + +// ---------------------------------------------------------------------------- +// identifier +// ---------------------------------------------------------------------------- +protected ID + : ('a'..'z')+ + ; + +// ---------------------------------------------------------------------------- +// Star +// +// This rule simply prevents JAVADOC_CLOSE from being called for every '*' in +// a comment. Calling JAVADOC_CLOSE will fail for simple '*' and cause an +// exception, which is slow. In other words, the grammar will work without +// this rule, but is slower. +// ---------------------------------------------------------------------------- +STAR + : '*' { _ttype := TT_SKIP; } + ; + +// ---------------------------------------------------------------------------- +// JavaDocClose +// ---------------------------------------------------------------------------- +JAVADOC_CLOSE + : "*/" { Selector.Pop; } + ; + +// ---------------------------------------------------------------------------- +// NewLine +// ---------------------------------------------------------------------------- +NEWLINE + : + ( + '\r' '\n' + | '\r' + | '\n' + ) + { + newLine; + _ttype := TT_SKIP; + } + ; \ No newline at end of file diff --git a/doc/tutorial/old/multiLexer/javaLexer.g b/doc/tutorial/old/multiLexer/javaLexer.g new file mode 100644 index 0000000..caff66b --- /dev/null +++ b/doc/tutorial/old/multiLexer/javaLexer.g @@ -0,0 +1,68 @@ +unit JavaLexer; + +uses +{ + dpgTokenStreamSelector; +} + +lexer TJavaLexer; +options +{ + k = 2; + importVocab = JavaDoc; + exportVocab = Java; +} + +tokens +{ + "int"; +} + +memberdecl +{ + public + Selector : IdpgTokenStreamSelector; +} + +// ---------------------------------------------------------------------------- +// Simple tokens +// ---------------------------------------------------------------------------- +SEMI : ';'; + +// ---------------------------------------------------------------------------- +// JavaDocOpen +// ---------------------------------------------------------------------------- +JAVADOC_OPEN + : "/**" { Selector.Push('docLexer'); } + ; + +// ---------------------------------------------------------------------------- +// Identifier +// ---------------------------------------------------------------------------- +ID +options +{ + testLiterals = true; +} + : ('a'..'z')+ + ; + +WS + : + ( + ' ' + | '\t' + | + ( + '\r' '\n' + | '\r' + | '\n' + ) + { + newLine; + } + ) + { + _ttype := TT_SKIP; + } + ; \ No newline at end of file diff --git a/doc/tutorial/old/multiLexer/javaParser.g b/doc/tutorial/old/multiLexer/javaParser.g new file mode 100644 index 0000000..f46b339 --- /dev/null +++ b/doc/tutorial/old/multiLexer/javaParser.g @@ -0,0 +1,20 @@ +unit javaParser; + +parser TJavaParser; +options +{ + k = 2; + importVocab = Java; +} + +input + : ( (javadoc)? "int" ID SEMI)+ + ; + +javadoc + : + JAVADOC_OPEN + (PARAM)? + (EXCEPTION)? + JAVADOC_CLOSE + ; \ No newline at end of file diff --git a/doc/tutorial/old/multiLexer/javaParser.pas b/doc/tutorial/old/multiLexer/javaParser.pas new file mode 100644 index 0000000..8754de0 --- /dev/null +++ b/doc/tutorial/old/multiLexer/javaParser.pas @@ -0,0 +1,91 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javaparser.g +// ============================================================================ +unit javaParser; + +interface + +uses + Classes, + Contnrs, + dpgLLkParser, + dpgToken, + dpgTypes, + javaParserTokens, + SysUtils; + +type + // ========================================================================= + // Class TJavaParser declaration + // ========================================================================= + TJavaParser = class( TdpgLLkParser) + + public // Public grammar rules + procedure input ; + procedure javadoc ; + + end; + +implementation +uses + dpgException, + dpgExceptionSemantic, + dpgExceptionMismatchedToken; + +// ============================================================================ +// input +// ============================================================================ +procedure TJavaParser.input; +var + _cnt_4: integer; + +begin + _cnt_4 := 0; + + while(true) do + begin + if (( LA(1) in [LT_int,TT_JAVADOC_OPEN])) then + begin + if (( LA(1) in [TT_JAVADOC_OPEN])) then + begin + javadoc; + end; + match(LT_int); + match(TT_ID); + match(TT_SEMI); + end + + else + begin + if _cnt_4 >= 1 then + break + else + Raise EdpgMismatchedToken.Create( LT(1), [LT_int,TT_JAVADOC_OPEN], FileName); + end; + + INC(_cnt_4); + end; +end; + +// ============================================================================ +// javadoc +// ============================================================================ +procedure TJavaParser.javadoc; +begin + + match(TT_JAVADOC_OPEN); + if (( LA(1) in [TT_PARAM])) then + begin + match(TT_PARAM); + end; + if (( LA(1) in [TT_EXCEPTION])) then + begin + match(TT_EXCEPTION); + end; + match(TT_JAVADOC_CLOSE); +end; + +end. diff --git a/doc/tutorial/old/multiLexer/javaParserTokens.pas b/doc/tutorial/old/multiLexer/javaParserTokens.pas new file mode 100644 index 0000000..86767a1 --- /dev/null +++ b/doc/tutorial/old/multiLexer/javaParserTokens.pas @@ -0,0 +1,25 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 1.0.0.118r +// Grammar: javaparser.g +// ============================================================================ +unit javaParserTokens; + +interface + +const + TT_EOF = 1; + TT_PARAM = 4; + TT_EXCEPTION = 5; + TT_ID = 6; + TT_STAR = 7; + TT_JAVADOC_CLOSE = 8; + TT_NEWLINE = 9; + LT_int = 10; + TT_SEMI = 11; + TT_JAVADOC_OPEN = 12; + TT_WS = 13; + +implementation +end. diff --git a/doc/tutorial/old/multiLexer/javaParserTokens.txt b/doc/tutorial/old/multiLexer/javaParserTokens.txt new file mode 100644 index 0000000..b11fbb9 --- /dev/null +++ b/doc/tutorial/old/multiLexer/javaParserTokens.txt @@ -0,0 +1,13 @@ +// $Delphi Parser Generator: javaParser.pas -> TJavaParserTokens.txt$ +TJavaParser +TT_EOF=1 +TT_PARAM=4 +TT_EXCEPTION=5 +TT_ID=6 +TT_STAR=7 +TT_JAVADOC_CLOSE=8 +TT_NEWLINE=9 +LT_int="int"=10 +TT_SEMI=11 +TT_JAVADOC_OPEN=12 +TT_WS=13 diff --git a/doc/tutorial/old/multiLexer/test.in b/doc/tutorial/old/multiLexer/test.in new file mode 100644 index 0000000..b50f9fd --- /dev/null +++ b/doc/tutorial/old/multiLexer/test.in @@ -0,0 +1,20 @@ +/** a javadoc comment + * @param foo + * @exception bar + * Just a little text for a comment + */ +int abc; + +/** a javadoc comment + * @param foo + * @exception bar + * Just a little text for a comment + */ +int zzz; + +/** a javadoc comment + * @param foo + * @exception bar + * Just a little text for a comment + */ +int xxx; diff --git a/doc/usersguide/dpg.pdf b/doc/usersguide/dpg.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a99635814d26b0dc53d01a8ad27c0f0d7fdeef84 GIT binary patch literal 108056 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

a%-X~NIawZuc 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 ZS8+*VQ3-f_4>a^=YQUwc>gw;t1prJWf$9JN literal 0 HcmV?d00001 diff --git a/doc/usersguide/dpg.tex b/doc/usersguide/dpg.tex new file mode 100644 index 0000000..7d8851d --- /dev/null +++ b/doc/usersguide/dpg.tex @@ -0,0 +1,36 @@ +\documentclass{zlbook} +\usepackage{minitoc} +%\usepackage[toc,page]{appendix} +%\usepackage{mtcoff} +\title{Delphi Parser Generator \\ user's guide} +\begin{document} +\dominitoc +\dominilof +\dominilot + +\pagestyle{empty} +\renewcommand{\thepage}{\roman{page}} +\maketitle + +\tableofcontents +%\listoftables +\renewcommand{\thepage}{\thechapter\ - \arabic{page}} +\clearpage +\pagestyle{fancy} + +\input{src/intro/intro} +\input{src/start/start} +\input{src/lang/lang} +\input{src/gram/gram} +\input{src/tokens/tokens} +\input{src/rt/rt} + + +\appendix +\renewcommand{\thepage}{\Alph{chapter} - \arabic{page}} + +%\begin{appendices} +\input{src/app/app-grammar} +%\end{appendices} + +\end{document} diff --git a/doc/usersguide/src/app/app-grammar.tex b/doc/usersguide/src/app/app-grammar.tex new file mode 100644 index 0000000..b811332 --- /dev/null +++ b/doc/usersguide/src/app/app-grammar.tex @@ -0,0 +1,625 @@ +\chapter{Grammar of Delphi Parser Generator} + +\clearpage \section{Lexical analyzer} +\begin{verbatim} +unit dpgDpgLexer; + +lexer TdpgDpgLexer; +options +{ + testLiterals = false; + k = 2; +} + +tokens +{ + "unit"; + "uses"; + "const"; + "type"; + + "lexer"; + "parser"; + + "options"; + "tokens"; + "memberdecl"; + "memberdef"; + + "private"; + "protected"; + "public"; + + "returns"; + "local"; + + "except"; + "finally"; + + SEMPRED; + + USES; + OPTIONS; + TOKENS; +} + +// -------------------------------------------------------- +// Simple tokens +// -------------------------------------------------------- +LPAREN: '('; +RPAREN: ')'; +RCURLY: '}'; +COLON: ':'; +SEMI: ';'; +COMMA: ','; +ASSIGN: '='; +IMPLIES: "=>"; +QUEST: '?'; +PLUS: '+'; +STAR: '*'; +NOT: '~'; +OR: '|'; +BANG: '!'; +WILDCARD: '.'; +RANGE: ".."; + +// -------------------------------------------------------- +// Character literal +// -------------------------------------------------------- +CHARLIT + : '\''! (ESC | ~'\'') '\''! ; + +// -------------------------------------------------------- +// String literal +// -------------------------------------------------------- +STRINGLIT + : '"' (ESC | ~'"')* '"' ; + +// -------------------------------------------------------- +// Integer +// -------------------------------------------------------- +INTEGER local +{ + i: integer; + v: integer; +} + : DNUMBER + { + v := 0; + for i:=1 to Length( TokenText) do + begin + v := v * 10 + ord( TokenText[i]) - ord('0'); + end; + + TokenText := IntToStr( v); + } + ; + + + + +// -------------------------------------------------------- +// Argument action +// -------------------------------------------------------- +ARGACTION + : + '['! + ( + '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | ~']' + )* + ']'! + ; + +// -------------------------------------------------------- +// Action +// -------------------------------------------------------- +ACTION + : + '{' + ( + '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | ~'}' + )* + '}' + ( '?'! { _ttype := TT_SEMPRED; } )? + ; + +// -------------------------------------------------------- +// Token ref +// -------------------------------------------------------- +TOKENREF +options +{ + testLiterals = true; +} + : 'A'..'Z' ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')* ; + +// -------------------------------------------------------- +// Rule ref +// -------------------------------------------------------- +RULEREF +local +{ + t: integer; +} + : + t = INT_RULEREF { _ttype := t; } + ( + {t = LT_uses}? WS_LOOP ('{' { _ttype := TT_USES; } )? + | {t = LT_options}? WS_LOOP ('{' { _ttype := TT_OPTIONS; } )? + | {t = LT_tokens}? WS_LOOP ('{' { _ttype := TT_TOKENS; } )? + )? + ; + +// -------------------------------------------------------- +// Internal rule ref +// -------------------------------------------------------- +protected INT_RULEREF returns [integer] +{ + _ttype := TT_RULEREF; +} + : 'a'..'z' ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')* + { + result := TestLiteral( _ttype); + } + ; + +// -------------------------------------------------------- +// COMMENT +// -------------------------------------------------------- +COMMENT + : SLCOMMENT { _ttype := TT_SKIP; } + | MLCOMMENT { _ttype := TT_SKIP; } + ; + +// -------------------------------------------------------- +// SLCOMMENT +// -------------------------------------------------------- +protected SLCOMMENT + : + "//" + ( ~( '\r' | '\n') )* + ( + '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + ) + ; + + + + + + +// -------------------------------------------------------- +// Multi line comment version +// Nested comments aren't allowed! +// -------------------------------------------------------- +protected MLCOMMENT + : + "(*" + ( + options + { + greedy = false; + } + : '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + | . + )* + "*)" + ; + +// -------------------------------------------------------- +// Numbers +// -------------------------------------------------------- +protected DNUMBER: '0'..'9' (DDIGIT)*; +protected DDIGIT: '0'..'9'; + +// -------------------------------------------------------- +// WS +// -------------------------------------------------------- +WS + : + ( + ' ' + | '\t' { tab; } + | '\r' '\n' { newLine; } + | '\r' { newLine; } + | '\n' { newLine; } + ) + { + _ttype := TT_SKIP; + } + ; + + + + + + + +// -------------------------------------------------------- +// WS_LOOP +// -------------------------------------------------------- +protected +WS_LOOP + : + ( + options + { + greedy = true; + } + : WS + | COMMENT + )* + ; + +// -------------------------------------------------------- +// Esc +// -------------------------------------------------------- +protected +ESC + : '\\'! ( 'r' | 'n' | 't' | '\'' | '"' ) + ; + +\end{verbatim} + + +\clearpage \section{Parser} +\begin{verbatim} +unit dpgDpgParser; + +parser TdpgDpgParser; +options +{ + defaultErrorHandler = false; + importVocab = dpgDpgLexer; + k = 2; +} + +// -------------------------------------------------------- +// grammar +// -------------------------------------------------------- +grammar + : "unit" id SEMI + (usesDecl)? + (constDecl)? + (typeDecl)? + classDecl + ; + +// -------------------------------------------------------- +// usesDecl +// -------------------------------------------------------- +usesDecl + : USES + ( + TOKENREF SEMI + | RULEREF SEMI + )* + + RCURLY + ; + +// -------------------------------------------------------- +// constDecl +// -------------------------------------------------------- +constDecl + : "const" ACTION + ; + +// -------------------------------------------------------- +// typeDecl +// -------------------------------------------------------- +typeDecl + : "type" ACTION + ; + +// -------------------------------------------------------- +// classDecl +// -------------------------------------------------------- +classDecl +local +{ + grType: integer; +} + : + // -------------------------------------------------- + // Determine parser type + // -------------------------------------------------- + ( "lexer" { grType := 0; } + | "parser" { grType := 1; } + ) + + // -------------------------------------------------- + // get class name + // -------------------------------------------------- + id + SEMI + + // -------------------------------------------------- + // Process optional class "options {...}" clause + // -------------------------------------------------- + (classOptions)? + + // -------------------------------------------------- + // Process optional class "tokens {...}" clause + // But only for lexers. + // -------------------------------------------------- + ( {grType=0}? classTokens)? + + // -------------------------------------------------- + // Process optional class "memberDecl {...}" clause + // -------------------------------------------------- + (classMemberDecl)? + + // -------------------------------------------------- + // Well, the rules + // -------------------------------------------------- + rules + + // -------------------------------------------------- + // Process optional class "memberDecl {...}" clause + // -------------------------------------------------- + (classMemberDef)? + ; +// -------------------------------------------------------- +// classOptions +// -------------------------------------------------------- +classOptions + : OPTIONS ( id ASSIGN optionValue SEMI )* RCURLY + ; + +// -------------------------------------------------------- +// classTokens +// -------------------------------------------------------- +classTokens + : + TOKENS + ( + TOKENREF SEMI + | STRINGLIT SEMI + )* + + RCURLY + ; + +// -------------------------------------------------------- +// classMemberDecl +// -------------------------------------------------------- +classMemberDecl + : "memberDecl" ACTION + ; + +// -------------------------------------------------------- +// classMemberDef +// -------------------------------------------------------- +classMemberDef + : "memberDef" ACTION + ; + +// -------------------------------------------------------- +// rules +// -------------------------------------------------------- +rules + : (rule)* + ; + +// -------------------------------------------------------- +// ruleExceptionBlock +// -------------------------------------------------------- +ruleExceptionBlock + : "except" ACTION + | "finally" ACTION + ; +// -------------------------------------------------------- +// altExceptionBlock +// -------------------------------------------------------- +altExceptionBlock + : "except" ACTION + | "finally" ACTION + ; + +// -------------------------------------------------------- +// rule +// -------------------------------------------------------- +rule + : + // -------------------------------------------------- + // Parse rule scope + // -------------------------------------------------- + ( "public" + | "protected" + | "private" + )? + + // -------------------------------------------------- + // Parse rule name + // -------------------------------------------------- + id + + // -------------------------------------------------- + // Optional arguments + // -------------------------------------------------- + (ARGACTION)? + + // -------------------------------------------------- + // Optional return type + // -------------------------------------------------- + ("returns" ARGACTION)? + + // -------------------------------------------------- + // Optional rule options + // -------------------------------------------------- + (ruleOptions)? + + // -------------------------------------------------- + // Optional rule local variable declarations + // -------------------------------------------------- + ("local" ACTION)? + + // -------------------------------------------------- + // Optional rule init action + // -------------------------------------------------- + (ACTION)? + + // -------------------------------------------------- + // Rule block + // -------------------------------------------------- + COLON + block + SEMI + + // -------------------------------------------------- + // Optional exception handler + // -------------------------------------------------- + (ruleExceptionBlock)? + ; + +// -------------------------------------------------------- +// block +// -------------------------------------------------------- +block + : alternative (OR alternative)* + ; + +// -------------------------------------------------------- +// alternative +// -------------------------------------------------------- +alternative + : (elem)* + (altExceptionBlock)? + ; + +// -------------------------------------------------------- +// elem +// -------------------------------------------------------- +elem + : element + ; + +// -------------------------------------------------------- +// element +// -------------------------------------------------------- +element +local +{ + assignLabel : IdpgToken; +} +{ + assignLabel := nil; +} + : + ( + id ASSIGN + (id COLON)? + ( + RULEREF (ARGACTION)? (BANG)? + | TOKENREF (ARGACTION)? + ) + ) + | + (assignLabel=id COLON)? + ( + RULEREF (ARGACTION)? (BANG)? + | range[assignLabel] + | terminal[assignLabel] + | NOT (notTerminal[assignLabel] | ebnf[ assignLabel, true]) + | ebnf[ assignLabel, false] + ) + | ACTION + | SEMPRED + ; + +// -------------------------------------------------------- +// range +// -------------------------------------------------------- +range [pTokenLabel: IdpgToken] +local + : + CHARLIT RANGE CHARLIT + | (TOKENREF | STRINGLIT) RANGE (TOKENREF | STRINGLIT) + ; +// -------------------------------------------------------- +// terminal +// -------------------------------------------------------- +terminal [pTokenLabel: IdpgToken] + : + CHARLIT (BANG)? + | TOKENREF (BANG)? (ARGACTION)? + | STRINGLIT (BANG)? + | WILDCARD (BANG)? + ; + +// -------------------------------------------------------- +// notTerminal +// -------------------------------------------------------- +notTerminal [pTokenLabel: IdpgToken] + : CHARLIT (BANG)? + | TOKENREF (BANG)? + ; + +// -------------------------------------------------------- +// ebnf +// -------------------------------------------------------- +ebnf [pTokenLabel: IdpgToken; pTokenNot: boolean] + : LPAREN + ( + subRuleOptions (ACTION)? COLON + | ACTION COLON + )? + + block + RPAREN + ( QUEST + | STAR + | PLUS + | IMPLIES + )? + ; + +// -------------------------------------------------------- +// subruleOptions +// -------------------------------------------------------- +subruleOptions + : OPTIONS (id ASSIGN optionValue)* SEMI RCURLY + ; + +// -------------------------------------------------------- +// ruleOptions +// -------------------------------------------------------- +ruleOptions + : OPTIONS (id ASSIGN optionValue)* SEMI RCURLY + ; + +// -------------------------------------------------------- +// optionValue +// -------------------------------------------------------- +optionValue returns [IdpgToken] + : result=qualifiedId + | result:STRINGLIT + | result:CHARLIT + | result:INTEGER + ; + +// -------------------------------------------------------- +// qualifiedId +// -------------------------------------------------------- +qualifiedId returns [IdpgToken] + : id (WILDCARD id)* + ; +// -------------------------------------------------------- +// id +// -------------------------------------------------------- +id returns [IdpgToken] + : result:TOKENREF + | result:RULEREF + ; +\end{verbatim} diff --git a/doc/usersguide/src/error/error-err.tex b/doc/usersguide/src/error/error-err.tex new file mode 100644 index 0000000..a504158 --- /dev/null +++ b/doc/usersguide/src/error/error-err.tex @@ -0,0 +1,77 @@ +\section{Error handling} + +All syntactic and semantic errors cause parser exceptions to be thrown. In +particular, the methods used to match tokens in the parser base class (match et +al) throw §EdpgMismatchedToken§. The methods in the lexer base class used to +match characters (match et al) throw analogous exceptions. + +\subsection{DPG exception hierarchy} + +DPG-generated parsers throw exceptions to signal recognition errors or other +stream problems. All exceptions derive from EdpgException. The hierarchy is the +following: + +\begin{verbatim} + EdpgException + EdpgMismatchedChar + EdpgMismatchedToken + EdpgSemantic +\end{verbatim} + +\subsubsection{EdpgException} The EdpgException exception class is the base of +all DPG generated exceptions. User defined exceptions must derive from this +class. + +\subsubsection{EdpgMismatchedChar} This exception is thrown by the lexer when it +is looking for a character, but finds a different one on the input stream. + +\subsubsection{EdpgMismatchedToken} This exception is thrown by the parser when +it is looking for a token, but finds a different one on the input token stream. + +\subsubsection{EdpgSemantic} This exception is thrown by a validating semantic +predicate. + +\subsection{Specifying exception handlers} + +DPG allows to specify specific exception handler to a given rule or +alternative. The general form of an exception handler specification is: + +\begin{verbatim} + ... except { code to handle exception } + ... finally { code to handle exception } +\end{verbatim} + +\subsubsection{Exception handler for a rule} + +The exception handler for a rule must be placed after the terminating +semicolon. The handler can be either an §except§ block or a §finally§ block. +The implementation of rule will be surrounded by a try block. + +\begin{verbatim} + r : ... + ; + except { handler code } +\end{verbatim} + +\subsubsection{Exception handler for an alternative} + +The exception handler of an alternative must be the last element of the +alternative. Both exception handler blocks can be used. Every alternative that +have exception block specified, will be surrounded by a §try...except/finally§ +block. + +\begin{verbatim} + r : alternative_1 ... except { handler code } + | alternative_2 ... finally { handler code } + ... + | alternative_n + ; +\end{verbatim} + +\paragraph{Note:} It is not necessary to define exception handler for each alternative. + +\subsubsection{Default error handler in lexer} + +To skip every character that isn't recognized by any public lexer rule, specify +§filter=true§ option for a lexer. That way, the parser doesn't have to deal +with lexical errors and ask for another token. diff --git a/doc/usersguide/src/error/error.tex b/doc/usersguide/src/error/error.tex new file mode 100644 index 0000000..e69de29 diff --git a/doc/usersguide/src/gram/gram.tex b/doc/usersguide/src/gram/gram.tex new file mode 100644 index 0000000..ad2571c --- /dev/null +++ b/doc/usersguide/src/gram/gram.tex @@ -0,0 +1,53 @@ +\chapter{Grammars} +\minitoc \clearpage + +\section{Structure of a grammar} + +The generic structure of a DPG grammar is the following: +\begin{itemize} + \item \emph{unit declaration} + \item \emph{unit sections} + \item \emph{grammar class definition} + \item \emph{grammar class sections} +\end{itemize} +\paragraph{Note:} the order of blocks cannot be changed! + +\subsection{Unit declaration} +The $unit$~$declaration$ is always the first block in any DPG grammar. It +specifies the name of the target Pascal unit generated by DPG from the +grammar. The syntax is identical to that of Delphi. +\begin{alltt} + \textbf{unit} \emph{UnitName} ; +\end{alltt} + +\subsection{Unit sections} +The $unit$~$sections$ block must follow the $unit$~$declaration$ +block if it exists. The members of this block are optional, but +they must appear in the following order: +\begin{itemize} + \item \emph{uses section} + \item \emph{const section} + \item \emph{type section} +\end{itemize} + +\subsection{Grammar class definition} +This block defines the type of the grammar class. The possible types are +§lexer§ and §parser§. +\begin{alltt} + \textbf{lexer} \emph{myLexer} ; // define lexer +\end{alltt} +or +\begin{alltt} + \textbf{parser} \emph{myParser} ; // define parser +\end{alltt} + +\subsection{Grammar class sections} +This block may contain the following sections in the order +specified: +\begin{itemize} + \item \emph{options section} + \item \emph{tokens section} (only for lexers) + \item \emph{memberdecl section} + \item \emph{rule definitions} + \item \emph{memberdef section} +\end{itemize} diff --git a/doc/usersguide/src/intro/intro.tex b/doc/usersguide/src/intro/intro.tex new file mode 100644 index 0000000..ca872ed --- /dev/null +++ b/doc/usersguide/src/intro/intro.tex @@ -0,0 +1,63 @@ +\chapter{Introduction} +\minitoc \clearpage + +\section{Overview} +The Delphi Parser Generator is a language tool which automatically +generates $LL(k)$ parsers in Object Pascal Language based on an +intuitive grammar, similar to §EBNF§. The generated code mimics a +hand-written parser, so that it is easier to debug and leads to +shortened development time compared to state-machine based $LR$ or +DFA/NFA parsers. To compensate theoretical limitations of $LL(k)$ +parsers, DPG features several powerful extensions enhancing its +functionality far beyond that of standard $LL(k)$ parsers. The +method of syntactic and semantic predicates makes the writing of +meta-parsers simple and routine. The philosophy of DPG is to allow +the programmer maximum control over the parsing process while +eliminating all the routine work. + +\section{Features} +\begin{itemize} + \item[-] Delphi code generator for $LL(k)$ lexers and parsers. + \item[-] Intuitive and consistent EBNF like syntax for both the lexer and the parser generator + resulting in a shallow learning curve. + \item[-] Extremely easy-to-read generated code undistinguishable from hand-written + parsers. The inlined statements are properly indented relative to the surrounding + program code. + \item[-] Syntactic predicates allow for conditional parsing based on + formal syntactic conditions, enhancing the functionality of the $LL(k)$ parsers + considerably. + \item[-] Semantic predicates allow for conditional parsing based on + essentially arbitrary conditions. For example, a DOM-based XML parser is easily + written by semantic predicates using an internal hash-table representation of + the DOM. Using traditional state-machine based parsers (like §YACC§), programmers + often need to delegate parsing tasks to the hand written part of the code. This + burdens them with laborious and error-prone routine work. Semantic predicates + prevent this, since the parser is allowed to use run-time information for the + parsing process dynamically. + \item[-] Actions can be inserted in the rules at every possible place. These actions can be + used for controlling the parsing process with high granularity. + \item[-] All rules may have return values and arguments. Rule arguments add a powerful + metaparsing capability completing the predicate and action mechanism optimally. + \item[-] All rules may have a code initialization section. This special feature is tuned + for Pascal to allow the programmer to declare and initialize local variables for each rule. + \item[-] Many convenient extensions to the plain §BNF§ syntax, such as §(...)§, §(...)?§, + §(...)+§, §(...)*§, which simplify the task of writing grammars and makes it less + error-prone. + \item[-] Element complements allow for matching a text not matching a given rule. + \item[-] Element labels are used to directly map rule information + to Pascal variables. They provide a seamless interaction between the + generated and user-written code. + \item[-] Intuitive Graphical User Interface with syntax highlighting, and + project management capabilities. +\end{itemize} + +\section{Installation} +The first step in using DPG is to install it in Delphi. However, before using +DPG be sure to read over the License Agreement. +\begin{itemize} + \item[-] run setup.exe and follow the instructions + \item[-] run Delphi and add your DPG run-time library directory to Delphi's + library path. For example, to do this for Delphi 6 select \emph{Tools} §|§ \emph{Environment Options} + on the menu bar. Go to the \emph{Library} tab and add the full path of your DPG run-time directory + to the \emph{Library Path} if you have not already done so. +\end{itemize} diff --git a/doc/usersguide/src/lang/lang-atomprod.tex b/doc/usersguide/src/lang/lang-atomprod.tex new file mode 100644 index 0000000..1e19091 --- /dev/null +++ b/doc/usersguide/src/lang/lang-atomprod.tex @@ -0,0 +1,40 @@ +\section{Atomic production elements} +\subsection{Character literal} +Single characters enclosed in quotes are character literals. A +character literal can only be referred to within a lexer rule. For +example, §'{'§ needs not be escaped as you are specifying the +literal character which is to be matched. Meta symbols are used +outside of characters and string literals to specify lexical +structure. Special characters can be specified in a similar way to +§C§ escape sequences. DPG accepts the following escape sequences: +§\n§, §\r§, §\t§, §\'§, §\"§, §\\§. The §#xx§ form is not accepted +by DPG. + +\subsection{String literal} +String literals are sequences of characters enclosed in double quotes. The same +escape sequences can be used in string literals as in character literals. +In parser rules, strings represent tokens, and each unique string is assigned +to a token type. Referring to a string within a lexer rule matches the +indicated sequence of characters and is a shorthand notation. For example, +consider the following equivalent lexer rule definitions: +\begin{verbatim} + BEGIN : "begin"; + BEGIN : 'b' 'e' 'g' 'i' 'n'; +\end{verbatim} + +\subsection{Wildcard} +The wildcard §.§ within a parser rule matches any single token; +within a lexer rule it matches any single character. + +\subsection{Token reference} +Identifiers beginning with an uppercase letter are treated as +token references. The subsequent characters may be a mixture of +letters, digits or underscores. Referencing a token in a parser +rule implies that you want to recognize a token with the specified +token type. This does not actually call the associated lexer rule +-- the lexical analysis phase delivers a stream of tokens to the +parser. A token reference within a lexer rule implies a method +call to that rule, and carries the same analysis semantics as a +rule reference within a parser. So, you may specify rule arguments +and return values for non-public tokens and for every parser rule. +See the next section on rule references. diff --git a/doc/usersguide/src/lang/lang-err.tex b/doc/usersguide/src/lang/lang-err.tex new file mode 100644 index 0000000..a504158 --- /dev/null +++ b/doc/usersguide/src/lang/lang-err.tex @@ -0,0 +1,77 @@ +\section{Error handling} + +All syntactic and semantic errors cause parser exceptions to be thrown. In +particular, the methods used to match tokens in the parser base class (match et +al) throw §EdpgMismatchedToken§. The methods in the lexer base class used to +match characters (match et al) throw analogous exceptions. + +\subsection{DPG exception hierarchy} + +DPG-generated parsers throw exceptions to signal recognition errors or other +stream problems. All exceptions derive from EdpgException. The hierarchy is the +following: + +\begin{verbatim} + EdpgException + EdpgMismatchedChar + EdpgMismatchedToken + EdpgSemantic +\end{verbatim} + +\subsubsection{EdpgException} The EdpgException exception class is the base of +all DPG generated exceptions. User defined exceptions must derive from this +class. + +\subsubsection{EdpgMismatchedChar} This exception is thrown by the lexer when it +is looking for a character, but finds a different one on the input stream. + +\subsubsection{EdpgMismatchedToken} This exception is thrown by the parser when +it is looking for a token, but finds a different one on the input token stream. + +\subsubsection{EdpgSemantic} This exception is thrown by a validating semantic +predicate. + +\subsection{Specifying exception handlers} + +DPG allows to specify specific exception handler to a given rule or +alternative. The general form of an exception handler specification is: + +\begin{verbatim} + ... except { code to handle exception } + ... finally { code to handle exception } +\end{verbatim} + +\subsubsection{Exception handler for a rule} + +The exception handler for a rule must be placed after the terminating +semicolon. The handler can be either an §except§ block or a §finally§ block. +The implementation of rule will be surrounded by a try block. + +\begin{verbatim} + r : ... + ; + except { handler code } +\end{verbatim} + +\subsubsection{Exception handler for an alternative} + +The exception handler of an alternative must be the last element of the +alternative. Both exception handler blocks can be used. Every alternative that +have exception block specified, will be surrounded by a §try...except/finally§ +block. + +\begin{verbatim} + r : alternative_1 ... except { handler code } + | alternative_2 ... finally { handler code } + ... + | alternative_n + ; +\end{verbatim} + +\paragraph{Note:} It is not necessary to define exception handler for each alternative. + +\subsubsection{Default error handler in lexer} + +To skip every character that isn't recognized by any public lexer rule, specify +§filter=true§ option for a lexer. That way, the parser doesn't have to deal +with lexical errors and ask for another token. diff --git a/doc/usersguide/src/lang/lang-opt.tex b/doc/usersguide/src/lang/lang-opt.tex new file mode 100644 index 0000000..467940a --- /dev/null +++ b/doc/usersguide/src/lang/lang-opt.tex @@ -0,0 +1,265 @@ +\section{Options} + +The §options{...}§ section is used to specify options for grammar +elements. i.e. elements are the lexer/parser classes, rules and +subrules. This section is preceded by the options keyword and +contains a series of option/value assignments surrounded by curly +braces. + +\subsection{k} +\begin{table}[H] + \small + \begin{tabular}{rl} + \emph{synopsis:} & set lookahead depth \\ + \emph{context:} & parser/lexer class declaration \\ + \emph{type:} & integer \\ + \emph{default:} & 1 + \end{tabular} +\end{table} + +For any grammar, the lookahead depth can be specified by using the $k$ option. + +\begin{verbatim} + lexer myLexer; + options + { + k = 2; + } +\end{verbatim} + +Setting the lookahead depth changes the maximum number of tokens that will be +examined to select alternative productions, and test for exit conditions of the +§EBNF§ constructs §(...)?§, §(...)+§, and §(...)*§. The lookahead analysis is +linear approximate (as opposed to full $LL(k)$ ). Consider this example with +$k=2$: +\begin{verbatim} + r : ( A B | B A ) + | A A + ; +\end{verbatim} + +Full $LL(k)$ analysis would resolve the ambiguity and produce a +lookahead test for the first alternative like: +\begin{verbatim} + if (LA(1)=A and LA(2)=B) or (LA(1)=B and LA(2)=A) +\end{verbatim} + +Linear approximate analysis would logically OR the lookahead sets at each +depth, resulting in a test like: + +\begin{verbatim} + if (LA(1)=A or LA(1)=B) and (LA(2)=A or LA(2)=B) +\end{verbatim} + +Which is ambiguous for the second alternative for §{A,A}§. +Therefore, setting the lookahead depth very high tends to yield +diminishing returns in most cases, because the lookahead sets at +large depths will include almost everything. This problem can be +solved using a syntactic predicate. + + +\subsection{importVocab} +\begin{table}[H] + \small + \begin{tabular}{rl} + \emph{synopsis:} & set initial grammar vocabulary \\ + \emph{context:} & parser/lexer class declaration \\ + \emph{type:} & ID \\ + \emph{default:} & none + \end{tabular} +\end{table} + +The import vocabulary for a grammar class can be specified using the +§importVocab§ option. + +\begin{verbatim} + lexer myLexer; + options + { + importVocab = XML; + } +\end{verbatim} + +DPG will look for the token exchange file named §XMLTokens.txt§, +and import all the token definitions from it. Parser grammar must +use this option, because without that, it cannot communicate with +the lexer. Lexer grammar can use this option too. It is useful, +when a parser class uses multiple lexers to get tokens from the +input stream. The vocabulary file has an identifier on the first +line that names the token vocabulary. All subsequent lines are of +the form §ID=value§ or §ID="literal"=value§. For example: + +\begin{verbatim} + ThocLexer + TT_EOF = 1 + TT_LPAREN = 4 + TT_RPAREN = 5 + LT_const = "const" = 6 +\end{verbatim} + +The token exchange file is automatically generated by DPG for each grammar. +\paragraph{Note:} you must take care of the order of grammars in a DPG project. +Vocabulary-generating grammars must appear before vocabulary-consuming +grammars. + +\subsection{exportVocab} +\begin{table}[H] + \small + \begin{tabular}{rl} + \emph{synopsis:} & set export grammar vocabulary \\ + \emph{context:} & parser/lexer class declaration \\ + \emph{type:} & ID \\ + \emph{default:} & grammar class name + \end{tabular} +\end{table} + +The vocabulary of a grammar is the union of the set of tokens provided by an +§importVocab§ option and the set of tokens and literals defined in the grammar. + +\begin{verbatim} + lexer myParser; + options + { + exportVocab = XML1; + } +\end{verbatim} + +If the exportVocab options isn't specified, then DPG will use the +grammar class name to export the vocabulary. DPG generates the +following files for the examp\-le above: §XML1Tokens.txt§ for +token exchange, and XML1Tokens.pas for the grammar class. + +\subsection{testLiterals} +\begin{table}[H] + \small + \begin{tabular}{rl} + \emph{context:} & lexer class declaration, lexer rule \\ + \emph{type:} & boolean \\ + \emph{default:} & false + \end{tabular} +\end{table} + +By default, DPG doesn't generate code to check the literals table +(the table generated for literal strings), because checking the +literals table after each token recognition is expensive. Instead, +it checks string literals in a lexer rule, that can recognize +them. The string literals table contains the strings defined in +the §tokens{...}§ section of a lexer grammar. +\begin{verbatim} + lexer myLexer; + options + { + testLiterals = false; + } + tokens + { + "function"; + "procedure"; + ... + } + + ID + options + { + testLiterals = true; + } + : (‘A’..’Z’ | ‘a’..’z’)(‘A’..’Z’ | ‘a’..’z’ | ‘0’..‘9’)* + ; +\end{verbatim} + +In the example above, if the input is matched by the rule §ID§ +then the implementation of the rule will check the literals table +for the matched token. If it exists, then the returned token type +will be set to the token type assigned to the string literal in +the literals table. Otherwise the returned token type will remain +unchanged. + +It is possible to check the literals table explicitly within an +action using the Test\-Li\-te\-ral method: + +\begin{verbatim} + { + ... + _ttype := TestLiteral; + _ttype := TestLiteral( _ttype); + ... + } +\end{verbatim} + +\subsection{caseSensitive} +\begin{table}[H] + \small + \begin{tabular}{rl} + \emph{context:} & lexer class declaration \\ + \emph{type:} & boolean \\ + \emph{default:} & false + \end{tabular} +\end{table} + +\begin{verbatim} + lexer myLexer; + options + { + caseSensitive = true; + } +\end{verbatim} + +Case is ignored when comparing against character and string literals in the +lexer. The case of the input stream is maintained when stored in the token +objects. + +\subsection{filter} +\begin{table}[H] + \small + \begin{tabular}{rl} + \emph{context:} & lexer class declaration \\ + \emph{type:} & boolean / ID \\ + \emph{default:} & false + \end{tabular} +\end{table} + +\begin{verbatim} + lexer myLexer; + options + { + filter = true; + } +\end{verbatim} + +When §true§, the lexer ignores any input not exactly matching one of the public +lexer rules. + +Notice that the filter rule must track new-lines in the general +case where the lexer might emit error messages. + +When set to a rule name, the filter rule is invoked either when the lookahead +(in nextToken) predicts none of the public lexical rules or when one of those +rules fails. In the latter case, the input is rolled back before attempting +the filter rule. Option §filter=true§ is like having a filter rule such as: + +\begin{verbatim} + IGNORE : . ; +\end{verbatim} + +\subsection{ignore} +\begin{table}[H] + \small + \begin{tabular}{rl} + \emph{context:} & lexer rule \\ + \emph{type:} & ID \\ + \emph{default:} & none + \end{tabular} +\end{table} + +\begin{verbatim} + lexer myLexer; + options + { + ignore = MyIgnoreRule; + } +\end{verbatim} + +Specify a lexer rule to use a white space between lexical rule +atomic elements (chars, strings, and rule references). The grammar +analysis, and hence the look\-ahead sets, are aware of the +whitespace references. diff --git a/doc/usersguide/src/lang/lang-prodoper.tex b/doc/usersguide/src/lang/lang-prodoper.tex new file mode 100644 index 0000000..9ee2bba --- /dev/null +++ b/doc/usersguide/src/lang/lang-prodoper.tex @@ -0,0 +1,41 @@ +\section{Production element operators} + +\subsection{Element complement} +The unary not operator $\sim$ may be applied to an atomic element +such as a token identifier. For some token atom §T§, $\sim$§T§ +matches any token other than §T§ except end-of-file. Within lexer +rules, $\sim$§'a'§ matches any character other than character +§'a'§. The sequence $\sim$§.§ (``not anything'') is meaningless +and not allowed. Example: +\begin{verbatim} + SL_COMMENT : "//" (~'\n')* '\n'; +\end{verbatim} + +\subsection{Set complement} +The unary not operator $\sim$ can also be used to construct a +token set or character set by complementing another set. This is +most useful when you want to match tokens or characters until a +certain delimiter set is encountered. Rather than invent a special +syntax for such sets, DPG allows the placement of $\sim$ in front +of a subrule containing only simple elements and no actions. The +simple elements may be token references, token ranges, character +literals, or character ranges. For example: +\begin{verbatim} + SL_COMMENT : "//" (~('\r'|'\n'))* ('\r'|'\n'); +\end{verbatim} + +\subsection{Range operator} +The binary range operator §..§ is used to define a range of atom +which may be matched. The expression §c1..c2§ in a lexer matches +characters included in that range. The expression §T..U§ in a +parser matches any token whose token type is inclusively in that +range, which is of dubious value if the token types are generated +externally. + +\subsection{Ignore operator} +In lexer grammars, the ignore operator §!§ can be applied to any +atomic production element. It means that the element followed by +the §!§ operator should not appear in the result token. Example: +\begin{verbatim} + STRING : '"'! (~'"')* '"'! ; +\end{verbatim} diff --git a/doc/usersguide/src/lang/lang-rest.tex b/doc/usersguide/src/lang/lang-rest.tex new file mode 100644 index 0000000..ca509fd --- /dev/null +++ b/doc/usersguide/src/lang/lang-rest.tex @@ -0,0 +1,82 @@ +\section{Element labels} + +Any atomic production element can be labeled by an identifier (case is insignificant). +For a labelled atomic element, the identifier is used within a semantic action to access +the associated Token object or character. For example, + +\begin{verbatim} + assign + : v:ID EQUALS expr SEMI + { + writeln(‘Assign to ‘ + v.TokenText); + } + ; +\end{verbatim} + +\section{EBNF rule elements} + +DPG supports the following extended BNF notations: +\begin{table}[H] + \small + \begin{tabular}{ll} +% \hline + §(...) § & -- exactly one occurrence of a subrule \\ + §(...)?§ & -- zero or one occurrence of a subrule \\ + §(...)+§ & -- one or more occurrence of a subrule \\ + §(...)*§ & -- zero or more occurrence of a subrule +% \hline + \end{tabular} +\end{table} + +\section{Rule arguments} +Character sequences in square brackets are arguments or return type specifiers. +Square brackets within string and character literals are not argument +delimiters. The arguments within §[]§ must follow the Object Pascal syntax. + +\section{Exception handlers} + +DPG allows the specification of exception handlers specific to a +given rule or alternative. The general form of an exception +handler specification is: + +\begin{verbatim} + ... except { code to handle exception } + ... finally { code to handle exception } +\end{verbatim} + +\subsection{Exception handler for a rule} + +The exception handler for a rule must be placed after the +terminating semicolon. The handler can be either an §except§ block +or a §finally§ block. The implementation of a rule will be +surrounded by a try block. + +\begin{verbatim} + r : ... + ; + except { handler code } +\end{verbatim} + +\subsection{Exception handler for an alternative} + +The exception handler of an alternative must be the last element +of the alternative. Both exception handler blocks can be used. +Every alternative that has an exception block will be surrounded +by a §try...except/finally§ block. + +\begin{verbatim} + r : alternative_1 ... except { handler code } + | alternative_2 ... finally { handler code } + ... + | alternative_n + ; +\end{verbatim} + +\paragraph{Note:} It is not necessary to define an exception handler for each alternative. + +\subsection{Default error handler in lexer} + +To skip every character that isn't recognized by any public lexer +rule, specify the option §filter=true§ for a lexer. That way, the +parser doesn't have to deal with lexical errors and ask for +another token. diff --git a/doc/usersguide/src/lang/lang-sect.tex b/doc/usersguide/src/lang/lang-sect.tex new file mode 100644 index 0000000..9b2a081 --- /dev/null +++ b/doc/usersguide/src/lang/lang-sect.tex @@ -0,0 +1,249 @@ +\section{Sections} + +\subsection{unit} +The unit section specifies the unit name of the generated source file. +The syntax is identical to Object Pascal. + +\subsection{uses} +The §uses{...}§ section is used to specify the units which must be +included in the interface's uses clause of the generated pascal +unit. Every unit name must be terminated by a semicolon. Repeated +units are included only once. +\begin{verbatim} + uses + { + Classes; + Windows; + } +\end{verbatim} + + +\subsection{const} +The §const{...}§ section is used to specify items that appear in +the interface's const clause of the generated pascal unit. The +content of this section is copied verbatim into the unit. +\begin{verbatim} + const + { + const1 = 12; + const2 = ‘FOO’; + } +\end{verbatim} + +\subsection{type} +The §type{...}§ section is used to specify items that appear in +the interface's type clause of the generated pascal unit. The +content of this section is copied verbatim into the unit. +\begin{verbatim} + type + { + TmyType1 = integer; + TmyType2 = array [0..16] of TmyType1; + } +\end{verbatim} + +\subsection{options} +The §options{...}§ section contains options for a given grammar +element. Options can be defined for lexer/parser classes, rules +and subrules. + +\subsection{tokens} +If you need to define an ``imaginary'' token (i.e. one that has no +corresponding real input symbol) use the §tokens{...}§ section to +define them. You can also define literals in this section. + +\begin{verbatim} + tokens + { + "procedure"; + "function"; + INTEGER; + } +\end{verbatim} + +Strings defined in this way are treated just as if you had referenced them in +the parser. The formal syntax is: + +\begin{verbatim} + tokenSpecification + : "tokens" + LCURLY + (tokenItem SEMI)* + RCURLY + ; + + tokenItem + : TOKEN + | STRING + ; +\end{verbatim} + +The §tokens{...}§ section is only valid in lexer grammars. + +\subsection{memberdecl} +The §memberdecl{...}§ section contains additional member +declarations for the grammar class. It allows the expansion of the +grammar class with user defined members, so it is not necessary to +derive new classes from the generated class to implement +additional functionality. The content of this section is copied +verbatim into the class declaration of the generated grammar +class. +\begin{verbatim} + memberdecl + { + procedure proc1; + procedure proc2; + } +\end{verbatim} + +\subsection{memberdef} +The §memberdef{...}§ section contains the implementation of the +classes' additional functionality. The content of this section is +copied verbatim into the implementation part of the generated +unit. This section may also contain the initialization and +finalization clauses. + +\begin{verbatim} + memberdef + { + procedure TmyClass.proc1; + begin + ... + end; + + procedure TmyClass.proc2; + begin + ... + end; + } +\end{verbatim} + +\subsection{parser} +Parser rules must be associated with a parser class. Each parser +class specification precedes the options, and rule definitions of +the parser. Grammar files §.g§ can hold only one class definition. +A parser specification in a grammar file looks like: +\begin{verbatim} + unit myParser; + uses... // optional uses {...} section + const... // optional const {...} section + type... // optional type {...} section + + parser TmyParser; + + options... // optional options {...} section + memberdecl... // optional memberdecl {...} section + parser rules... + memberdef... // optional memberdef {...} section +\end{verbatim} + +In the generated code, the parser class results in an Object +Pascal class, and the rules become member methods of the class. + +Note, that the content of the §memberdecl{...}§ section is copied +verbatim into the class declaration part of the generated parser +class while the content of the §memberdef{...}§ section is copied +after the implementation of the member rules, so the +initialization and finalization clauses of a pascal unit can be +placed in the §memberdef{...}§ section. + +\subsection{lexer} +To perform lexical analysis, you need to specify a lexer class that describes +how to break up the input character stream into a stream of tokens. The syntax +is similar to that of a parser class: +\begin{verbatim} + unit myLexer; + uses... // optional uses {...} section + const... // optional const {...} section + type... // optional type {...} section + + lexer TmyLexer; + + options... // optional options {...} section + tokens... // optional tokens {...} section + memberdecl... // optional memberdecl {...} section + lexer rules... + memberdef... // optional memberdef {...} section +\end{verbatim} + +Lexical rules contained within a lexer class become member methods in the +generated class. A lexer grammar may have a §tokens{...}§ section to specify +imaginary tokens and string literals. + +\subsection{rule definitions} +The structure of an input stream of atoms is specified by a set of +mutually-referenced rules. Each rule has a name and any of the +following optional attributes: a scope specifier; a set of +arguments; an init-action; a return value; local variable +definitions; an exception handler and an alternative or +alternatives. Each alternative contains a series of elements that +specify what to match and where. Scope can be specified by +private, protected, or public keywords. A rule has public scope by +default. The basic form of a rule is: +\begin{verbatim} + (scope) rulename + : alternative_1 + | alternative_2 + ... + | alternative_n + ; +\end{verbatim} + +Parameters for a rule can be specified in the following form: +\begin{verbatim} + rulename [formal parameters] : ... ; +\end{verbatim} + +If the rule returns a value, it’s type can be defined with the +returns keyword: +\begin{verbatim} + rulename returns [typename] : ... ; +\end{verbatim} + +where §typename§ is a valid Object Pascal type specifier. + +Local variables for a rule can be defined in the §local{...}§ section: + +\begin{verbatim} + rule + local + { + foo: integer; + bar: string; + } +\end{verbatim} + +Init-actions are specified before the colon. Init-actions differ from normal +actions because they are always executed regardless of guess mode. + +\begin{verbatim} + rule + { + init-action + } + : ... ; +\end{verbatim} + + +\paragraph{Parser rules} apply structure to a stream of tokens, whereas +lexer rules apply structure to a stream of characters. Parser +rules, therefore, must not reference cha\-rac\-ter literals. +Double-quoted strings in parser rules are considered to be token +references. Note: all parser rules must begin with a lowercase +letter. + +\paragraph{Lexer rules} defined within a lexer grammar must have a name beginning +with an uppercase letter. These rules implicitly match +cha\-rac\-ters on the input stream instead of tokens on the token +stream. Referenced grammar elements include token references +(implicit lexer rule references), cha\-rac\-ters and strings. +Lexer rules are processed in the same manner as parser rules, and +may also specify arguments and return values. A scope specifier +for a lexer rule has special meaning in lexer grammars. In the +generated Object Pascal unit, the lexer class has a §nextToken§ +function which is the interface between the lexer and the parser. +This function is synthesized from the public lexer rules. It means +that non-public lexer rules don't modify the prediction logic of +the lexer. They are usually helper rules. If the lexer grammar has +no public rule at all, the §nextToken§ function returns EOF to the +parser. diff --git a/doc/usersguide/src/lang/lang-simpprod.tex b/doc/usersguide/src/lang/lang-simpprod.tex new file mode 100644 index 0000000..4891eaf --- /dev/null +++ b/doc/usersguide/src/lang/lang-simpprod.tex @@ -0,0 +1,79 @@ +\section{Simple production elements} +\subsection{Rule reference} +Identifiers beginning with lowercase letter are treated as parser +rule references. The subsequent characters may be any letter, +digit, number, or underscore. Lexical rules may not reference +parser rules. Referencing a rule implies a method call to that +rule at that point in the parse. You may pass parameters and +obtain return values. For example, formal and actual parameters +are specified within square brackets: +\begin{verbatim} + function + : type ID LPAREN args RPAREN block [1] + ; + + block [scope: integer] + : LCURLY + ... + { (* use arg 'scope' *) } + ... + RCURLY + ; +\end{verbatim} + +Return values that are stored in variables use a simple assignment +notation: +\begin{verbatim} + set + local + { + ids : TStringList; + } + { + ids := nil; + } + : LPAREN ids=idList RPAREN + ; + + idList returns [TStringList] + { + result := TStringList.Create; + } + : id:ID { result.Add( id.TokenText;); } + ( + COMMA id:ID + { + result.Add( id.TokenText;); + } + )* + ; +\end{verbatim} + +\subsection{Semantic action} +Actions are blocks of Object Pascal source code enclosed in curly braces. The +code is executed after the preceding production element has been recognized and +before the recognition of the following element. Actions are typically used to +generate out\-put, construct trees, or modify a symbol table. An action's +position dictates when it is recognized relative to the surrounding grammar +elements. + +If the action is the first element of a production, it is executed +before any other e\-le\-ment in that production, but only if that +production is predicted by the lookahead. + +The first action of an §EBNF§ subrule may be followed by §:§. +Doing so de\-sig\-na\-tes the action as an init-action and +associates it with the subrule as a whole, instead of any +production. It is executed immediately upon entering the subrule, +and is executed even while guessing (testing syntactic +predicates). For example: + +\begin{verbatim} + ( { init-action} : + { action of 1st production} production1 + | { action of 2nd production} production2 + )? +\end{verbatim} + +The init-action would be executed regardless of what (if anything) +matched in the optional subrule. diff --git a/doc/usersguide/src/lang/lang-syntactic.tex b/doc/usersguide/src/lang/lang-syntactic.tex new file mode 100644 index 0000000..f5fa83e --- /dev/null +++ b/doc/usersguide/src/lang/lang-syntactic.tex @@ -0,0 +1,49 @@ +Delphi Parser Generator (DPG) uses the ASCII character set, +including the letters \emph{A} through \emph{Z} and \emph{a} +through \emph{z}, the digits \emph{0} through \emph{9}, and other +standard characters. It is case sensitive. The space character +(ASCII 32), the tab character (ASCII 9), and the new-line +characters (ASCII 13,10) are called \emph{white-space} characters. + +\section{General} +\subsection{Comments} +DPG accepts single and multi-line comments. Single-line comments begin with +§//§ while multi-line (block) comments are enclosed by §(*§~and~§*)§. + +\subsection{White Space} +Spaces, tabs, and new-lines (including most used §CR-LF§, §CR§, +§LF§ constructions) are separators in that they separate DPG +symbols, such as identifiers. White spaces have no additional +significance i.e. the code layout does not play any semantical +role. However the layout of the embedded Delphi code is preserved +in the ge\-ne\-ra\-ted source files. + +\subsection{Symbols} +DPG uses the following punctuation and keywords: + +\begin{table}[H] + \small + \begin{center} + \begin{tabular}{|ll|ll|} + \hline + §(...)§ & subrule & §unit§ & unit name \\ + §(...)*§ & closure subrule & §uses§ & uses section \\ + §(...)+§ & positive closure & §const§ & const section \\ + §(...)?§ & optional subrule & §type§ & type section \\ + §[...]§ & rule arguments & §lexer§ & lexer class \\ + §{...}§ & semantic action & §parser§ & parser class \\ + §{...}?§ & semantic predicate & §options§ & options section \\ + §(...)=>§ & syntactic predicate & §tokens§ & tokens section \\ + § |§ & alternative operator & §returns§ & rule return value \\ + § ..§ & range operator & §except§ & exception handler \\ + § ~§ & not operator & §finally§ & exception handler \\ + § !§ & ignore operator & §memberdecl§ & member declaration \\ + § .§ & wildcard & §memberdef§ & member definition \\ + § =§ & assignment operator & §local§ & local rule variables \\ + § :§ & label, start rule & & \\ + § ;§ & end rule & & \\ + \hline + \end{tabular} + \end{center} + \caption{DPG symbols} +\end{table} diff --git a/doc/usersguide/src/lang/lang.tex b/doc/usersguide/src/lang/lang.tex new file mode 100644 index 0000000..4c4d0a1 --- /dev/null +++ b/doc/usersguide/src/lang/lang.tex @@ -0,0 +1,10 @@ +\chapter{Syntactic elements} +\minitoc +\clearpage +\include{src/lang/lang-syntactic} +\include{src/lang/lang-atomprod} +\include{src/lang/lang-simpprod} +\include{src/lang/lang-prodoper} +\include{src/lang/lang-sect} +\include{src/lang/lang-opt} +\include{src/lang/lang-rest} diff --git a/doc/usersguide/src/rt/rt-err.tex b/doc/usersguide/src/rt/rt-err.tex new file mode 100644 index 0000000..cb68c21 --- /dev/null +++ b/doc/usersguide/src/rt/rt-err.tex @@ -0,0 +1,94 @@ +\section{Error handling} + +All syntactic and semantic errors throw exceptions. In particular, +the methods used to match tokens in the parser base class (match +etc) throw §EdpgMismatchedToken§. The methods in the lexer base +class used to match characters (match etc) throw exceptions +similarly. + +\subsection{DPG exception hierarchy} + +DPG-generated parsers throw exceptions to signal recognition +errors or other stream problems. All exceptions derive from +EdpgException. The hierarchy is as follows: + +\begin{verbatim} + EdpgException + EdpgMismatchedChar + EdpgMismatchedToken + EdpgSemantic +\end{verbatim} + +\subsection{EdpgException} +The §EdpgException§ is the base class for all DPG exceptions. It +defines the following read-only properties: +\begin{alltt} + FileName : string; + Line : integer; + Column : integer; +\end{alltt} +These properties contain information about the location where the exception +occurred. + +\subsection{EdpgMismatchedChar} +The §EdpgMismatchedChar§ exception is thrown by the lexer when it +is looking for a character, but finds a different one on the input +stream than expected. It defines the following properties in +addition to those of §EdpgException§. +\begin{alltt} + FoundChar : char; + FoundString : string; + CharSet : TdpgCharSet; + Str : string; + Inverted : boolean; +\end{alltt} +The §FoundChar§ and §FoundString§ properties contain the character +or string that was found on the input stream. The §CharSet§ and +§Str§ properties contain the values which the lexer expected to +find. The §Inverted§ property is set only if the exception came +from a §MatchNot(...)§ operation. In this case, the §CharSet§ +property contains the values, that the lexer must §not§ match. The +validity of pro\-per\-ti\-es are shown in the next table, +depending on the kind of exception. + +\begin{table}[H] + \small + \begin{center} + \begin{tabular}{lcc} + & Mismatched char & Mismatched string \\ + \hline + FoundChar & valid & - \\ + FoundString & - & valid \\ + CharSet & valid & - \\ + Str & - & valid \\ + Inverted & valid & - \\ + \hline + \end{tabular} + \end{center} +\end{table} + +\subsection{EdpgMismatchedToken} +The §EdpgMismatchedToken§ exception is thrown by the parser when +it is looking for a token, but finds a different one on the input +token stream than expected. It defines the following properties in +addition to those of §EdpgException§. +\begin{alltt} + FoundToken : IdpgToken; + TokenSet : TdpgByteSet; + Inverted : boolean; +\end{alltt} +The §FoundToken§ property contains the token the parser received from the +lexer. The §TokenSet§ property contains the vaules the parser expected to +get. The §Inverted§ property is set only if the exception came from a +§MatchNot(...)§ operation. In this case, the §TokenSet§ property contains the +values the parser must §not§ get. + +\subsection{EdpgSemantic} +This exception is thrown by a validating semantic predicate. It +defines the following property in addition to those of +§EdpgException§. +\begin{alltt} + Assert : string; +\end{alltt} +The §Assert§ property contains the validating expression that caused the +exception. diff --git a/doc/usersguide/src/rt/rt.tex b/doc/usersguide/src/rt/rt.tex new file mode 100644 index 0000000..50c0ab8 --- /dev/null +++ b/doc/usersguide/src/rt/rt.tex @@ -0,0 +1,3 @@ +\chapter{Run-time} +\minitoc \clearpage +\include{src/rt/rt-err} diff --git a/doc/usersguide/src/start/start.tex b/doc/usersguide/src/start/start.tex new file mode 100644 index 0000000..956c1c5 --- /dev/null +++ b/doc/usersguide/src/start/start.tex @@ -0,0 +1,200 @@ +\chapter{Getting started} +\minitoc \clearpage + +In this chapter, we develop a simple calculator. It accepts integers, the four +arithmetic operators (§+§,§-§,§/§,§*§), and parenthesis on its input. +Spaces, tabs and newline characters are treated as white spaces and used for +separating tokens. Complete Expressions must be terminated by semicolons. + +\section{Lexical analyzer} + +Let us define the calculator's lexer. + +\begin{verbatim} + 1 unit myLexer; + 2 + 3 lexer TmyLexer; + 4 options + 5 { + 6 exportvocab = myLexer; + 7 } +\end{verbatim} +In line §1§ we define the unit name of the generated Pascal source +file for the lexer. In line §3§ we give a name to the lexer class. +If there is an §options§ block for a grammar class, it must follow +the class declaration. Here, we define one option for the lexer: +§exportVocab§. This option tells the DPG that all the token +definitions must be exported to §myLexerTokens.txt§ and +§myLexerTokens.pas§. Grammars can import the generated token names +using the exported §.txt§ files. + +\paragraph{Note:} it is not necessary to define the §exportVocab§ option for a +grammar. The file names for the token exchange files are automatically created +using the specified unit name. + +Now we define the lexer tokens. + +\begin{verbatim} + 8 LPAREN: '('; + 9 RPAREN: ')'; + 10 PLUS: '+'; + 11 MINUS: '-'; + 12 STAR: '*'; + 13 SLASH: '/'; + 14 SEMI: ';'; +\end{verbatim} +In lines from §8§ to §14§, there are simple token definitions. Each of them +recognizes one character from the input stream. + +\begin{verbatim} + 15 INT: ('0'..'9')+ ; +\end{verbatim} +In line §15§, we define a rule to recognize integer numbers. This tells us that +the INT consists of one or more numeric characters. + +Now, define a rule to handle white space characters. +\begin{verbatim} + 16 WS + 17 : '\r' '\n' { _ttype := TT_SKIP; } + 18 | '\t' { _ttype := TT_SKIP; } + 19 | ' ' { _ttype := TT_SKIP; } + 20 ; +\end{verbatim} +Characters surrounded by curly braces are actions. The content of +an action block will be copied verbatim into the generated Pascal +source file. In this example the expression §_ttype := TT_SKIP;§ +forbids the §WS§ rule to generate a token, because we don't need +it. + +Now the lexer definition is finished. This simple lexer recognizes relevant +characters, integers and skips every white spaces on its input. + +\section{Parser} + +Now we define the parser. + +\begin{verbatim} + 1 unit myParser; + 2 + 3 parser TmyParser; + 4 options + 5 { + 6 importVocab = myLexer; + 7 } +\end{verbatim} +This part is analogous to lexer definition with one exception. In +line §6§, we import the tokens from a file specified by the +§exportVocab§ option in the lexer grammar. Now, the parser knows +which tokens are to be expected from the lexer. + +\begin{verbatim} + 8 memberdecl + 9 { + 10 value: integer; + 11 } +\end{verbatim} +In lines from §8§ to §11§, we specify the §memberdecl§ section. This section is +used to define members for the generated parser class. In this example, the §TmyParser§ +class will have a member called §value§. We use this member to store the result +of the calculation for the current expression. + +Now we define the rules. +\begin{verbatim} + 12 calc + 13 : (expression SEMI { writeln( value); } )* + 14 ; + 15 + 16 expression + 17 local + 18 { + 19 temp : integer; + 20 } + 21 : term { temp := value; } + 22 ( + 23 PLUS term { temp := temp + value; } + 24 | MINUS term { temp := temp - value; } + 25 )* { value := temp; } + 26 ; +\end{verbatim} +In lines §17..20§, we define a local variable for the rule +§expression§. The following rules are defined in a similar way to +the rule §expression§. + +\begin{verbatim} + 27 term + 28 local + 29 { + 30 temp : integer; + 31 } + 32 : factor { temp := value; } + 33 ( + 34 STAR factor { temp := temp * value; } + 35 | SLASH factor { temp := temp div value; } + 36 )* { value := temp; } + 37 ; + 38 + 39 factor + 40 local + 41 { + 42 temp : integer; + 43 } + 44 : uInt + 45 | LPAREN expression RPAREN + 46 ; + 47 + 48 uInt + 49 : x:INT { value := StrToInt( x.TokenText); } + 50 ; +\end{verbatim} +In line §49§, we specified that the rule must have a variable +called 'x' which will contain the INT token. For the moment, it is +enough to know that it has a property §TokenText§ which contains +the text of the recognized token. This property is a string +property, so we have to convert it to an integer, and store it in +the §value§ member variable. + +\section{The project} +The following simple project demonstrates how the defined lexer +and parser classes are used. + +\begin{verbatim} + 1 program calc; + 2 {$APPTYPE CONSOLE} + 3 uses + 4 Classes, + 5 SysUtils, + 6 myLexer in 'myLexer.pas', + 7 myParser in 'myParser.pas'; + 8 + 9 var + 10 stm: TFileStream; + 11 lex: TmyLexer; + 12 par: TmyParser; + 13 + 14 begin + 15 if ParamCount <> 1 then + 16 begin + 17 writeln('usage: calc '); + 18 exit; + 19 end + 20 else + 21 begin + 22 try + 23 stm := TFileStream.Create( ParamStr(1), + 24 fmOpenRead); + 24 lex := TmyLexer.Create(stm); + 25 par := TmyParser.Create(lex); + 26 + 27 par.calc; + 28 except + 29 on EdpgMismatchedToken do + 22 writeln('Syntax error'); + 30 on EdpgMismatchedChar do + 33 writeln('Syntax rrror'); + 29 end; + 30 end; + 31 + 32 stm.Free; + 33 par.Free; + 34 end. +\end{verbatim} diff --git a/doc/usersguide/src/tokens/tokens.tex b/doc/usersguide/src/tokens/tokens.tex new file mode 100644 index 0000000..8d66a1b --- /dev/null +++ b/doc/usersguide/src/tokens/tokens.tex @@ -0,0 +1,281 @@ +\chapter{Tokens} +\minitoc \clearpage +\section{Overview} +Tokens are the basic building blocks of any parser or compiler. +The task of a lexer (lexical analyzer, scanner) is to break up the +input character stream into a stream of tokens. Then §nextToken§ +method of a lexer passes the next token to the parser, or throws +an exception if the next character on the input stream cannot be +matched by any of the public lexer rules. The §nextToken§ method +is always synthesized from the public lexer rules. + +§Tokens§ in DPG are interface pointers. The interface type is §IdpgToken§, +which defines the following properties: +\begin{verbatim} + IdpgToken = interface + ... + property TokenText : string; + property TokenType : integer; + property TokenLine : integer; + property TokenColumn : integer; + ... + end; +\end{verbatim} + +where §TokenText§ is the text matched by the lexer; §TokenType§ is +the type of token assigned to the token by DPG; §TokenLine§ is the +line number where the token starts in the input stream; +§TokenColumn§ is the column number. + +Within parser rules, the input token can be accessed via this interface. To +obtain the interface to the recognized token, the reference to the token must +be prefixed by a label. For example, +\begin{verbatim} + ... + x:NUMBER + { + ... + LogMsg( 'Token: ' + x.TokenText ); + LogMsg( 'Type: ' + IntToStr(x.TokenType)); + ... + } + ... +\end{verbatim} + +Note: Variables for labels are always generated by DPG, so you should not define +them in the §local{...}§ section of the rule. + +\section{Defining tokens} +In DPG, tokens can be defined in the lexer grammars. DPG always +generates a token exchange file that describes all the token types +matched by the lexer. This file can be imported in a parser +grammar, so the lexer and parser have the same token types. Tokens +can be defined either, +\begin{itemize} + \item[-] via lexer rules, or + \item[-] in the lexer's §tokens{...}§ section +\end{itemize} + +\subsubsection{Defining a token using a lexer rule} +The commonest method of defining a token is using a lexer rule. In +lexer grammars, every rule is associated with a §TokenType§ which +is determined by DPG at compile time. This value is assigned to +the result token by default, but it can be modified in the given +rule if needed. This is used mostly in rules that need runtime +information to set the type of the result token, but is otherwise +uncommon. + +There is one exception: when a rule must not generate a token at all. +This is useful for defining comments or white-spaces for a grammar. +Every lexer rule has a local variable called §_ttype§. If +§_ttype§ has a value of §TT_SKIP§, then the rule won't generate any token. For +example, +\begin{verbatim} + SLCOMMENT : "//" ( ~'\n')* '\n' { _ttype := TT_SKIP; } ; +\end{verbatim} + +The following examples are normal lexer rules, and they are typical in lexers: +\begin{verbatim} + LPAREN: '('; + RPAREN: ')'; + DIGIT: '0'..'9'; + NUMBER: DIGIT (DIGIT)*; + LETTER: 'a'..'Z' | 'A'..'Z'; + ID: LETTER (LETTER | DIGIT | '_')*; +\end{verbatim} + +\subsubsection{Defining a token in the tokens\{...\} section} + +Lexer grammars may have a §tokens{...}§ section in the class +declaration. Within this section you can define ``imaginary'' +tokens and string literals. These tokens are not ``real'' tokens +and cannot be referenced in lexer rules. ``Imaginary'' tokens are +helpful when a rule can recognize more than one type of token and +defining rules for these tokens would be ambiguous. For example, + +\begin{verbatim} +tokens +{ + STRING; + CHAR; +} +// ======================================================== +// String or char +// ======================================================== +STRING_OR_CHAR +: '\'' (~'\'' | '\'' '\'')* '\'' + { + if TokenText = '''''' then _ttype := TT_STRING + else if TokenText = '''''''''' then _ttype := TT_CHAR + else if Length( TokenText) > 3 then _ttype := TT_STRING + else _ttype := TT_CHAR; + } +; +\end{verbatim} +The rule §STRING_OR_CHAR§ recognizes a pascal character literal, +and a pascal string literal. The code in the action block decides +which type of token must be created by the rule. Note: These +tokens are ``imaginary'' tokens. Referencing them in lexer +grammars is not possible, because they have no implementation. +Within parser rules, the tokens §STRING§ and §CHAR§ can be +referenced. But §STRING_OR_CHAR§ can't be referenced, because this +rule creates a §STRING§ or a §CHAR§ token. + +\paragraph{String literals} in the §tokens{...}§ section are useful when the language +defines keywords. In this case you can list your language's keywords in this +section. They will be put into the lexer's literals table. The lexer will consult +this table in the following cases: +\begin{itemize} + \item[-] if the §testLiterals§ option for the lexer class is true, the lexer checks the + literals table after each recognized token, + \item[-] if the §testLiterals§ option for the lexer class is false, the + check will be executed in rules, that have this option set. +\end{itemize} + +If neither lexer rules nor lexer class have this option set, the +lexer's literals table can be explicitly checked via the +§TestLiterals§ method. The advantage of using string literals is +that you can reference them in the parser as they are defined in +the §tokens{...}§ section. For example, + +\begin{verbatim} + ... + lexer TmyLexer; + options + { + testLiterals = true; + } + tokens + { + ... + "function"; + "procedure"; + ... + } + ... + + parser TmyParser; + rule1 : "function" ID SEMI; + rule2 : "procedure" ID LPAREN args RPAREN SEMI; + ... +\end{verbatim} +In the above example we set the §testLiterals§ option to true for the lexer +class. This is not recommended, because the lexer will check the literals table +even if it found a non-string token. Instead, you have to check the table in a +rule that can recognize these literals. For example: + +\begin{verbatim} + ... + lexer TmyLexer; + ... + + ID + options + { + testLiterals=true; + } + : 'a'..'z' | 'A'..'Z' ('a'..'z' | 'A'..'Z' | '0'..'9')* + ; +\end{verbatim} +Here the literals table will only be consulted in the rule §ID§. +This will improve the lexer's speed. Of course you can set the +§testLiterals§ options to true for as many rules as you want. All +of them will check the literals table. + +\paragraph{Note:} The §testLiterals§ option has no effect for lexer rules. + + +\section{User defined token classes} + +By default, DPG uses the §TdpgToken§ class to represent tokens. +This class is derived from §TInterfacedObject§, and implements the +§IdpgToken§ interface. This interface is used across the generated +code. To define a new token class you must derive your new class +from §TdpgToken§, implement your interface to access and +manipulate your object, and finally tell the lexer that it must +create your type of token object instead of the default +§TdpgToken§. After that, within the rules you must obtain the +interface of your class and use it. Let us have a more detailed +look at this: + +1. Create a token class: +\begin{verbatim} + ImyToken = interface( IdpgToken) + [a guid definition] + + function Get_MyString : string; + procedure Set_MyString( AString: string); + + property MyString : string read Get_MyString + write Set_MyString; + end; + + TmyToken = class( TdpgToken, + IdpgToken, + ImyToken) + protected + fMyString : string; + + function Get_MyString : string; + procedure Set_MyString( AString: string); + + public + constructor Create( pType: integer; + pText: string); override; + + end; + + constructor TmyToken.Create( pType: integer; + pText: string); + begin + inherited; + ... + your code here + ... + end; + + function TmyToken.Get_MyString: string; + begin + result := fMyString; + end; + + function TmyToken.Set_MyString( pString: string); + begin + fMyString := pString; + end; +\end{verbatim} + +2. Tell to lexer that it must use our token class. +\begin{verbatim} + uses myToken; + ... + myLexer.TokenClass := TmyToken; +\end{verbatim} + +3. Use it in a rule. +\begin{verbatim} + ... + parser TmyParser; + + rule1 + : + "procedure" x:id (LPAREN params RPAREN)? + { + (x as ImyToken).MyString := 'procid'; + } + ; + +\end{verbatim} + +\paragraph{Note:} You must cast the returned interface to your token interface, +because the §makeToken§ method of the lexer always returns an §IdpgToken§ +interface and the labels specified to obtain a reference to a token are always +§IdpgToken§ references. + +\paragraph{Note:} If you have to do special actions to initialize your token +class, you must have the same constructor as defined in the +example. The §makeToken§ method of the lexer always creates tokens +with this constructor. If you have another kind of constructor for +your token class, it won't be used by the lexer. + +\clearpage diff --git a/doc/usersguide/zlbook.cls b/doc/usersguide/zlbook.cls new file mode 100644 index 0000000..d8d8d0d --- /dev/null +++ b/doc/usersguide/zlbook.cls @@ -0,0 +1,88 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{zlbook} +\LoadClass[a4paper,twoside,11pt]{book} +\usepackage{times} +\usepackage{chappg} +\usepackage{here} +\usepackage{alltt} +\usepackage[bookman]{quotchap} +\RequirePackage{shortvrb} +\MakeShortVerb{\§} + +\let\o@verbatim\verbatim + +\def\verbatim{% + \ifhmode\unskip\par\fi +% \nopagebreak % Overridden by list penalty + \ifx\@currsize\normalsize + \small + \fi + \o@verbatim +} + +% No paragraph indentation, space between paragraphs +\setlength{\parindent}{0pt} +\setlength{\parskip}{\medskipamount} + +\renewcommand{\thepage}{\thechapter\ - \arabic{page}} + +\usepackage{fancyhdr} +\pagestyle{fancy} +%\addtolength{\headwidth}{0.5in} +%\addtolength{\headwidth}{\marginparsep} +%\addtolength{\headwidth}{\marginparwidth} +\renewcommand{\chaptermark}[1]{\markboth{#1}{}} +\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} +\fancyhf{} +%\fancyhead[LE,RO]{\bfseries\thepage} +%\fancyhead[RO]{\bfseries\rightmark} +%\fancyhead[LE]{\bfseries\leftmark} +\fancyfoot[RO]{\bfseries\thepage} +\fancyfoot[LE]{\bfseries\thepage} + +\fancyhead[RO]{\rightmark} +\fancyhead[LE]{\leftmark} +\fancyfoot[RO]{\thepage} +\fancyfoot[LE]{\thepage} + +\fancypagestyle{plain}{% + \fancyhf{} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} +} + +\renewcommand{\headrulewidth}{0.4pt} +\renewcommand{\footrulewidth}{0.4pt} +%\renewcommand{\normalsize}{\fontsize{10pt}{12pt}\selectfont} + + +\def\cleardoublepage{\clearpage\if@twoside \ifodd\c@page\else + \hbox{} + \vspace*{\fill} + \begin{center} +% This page intentionally left blank. + \end{center} + \vspace{\fill} + \thispagestyle{empty} + \newpage + \if@twocolumn\hbox{}\newpage\fi\fi\fi} + +%\addtolength{\textwidth}{1cm} + + +\newenvironment{decl}[1][]% + {\par\small\addvspace{4.5ex plus 1ex}% + \vskip -\parskip + \ifx\relax#1\relax + \def\@decl@date{}% + \else + \def\@decl@date{\NEWfeature{#1}}% + \fi + \noindent\hspace{-\leftmargini}% + \begin{tabular}{|l|}\hline\ignorespaces}% + {\\\hline\end{tabular}\nobreak\@decl@date\par\nobreak + \vspace{2.3ex}\vskip -\parskip} + +\newcommand{\NEWfeature}[1]{% + \hskip 1sp \marginpar{\small\sffamily\raggedright + New feature\\#1}}