├── example ├── example.lpr ├── example.lpi ├── unit1.pas ├── unit1.lfm └── simplegrammar.pas ├── fpcgoldenginelpk.pas ├── .gitignore ├── README.md ├── fpcgoldenginelpk.lpk ├── LICENSE └── src ├── parser.pas ├── cgtgrammar.pas └── lexer.pas /example/example.lpr: -------------------------------------------------------------------------------- 1 | program example; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | uses 6 | {$IFDEF UNIX} 7 | cthreads, 8 | {$ENDIF} 9 | {$IFDEF HASAMIGA} 10 | athreads, 11 | {$ENDIF} 12 | Interfaces, // this includes the LCL widgetset 13 | Forms, Unit1; 14 | 15 | {$R *.res} 16 | 17 | begin 18 | RequireDerivedFormResource:=True; 19 | Application.Scaled:=True; 20 | Application.Initialize; 21 | Application.CreateForm(TForm1, Form1); 22 | Application.Run; 23 | end. 24 | 25 | -------------------------------------------------------------------------------- /fpcgoldenginelpk.pas: -------------------------------------------------------------------------------- 1 | { This file was automatically created by Lazarus. Do not edit! 2 | This source is only used to compile and install the package. 3 | } 4 | 5 | unit FPCGoldEnginelpk; 6 | 7 | {$warn 5023 off : no warning about unused units} 8 | interface 9 | 10 | uses 11 | cgtgrammar, lexer, parser, LazarusPackageIntf; 12 | 13 | implementation 14 | 15 | procedure Register; 16 | begin 17 | end; 18 | 19 | initialization 20 | RegisterPackage('FPCGoldEnginelpk', @Register); 21 | end. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Lazarus compiler-generated binaries (safe to delete) 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | *.lrs 7 | *.res 8 | *.compiled 9 | *.dbg 10 | *.ppu 11 | *.o 12 | *.or 13 | *.a 14 | *.ico 15 | 16 | # Lazarus autogenerated files (duplicated info) 17 | *.rst 18 | *.rsj 19 | *.lrt 20 | 21 | # Lazarus local files (user-specific info) 22 | *.lps 23 | 24 | # Lazarus backups and unit output folders. 25 | # These can be changed by user in Lazarus/project options. 26 | backup/ 27 | *.bak 28 | lib/ 29 | 30 | # Application bundle for Mac OS 31 | *.app/ 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPC GOLD Engine 2 | 3 | This is an engine for the GOLD Parsing System (http://goldparser.org/) written in FreePascal. 4 | 5 | See the example for a small program that builds a parse tree and uses the Lexer to Colorize a `TSynEdit` 6 | 7 | ## Features 8 | * v1.0 and v5.0 support 9 | * event based parse tree construction 10 | 11 | ## Example Usage: 12 | ```pascal 13 | function TMyClass.BuildTreeNode(const Produces: TGrammarSymbol; Consumes: specialize TArray): TObject; 14 | begin 15 | Result := TParseTree.Create(Produces.Name, Consumes); 16 | end; 17 | 18 | function TMyClass.BuildLeafNode(const AToken: TToken): TObject; 19 | begin 20 | Result := TParseTreeLeaf.Create(AToken.Name); 21 | end; 22 | 23 | ... 24 | 25 | Grammar := TCGTGrammar.Create; 26 | try 27 | Grammar.LoadFromFile(FileName); 28 | ParseTree := Grammar.ParseString(InputString, @BuildTreeNode, @BuildLeafNode); 29 | finally 30 | Grammar.Free; 31 | end; 32 | ``` 33 | 34 | ## Documentation 35 | Currently no documentation available specifically for the node engine. 36 | 37 | For general engine design and how to construct your own engine check out https://github.com/Warfley/goldengine/docs 38 | -------------------------------------------------------------------------------- /fpcgoldenginelpk.lpk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, Frederic Kehrein 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /example/example.lpi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <Scaled Value="True"/> 10 | <ResourceType Value="res"/> 11 | <UseXPManifest Value="True"/> 12 | <XPManifest> 13 | <DpiAware Value="True/PM_V2"/> 14 | </XPManifest> 15 | <Icon Value="0"/> 16 | </General> 17 | <BuildModes> 18 | <Item Name="Default" Default="True"/> 19 | </BuildModes> 20 | <PublishOptions> 21 | <Version Value="2"/> 22 | <UseFileFilters Value="True"/> 23 | </PublishOptions> 24 | <RunParams> 25 | <FormatVersion Value="2"/> 26 | </RunParams> 27 | <RequiredPackages> 28 | <Item> 29 | <PackageName Value="FPCGoldEnginelpk"/> 30 | </Item> 31 | <Item> 32 | <PackageName Value="SynEdit"/> 33 | </Item> 34 | <Item> 35 | <PackageName Value="LCL"/> 36 | </Item> 37 | </RequiredPackages> 38 | <Units> 39 | <Unit> 40 | <Filename Value="example.lpr"/> 41 | <IsPartOfProject Value="True"/> 42 | </Unit> 43 | <Unit> 44 | <Filename Value="unit1.pas"/> 45 | <IsPartOfProject Value="True"/> 46 | <ComponentName Value="Form1"/> 47 | <HasResources Value="True"/> 48 | <ResourceBaseClass Value="Form"/> 49 | <UnitName Value="Unit1"/> 50 | </Unit> 51 | </Units> 52 | </ProjectOptions> 53 | <CompilerOptions> 54 | <Version Value="11"/> 55 | <PathDelim Value="\"/> 56 | <Target> 57 | <Filename Value="example"/> 58 | </Target> 59 | <SearchPaths> 60 | <IncludeFiles Value="$(ProjOutDir)"/> 61 | <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> 62 | </SearchPaths> 63 | <Linking> 64 | <Debugging> 65 | <UseHeaptrc Value="True"/> 66 | </Debugging> 67 | <Options> 68 | <Win32> 69 | <GraphicApplication Value="True"/> 70 | </Win32> 71 | </Options> 72 | </Linking> 73 | </CompilerOptions> 74 | <Debugging> 75 | <Exceptions> 76 | <Item> 77 | <Name Value="EAbort"/> 78 | </Item> 79 | <Item> 80 | <Name Value="ECodetoolError"/> 81 | </Item> 82 | <Item> 83 | <Name Value="EFOpenError"/> 84 | </Item> 85 | </Exceptions> 86 | </Debugging> 87 | </CONFIG> 88 | -------------------------------------------------------------------------------- /example/unit1.pas: -------------------------------------------------------------------------------- 1 | unit Unit1; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls, 9 | EditBtn, StdCtrls, Buttons, SynEdit, SynEditHighlighter, cgtgrammar, lexer, parser, 10 | SimpleGrammar; 11 | 12 | type 13 | 14 | { TForm1 } 15 | 16 | TForm1 = class(TForm) 17 | Button1: TButton; 18 | Button2: TButton; 19 | FileNameEdit1: TFileNameEdit; 20 | OpenDialog1: TOpenDialog; 21 | Panel1: TPanel; 22 | Splitter1: TSplitter; 23 | SynEdit1: TSynEdit; 24 | TreeView1: TTreeView; 25 | procedure Button1Click(Sender: TObject); 26 | procedure Button2Click(Sender: TObject); 27 | procedure FormCreate(Sender: TObject); 28 | procedure FormDestroy(Sender: TObject); 29 | private 30 | FGrammar: TCGTGrammar; 31 | function LeafNode(const AToken: TToken): TTreeNode; 32 | function ReduceNode(const Produces: TGrammarSymbol; Consumes: specialize TArray<TTreeNode>): TTreeNode; 33 | procedure MoveToParent(Node, NewParent: TTreeNode); 34 | public 35 | 36 | end; 37 | 38 | { TGrammarHighlighter } 39 | 40 | TGrammarHighlighter = class(TSynCustomHighlighter) 41 | private 42 | FGrammar: TCGTGrammar; 43 | FLastMatch: TToken; 44 | FIterator: TUTF8Iterator; 45 | FAttributes: Array of TSynHighlighterAttributes; 46 | public 47 | constructor WithDFA(AOwner: TComponent; AGrammar: TCGTGrammar); 48 | destructor Destroy; override; 49 | 50 | procedure SetLine(const NewValue: String; LineNumber: Integer); override; 51 | procedure Next; override; 52 | function GetEol: Boolean; override; 53 | function GetToken: String; override; 54 | function GetTokenPos: Integer; override; 55 | function GetTokenKind: integer; override; 56 | function GetTokenAttribute: TSynHighlighterAttributes; override; 57 | procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); 58 | override; 59 | function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; 60 | override; 61 | end; 62 | 63 | var 64 | Form1: TForm1; 65 | 66 | implementation 67 | 68 | {$R *.lfm} 69 | 70 | { TGrammarHighlighter } 71 | 72 | constructor TGrammarHighlighter.WithDFA(AOwner: TComponent; 73 | AGrammar: TCGTGrammar); 74 | var 75 | i: Integer; 76 | begin 77 | inherited Create(AOwner); 78 | FGrammar := AGrammar; 79 | SetLength(FAttributes, 10); 80 | for i:=0 to Length(FAttributes) - 1 do 81 | begin 82 | FAttributes[i] := TSynHighlighterAttributes.Create(i.ToString); 83 | FAttributes[i].Foreground := Random($FFFFFF); 84 | end; 85 | end; 86 | 87 | destructor TGrammarHighlighter.Destroy; 88 | var 89 | Attr: TSynHighlighterAttributes; 90 | begin 91 | for Attr in FAttributes do 92 | Attr.Free; 93 | inherited Destroy; 94 | end; 95 | 96 | procedure TGrammarHighlighter.SetLine(const NewValue: String; 97 | LineNumber: Integer); 98 | begin 99 | inherited SetLine(NewValue, LineNumber); 100 | FIterator := IterateUTF8(NewValue); 101 | FLastMatch := FGrammar.LexToken(FIterator); 102 | end; 103 | 104 | procedure TGrammarHighlighter.Next; 105 | begin 106 | FLastMatch := FGrammar.LexToken(FIterator); 107 | end; 108 | 109 | function TGrammarHighlighter.GetEol: Boolean; 110 | begin 111 | Result := FLastMatch.Symbol^.SymbolType = stEOF; 112 | end; 113 | 114 | function TGrammarHighlighter.GetToken: String; 115 | begin 116 | Result := FLastMatch.Value; 117 | end; 118 | 119 | function TGrammarHighlighter.GetTokenPos: Integer; 120 | begin 121 | Result := FLastMatch.StartPos; 122 | end; 123 | 124 | function TGrammarHighlighter.GetTokenKind: integer; 125 | begin 126 | Result := FLastMatch.Symbol^.Index; 127 | end; 128 | 129 | function TGrammarHighlighter.GetTokenAttribute: TSynHighlighterAttributes; 130 | begin 131 | Result := FAttributes[abs(FLastMatch.Symbol^.Index) mod Length(FAttributes)]; 132 | end; 133 | 134 | procedure TGrammarHighlighter.GetTokenEx(out TokenStart: PChar; out 135 | TokenLength: integer); 136 | begin 137 | TokenStart := @FIterator.Data[FLastMatch.StartPos]; 138 | TokenLength := FLastMatch.Value.Length; 139 | end; 140 | 141 | function TGrammarHighlighter.GetDefaultAttribute(Index: integer 142 | ): TSynHighlighterAttributes; 143 | begin 144 | Result := FAttributes[0]; 145 | end; 146 | 147 | { TForm1 } 148 | 149 | procedure TForm1.FormCreate(Sender: TObject); 150 | begin 151 | FGrammar := TCGTGrammar.Create; 152 | end; 153 | 154 | procedure TForm1.FormDestroy(Sender: TObject); 155 | begin 156 | FGrammar.Free; 157 | end; 158 | 159 | function TForm1.LeafNode(const AToken: TToken): TTreeNode; 160 | begin 161 | Result := TreeView1.Items.Add(nil, AToken.Symbol^.Name); 162 | end; 163 | 164 | function TForm1.ReduceNode(const Produces: TGrammarSymbol; Consumes: specialize 165 | TArray<TTreeNode>): TTreeNode; 166 | var 167 | Node: TTreeNode; 168 | begin 169 | Result := TreeView1.Items.Add(nil, Produces.Name); 170 | for Node in Consumes do 171 | MoveToParent(Node, Result); 172 | end; 173 | 174 | procedure TForm1.MoveToParent(Node, NewParent: TTreeNode); 175 | var 176 | NewChild: TTreeNode; 177 | begin 178 | NewChild := TreeView1.Items.AddChild(NewParent, Node.Text); 179 | while Node.HasChildren do 180 | MoveToParent(Node.Items[0], NewChild); 181 | Node.Free; 182 | end; 183 | 184 | procedure TForm1.Button1Click(Sender: TObject); 185 | var 186 | Highlighter: TSynCustomHighlighter; 187 | begin 188 | Highlighter := SynEdit1.Highlighter; 189 | SynEdit1.Highlighter := nil; 190 | Highlighter.Free; 191 | if FileNameEdit1.FileName = 'Integrated' then 192 | begin 193 | FGrammar.Free; 194 | FGrammar := TSimple.Create; 195 | end 196 | else 197 | FGrammar.LoadFromFile(FileNameEdit1.FileName); 198 | SynEdit1.Highlighter := TGrammarHighlighter.WithDFA(SynEdit1, FGrammar); 199 | TreeView1.Items.BeginUpdate; 200 | try 201 | TreeView1.Items.Clear; 202 | FGrammar.ParseString(SynEdit1.Text, TBuildParseTreeEvent(@ReduceNode), TBuildParseTreeLeafEvent(@LeafNode)); 203 | finally 204 | TreeView1.Items.EndUpdate; 205 | end; 206 | end; 207 | 208 | procedure TForm1.Button2Click(Sender: TObject); 209 | begin 210 | if OpenDialog1.Execute then 211 | SynEdit1.Lines.LoadFromFile(OpenDialog1.FileName); 212 | end; 213 | 214 | end. 215 | 216 | -------------------------------------------------------------------------------- /src/parser.pas: -------------------------------------------------------------------------------- 1 | unit parser; 2 | 3 | {$mode ObjFPC}{$H+} 4 | {$ModeSwitch advancedrecords} 5 | {$TypedAddress On} 6 | 7 | interface 8 | 9 | uses 10 | SysUtils, Classes, lexer, Generics.Collections; 11 | 12 | type 13 | EParserNotFinished = class(Exception); 14 | EUnknownSymbolException = class(Exception); 15 | EGotoNotFoundError = class(Exception); 16 | 17 | { EParserError } 18 | 19 | EParserError = class(Exception) 20 | public type 21 | TParseStackData = array of TObject; 22 | private 23 | FLookAhead: TToken; 24 | FStackData: TParseStackData; 25 | FFreeNodes: Boolean; 26 | public 27 | constructor Create(const Msg: String; const AToken: TToken; 28 | const AStackData: TParseStackData; 29 | FreeOnDestroy: Boolean); 30 | destructor Destroy; override; 31 | 32 | property LookAhead: TToken read FLookAhead; 33 | property StackData: TParseStackData read FStackData write FStackData; 34 | property FreeNodes: boolean read FFreeNodes write FFreeNodes; 35 | end; 36 | 37 | { ERuleNotApplicableError } 38 | 39 | ERuleNotApplicableError = class(EParserError) 40 | private 41 | FRuleIndex: Integer; 42 | public 43 | constructor Create(const Msg: String; const AToken: TToken; 44 | const AStackData: TParseStackData; FreeOnDestroy: Boolean; ARule: Integer); 45 | 46 | property RuleIndex: Integer read FRuleIndex; 47 | end; 48 | 49 | TLRActionType = (atShift = 1, atReduce, atGoto, atAccept); 50 | TLRTransition = record 51 | LookAhead: Integer; 52 | Action: TLRActionType; 53 | Value: Integer; 54 | end; 55 | TLRTransitions = array of TLRTransition; 56 | 57 | TConsumes = array of Integer; 58 | 59 | TLRRule = record 60 | Produces: Integer; 61 | Consumes: TConsumes; 62 | end; 63 | TLRRules = class(specialize TList<TLRRule>); 64 | 65 | TAcceptSymbols = class(specialize THashSet<Integer>); 66 | TActionTable = class(specialize THashMap<Integer, Integer>); 67 | 68 | { TLRState } 69 | 70 | TLRState = class 71 | private 72 | FAcceptSymbols: TAcceptSymbols; 73 | FShiftTable: TActionTable; 74 | FReduceTable: TActionTable; 75 | FGotoTable: TActionTable; 76 | public 77 | constructor Create(ATransitions: TLRTransitions); 78 | destructor Destroy; override; 79 | 80 | property AcceptSymbols: TAcceptSymbols read FAcceptSymbols; 81 | property ShiftTable: TActionTable read FShiftTable; 82 | property ReduceTable: TActionTable read FReduceTable; 83 | property GotoTable: TActionTable read FGotoTable; 84 | end; 85 | TLRStates = class(specialize TObjectList<TLRState>); 86 | 87 | // Using Runtime (Inheritance based TObject) Polymorhism 88 | // Reason: FPC won't allow me to make this generic 89 | TLRStackItem = record 90 | State: Integer; 91 | Symbol: Integer; 92 | Data: TObject; 93 | end; 94 | 95 | TLRParserStack = class(specialize TList<TLRStackItem>); 96 | TParseTreeNodes = array of TObject; 97 | 98 | TBuildParseTreeEvent = function(const Produces: TGrammarSymbol; Consumes: TParseTreeNodes): TObject of object; 99 | TBuildParseTreeLeafEvent = function(const AToken: TToken): TObject of object; 100 | 101 | { TLALRParser } 102 | 103 | TLALRParser = class 104 | private 105 | FStates: TLRStates; 106 | FRules: TLRRules; 107 | FInitialState: Integer; 108 | 109 | FBuildNode: TBuildParseTreeEvent; 110 | FBuildLeaf: TBuildParseTreeLeafEvent; 111 | FFreeNodes: Boolean; 112 | 113 | FStack: TLRParserStack; 114 | 115 | function PopStack(Count: SizeInt): TParseTreeNodes; 116 | function ParseTreeError(const Message: String; const LookAhead: TToken): EParserError; 117 | function RuleNotApplicableError(const Message: String; const LookAhead: TToken; ARule: Integer): ERuleNotApplicableError; 118 | public 119 | constructor Create; 120 | destructor Destroy; override; 121 | 122 | procedure AddState(AState: TLRState); inline; 123 | procedure AddRule(const ARule: TLRRule); inline; 124 | 125 | procedure SetInitialState(AState: Integer); inline; 126 | 127 | procedure Reset; 128 | 129 | function Step(LookAhead: TToken; const SymbolTable: TGrammarSymbolTable 130 | ): TLRActionType; 131 | 132 | function ExtractResult: TObject; 133 | 134 | property BuildNode: TBuildParseTreeEvent read FBuildNode write FBuildNode; 135 | property BuildLeaf: TBuildParseTreeLeafEvent read FBuildLeaf write FBuildLeaf; 136 | property FreeNodes: Boolean read FFreeNodes write FFreeNodes; 137 | property States: TLRStates read FStates; 138 | property Rules: TLRRules read FRules; 139 | end; 140 | 141 | function LRTransition(LookAhead: Integer; Action: TLRActionType; Value: Integer): TLRTransition; inline; 142 | function LRRule(Produces: Integer; const Consumes: TConsumes): TLRRule; inline; 143 | implementation 144 | 145 | function LRTransition(LookAhead: Integer; Action: TLRActionType; Value: Integer 146 | ): TLRTransition; 147 | begin 148 | Result.Action := Action; 149 | Result.LookAhead := LookAhead; 150 | Result.Value := Value; 151 | end; 152 | 153 | function LRRule(Produces: Integer; const Consumes: TConsumes): TLRRule; 154 | begin 155 | Result.Consumes := Consumes; 156 | Result.Produces := Produces; 157 | end; 158 | 159 | { ERuleNotApplicableError } 160 | 161 | constructor ERuleNotApplicableError.Create(const Msg: String; 162 | const AToken: TToken; const AStackData: TParseStackData; 163 | FreeOnDestroy: Boolean; ARule: Integer); 164 | begin 165 | inherited Create(Msg, AToken, AStackData, FreeOnDestroy); 166 | FRuleIndex := ARule; 167 | end; 168 | 169 | { EParserError } 170 | 171 | constructor EParserError.Create(const Msg: String; const AToken: TToken; 172 | const AStackData: TParseStackData; FreeOnDestroy: Boolean); 173 | begin 174 | inherited Create(Msg); 175 | FStackData := AStackData; 176 | FFreeNodes := FreeOnDestroy; 177 | FLookAhead := AToken; 178 | end; 179 | 180 | destructor EParserError.Destroy; 181 | var 182 | i: Integer; 183 | begin 184 | if FFreeNodes then 185 | for i:=0 to Length(FStackData) - 1 do 186 | FStackData[i].Free; 187 | inherited Destroy; 188 | end; 189 | 190 | { TLALRParser } 191 | 192 | function TLALRParser.PopStack(Count: SizeInt): TParseTreeNodes; 193 | var 194 | i: SizeInt; 195 | begin 196 | Result := []; 197 | if Count > FStack.Count then 198 | Count := FStack.Count; 199 | if Count < 0 then 200 | Count := 0; 201 | SetLength(Result, Count); 202 | for i:=Count - 1 downto 0 do 203 | begin 204 | Result[i] := FStack.Last.Data; 205 | FStack.Delete(FStack.Count - 1); 206 | end; 207 | end; 208 | 209 | function TLALRParser.ParseTreeError(const Message: String; 210 | const LookAhead: TToken): EParserError; 211 | begin 212 | Result := EParserError.Create(Message, LookAhead, PopStack(FStack.Count), FFreeNodes); 213 | end; 214 | 215 | function TLALRParser.RuleNotApplicableError(const Message: String; 216 | const LookAhead: TToken; ARule: Integer): ERuleNotApplicableError; 217 | begin 218 | Result := ERuleNotApplicableError.Create(Message, LookAhead, PopStack(FStack.Count), FFreeNodes, ARule); 219 | end; 220 | 221 | constructor TLALRParser.Create; 222 | begin 223 | inherited Create; 224 | FStates := TLRStates.Create; 225 | FRules := TLRRules.Create; 226 | FInitialState := 0; 227 | FBuildNode := nil; 228 | FFreeNodes := True; 229 | 230 | FStack := TLRParserStack.Create; 231 | end; 232 | 233 | destructor TLALRParser.Destroy; 234 | begin 235 | FStates.Free; 236 | FRules.Free; 237 | Reset; 238 | FStack.Free; 239 | inherited Destroy; 240 | end; 241 | 242 | procedure TLALRParser.AddState(AState: TLRState); 243 | begin 244 | FStates.Add(AState); 245 | end; 246 | 247 | procedure TLALRParser.AddRule(const ARule: TLRRule); 248 | begin 249 | FRules.Add(ARule); 250 | end; 251 | 252 | procedure TLALRParser.SetInitialState(AState: Integer); 253 | begin 254 | FInitialState := AState; 255 | end; 256 | 257 | procedure TLALRParser.Reset; 258 | begin 259 | while FStack.Count > 0 do 260 | begin 261 | if FFreeNodes then 262 | FStack.Last.Data.Free; 263 | FStack.Delete(FStack.Count - 1); 264 | end; 265 | end; 266 | 267 | function StackItem(State: Integer; Symbol: Integer; const Data: TObject): TLRStackItem; inline; 268 | begin 269 | Result.State := State; 270 | Result.Data := Data; 271 | Result.Symbol := Symbol; 272 | end; 273 | 274 | function TLALRParser.Step(LookAhead: TToken; const SymbolTable: TGrammarSymbolTable): TLRActionType; 275 | 276 | var 277 | CurrentState, NewTop: TLRState; 278 | NextState: Integer; 279 | RuleIndex, i: Integer; 280 | Rule: TLRRule; 281 | Consumes: TParseTreeNodes; 282 | NewNode: TObject; 283 | begin 284 | if not Assigned(LookAhead.Symbol) then 285 | raise EUnknownSymbolException.Create('Unknown symbol for lookahead token: ' + LookAhead.Value); 286 | 287 | if FStack.Count = 0 then 288 | CurrentState := FStates[FInitialState] 289 | else 290 | CurrentState := FStates[FStack.Last.State]; 291 | 292 | if CurrentState.FAcceptSymbols.Contains(LookAhead.Symbol^.Index) then 293 | Exit(atAccept); 294 | 295 | if CurrentState.FShiftTable.TryGetValue(LookAhead.Symbol^.Index, NextState) then 296 | begin 297 | if Assigned(BuildLeaf) then 298 | NewNode := BuildLeaf(LookAhead) 299 | else 300 | NewNode := nil; 301 | FStack.Add(StackItem(NextState, LookAhead.Symbol^.Index, NewNode)); 302 | Exit(atShift); 303 | end; 304 | 305 | if not CurrentState.FReduceTable.TryGetValue(LookAhead.Symbol^.Index, RuleIndex) then 306 | raise ParseTreeError('No action found for Look Ahead: ' + LookAhead.Symbol^.Name, LookAhead); 307 | 308 | 309 | Rule := FRules[RuleIndex]; 310 | 311 | if FStack.Count < Length(Rule.Consumes) then 312 | raise RuleNotApplicableError('Not enough elements on the stack' , LookAhead, RuleIndex); 313 | 314 | for i:=0 to Length(Rule.Consumes) - 1 do 315 | if FStack[FStack.Count - Length(Rule.Consumes) + i].Symbol <> Rule.Consumes[i] then 316 | raise RuleNotApplicableError('Rule Symbols do not match Symbols, expected: ' 317 | + SymbolTable[Rule.Consumes[i]].Name + ' got: ' 318 | + SymbolTable[FStack[FStack.Count - Length(Rule.Consumes) + i].Symbol].Name, 319 | LookAhead, RuleIndex); 320 | 321 | Consumes := PopStack(Length(Rule.Consumes)); 322 | if Assigned(BuildNode) then 323 | NewNode := BuildNode(SymbolTable[Rule.Produces], Consumes) 324 | else 325 | NewNode := nil; 326 | 327 | if FStack.Count = 0 then 328 | NewTop := FStates[FInitialState] 329 | else 330 | NewTop := FStates[FStack.Last.State]; 331 | 332 | if not NewTop.GotoTable.TryGetValue(Rule.Produces, NextState) then 333 | raise EGotoNotFoundError.Create('No entry in goto table for ' + Rule.Produces.ToString); 334 | 335 | FStack.Add(StackItem(NextState, Rule.Produces, NewNode)); 336 | Result := atReduce; 337 | end; 338 | 339 | function TLALRParser.ExtractResult: TObject; 340 | begin 341 | if FStack.Count <> 1 then 342 | raise EParserNotFinished.Create('Parser not finished with an ACCEPT'); 343 | Result := FStack.Last.Data; 344 | FStack.Clear; 345 | end; 346 | 347 | { TLRState } 348 | 349 | constructor TLRState.Create(ATransitions: TLRTransitions); 350 | var 351 | Transition: TLRTransition; 352 | begin 353 | inherited Create; 354 | FAcceptSymbols := TAcceptSymbols.Create; 355 | FShiftTable := TActionTable.Create; 356 | FReduceTable := TActionTable.Create; 357 | FGotoTable := TActionTable.Create; 358 | 359 | for Transition in ATransitions do 360 | if Transition.Action = atShift then 361 | FShiftTable.Add(Transition.LookAhead, Transition.Value) 362 | else if Transition.Action = atReduce then 363 | FReduceTable.Add(Transition.LookAhead, Transition.Value) 364 | else if Transition.Action = atGoto then 365 | FGotoTable.Add(Transition.LookAhead, Transition.Value) 366 | else if Transition.Action = atAccept then 367 | FAcceptSymbols.Add(Transition.LookAhead); 368 | end; 369 | 370 | destructor TLRState.Destroy; 371 | begin 372 | FAcceptSymbols.Free; 373 | FShiftTable.Free; 374 | FReduceTable.Free; 375 | FGotoTable.Free; 376 | inherited Destroy; 377 | end; 378 | 379 | end. 380 | 381 | -------------------------------------------------------------------------------- /example/unit1.lfm: -------------------------------------------------------------------------------- 1 | object Form1: TForm1 2 | Left = 684 3 | Height = 691 4 | Top = 250 5 | Width = 872 6 | Caption = 'Form1' 7 | ClientHeight = 691 8 | ClientWidth = 872 9 | DesignTimePPI = 144 10 | OnCreate = FormCreate 11 | OnDestroy = FormDestroy 12 | object TreeView1: TTreeView 13 | Left = 0 14 | Height = 659 15 | Top = 32 16 | Width = 182 17 | Align = alLeft 18 | ParentFont = False 19 | TabOrder = 1 20 | end 21 | inline SynEdit1: TSynEdit 22 | Left = 190 23 | Height = 659 24 | Top = 32 25 | Width = 682 26 | Align = alClient 27 | Font.Height = -24 28 | Font.Name = 'Consolas' 29 | Font.Pitch = fpFixed 30 | Font.Quality = fqNonAntialiased 31 | ParentColor = False 32 | ParentFont = False 33 | TabOrder = 0 34 | Gutter.Width = 87 35 | Gutter.MouseActions = <> 36 | RightGutter.Width = 0 37 | RightGutter.MouseActions = <> 38 | Keystrokes = < 39 | item 40 | Command = ecUp 41 | ShortCut = 38 42 | end 43 | item 44 | Command = ecSelUp 45 | ShortCut = 8230 46 | end 47 | item 48 | Command = ecScrollUp 49 | ShortCut = 16422 50 | end 51 | item 52 | Command = ecDown 53 | ShortCut = 40 54 | end 55 | item 56 | Command = ecSelDown 57 | ShortCut = 8232 58 | end 59 | item 60 | Command = ecScrollDown 61 | ShortCut = 16424 62 | end 63 | item 64 | Command = ecLeft 65 | ShortCut = 37 66 | end 67 | item 68 | Command = ecSelLeft 69 | ShortCut = 8229 70 | end 71 | item 72 | Command = ecWordLeft 73 | ShortCut = 16421 74 | end 75 | item 76 | Command = ecSelWordLeft 77 | ShortCut = 24613 78 | end 79 | item 80 | Command = ecRight 81 | ShortCut = 39 82 | end 83 | item 84 | Command = ecSelRight 85 | ShortCut = 8231 86 | end 87 | item 88 | Command = ecWordRight 89 | ShortCut = 16423 90 | end 91 | item 92 | Command = ecSelWordRight 93 | ShortCut = 24615 94 | end 95 | item 96 | Command = ecPageDown 97 | ShortCut = 34 98 | end 99 | item 100 | Command = ecSelPageDown 101 | ShortCut = 8226 102 | end 103 | item 104 | Command = ecPageBottom 105 | ShortCut = 16418 106 | end 107 | item 108 | Command = ecSelPageBottom 109 | ShortCut = 24610 110 | end 111 | item 112 | Command = ecPageUp 113 | ShortCut = 33 114 | end 115 | item 116 | Command = ecSelPageUp 117 | ShortCut = 8225 118 | end 119 | item 120 | Command = ecPageTop 121 | ShortCut = 16417 122 | end 123 | item 124 | Command = ecSelPageTop 125 | ShortCut = 24609 126 | end 127 | item 128 | Command = ecLineStart 129 | ShortCut = 36 130 | end 131 | item 132 | Command = ecSelLineStart 133 | ShortCut = 8228 134 | end 135 | item 136 | Command = ecEditorTop 137 | ShortCut = 16420 138 | end 139 | item 140 | Command = ecSelEditorTop 141 | ShortCut = 24612 142 | end 143 | item 144 | Command = ecLineEnd 145 | ShortCut = 35 146 | end 147 | item 148 | Command = ecSelLineEnd 149 | ShortCut = 8227 150 | end 151 | item 152 | Command = ecEditorBottom 153 | ShortCut = 16419 154 | end 155 | item 156 | Command = ecSelEditorBottom 157 | ShortCut = 24611 158 | end 159 | item 160 | Command = ecToggleMode 161 | ShortCut = 45 162 | end 163 | item 164 | Command = ecCopy 165 | ShortCut = 16429 166 | end 167 | item 168 | Command = ecPaste 169 | ShortCut = 8237 170 | end 171 | item 172 | Command = ecDeleteChar 173 | ShortCut = 46 174 | end 175 | item 176 | Command = ecCut 177 | ShortCut = 8238 178 | end 179 | item 180 | Command = ecDeleteLastChar 181 | ShortCut = 8 182 | end 183 | item 184 | Command = ecDeleteLastChar 185 | ShortCut = 8200 186 | end 187 | item 188 | Command = ecDeleteLastWord 189 | ShortCut = 16392 190 | end 191 | item 192 | Command = ecUndo 193 | ShortCut = 32776 194 | end 195 | item 196 | Command = ecRedo 197 | ShortCut = 40968 198 | end 199 | item 200 | Command = ecLineBreak 201 | ShortCut = 13 202 | end 203 | item 204 | Command = ecSelectAll 205 | ShortCut = 16449 206 | end 207 | item 208 | Command = ecCopy 209 | ShortCut = 16451 210 | end 211 | item 212 | Command = ecBlockIndent 213 | ShortCut = 24649 214 | end 215 | item 216 | Command = ecLineBreak 217 | ShortCut = 16461 218 | end 219 | item 220 | Command = ecInsertLine 221 | ShortCut = 16462 222 | end 223 | item 224 | Command = ecDeleteWord 225 | ShortCut = 16468 226 | end 227 | item 228 | Command = ecBlockUnindent 229 | ShortCut = 24661 230 | end 231 | item 232 | Command = ecPaste 233 | ShortCut = 16470 234 | end 235 | item 236 | Command = ecCut 237 | ShortCut = 16472 238 | end 239 | item 240 | Command = ecDeleteLine 241 | ShortCut = 16473 242 | end 243 | item 244 | Command = ecDeleteEOL 245 | ShortCut = 24665 246 | end 247 | item 248 | Command = ecUndo 249 | ShortCut = 16474 250 | end 251 | item 252 | Command = ecRedo 253 | ShortCut = 24666 254 | end 255 | item 256 | Command = ecGotoMarker0 257 | ShortCut = 16432 258 | end 259 | item 260 | Command = ecGotoMarker1 261 | ShortCut = 16433 262 | end 263 | item 264 | Command = ecGotoMarker2 265 | ShortCut = 16434 266 | end 267 | item 268 | Command = ecGotoMarker3 269 | ShortCut = 16435 270 | end 271 | item 272 | Command = ecGotoMarker4 273 | ShortCut = 16436 274 | end 275 | item 276 | Command = ecGotoMarker5 277 | ShortCut = 16437 278 | end 279 | item 280 | Command = ecGotoMarker6 281 | ShortCut = 16438 282 | end 283 | item 284 | Command = ecGotoMarker7 285 | ShortCut = 16439 286 | end 287 | item 288 | Command = ecGotoMarker8 289 | ShortCut = 16440 290 | end 291 | item 292 | Command = ecGotoMarker9 293 | ShortCut = 16441 294 | end 295 | item 296 | Command = ecSetMarker0 297 | ShortCut = 24624 298 | end 299 | item 300 | Command = ecSetMarker1 301 | ShortCut = 24625 302 | end 303 | item 304 | Command = ecSetMarker2 305 | ShortCut = 24626 306 | end 307 | item 308 | Command = ecSetMarker3 309 | ShortCut = 24627 310 | end 311 | item 312 | Command = ecSetMarker4 313 | ShortCut = 24628 314 | end 315 | item 316 | Command = ecSetMarker5 317 | ShortCut = 24629 318 | end 319 | item 320 | Command = ecSetMarker6 321 | ShortCut = 24630 322 | end 323 | item 324 | Command = ecSetMarker7 325 | ShortCut = 24631 326 | end 327 | item 328 | Command = ecSetMarker8 329 | ShortCut = 24632 330 | end 331 | item 332 | Command = ecSetMarker9 333 | ShortCut = 24633 334 | end 335 | item 336 | Command = EcFoldLevel1 337 | ShortCut = 41009 338 | end 339 | item 340 | Command = EcFoldLevel2 341 | ShortCut = 41010 342 | end 343 | item 344 | Command = EcFoldLevel3 345 | ShortCut = 41011 346 | end 347 | item 348 | Command = EcFoldLevel4 349 | ShortCut = 41012 350 | end 351 | item 352 | Command = EcFoldLevel5 353 | ShortCut = 41013 354 | end 355 | item 356 | Command = EcFoldLevel6 357 | ShortCut = 41014 358 | end 359 | item 360 | Command = EcFoldLevel7 361 | ShortCut = 41015 362 | end 363 | item 364 | Command = EcFoldLevel8 365 | ShortCut = 41016 366 | end 367 | item 368 | Command = EcFoldLevel9 369 | ShortCut = 41017 370 | end 371 | item 372 | Command = EcFoldLevel0 373 | ShortCut = 41008 374 | end 375 | item 376 | Command = EcFoldCurrent 377 | ShortCut = 41005 378 | end 379 | item 380 | Command = EcUnFoldCurrent 381 | ShortCut = 41003 382 | end 383 | item 384 | Command = EcToggleMarkupWord 385 | ShortCut = 32845 386 | end 387 | item 388 | Command = ecNormalSelect 389 | ShortCut = 24654 390 | end 391 | item 392 | Command = ecColumnSelect 393 | ShortCut = 24643 394 | end 395 | item 396 | Command = ecLineSelect 397 | ShortCut = 24652 398 | end 399 | item 400 | Command = ecTab 401 | ShortCut = 9 402 | end 403 | item 404 | Command = ecShiftTab 405 | ShortCut = 8201 406 | end 407 | item 408 | Command = ecMatchBracket 409 | ShortCut = 24642 410 | end 411 | item 412 | Command = ecColSelUp 413 | ShortCut = 40998 414 | end 415 | item 416 | Command = ecColSelDown 417 | ShortCut = 41000 418 | end 419 | item 420 | Command = ecColSelLeft 421 | ShortCut = 40997 422 | end 423 | item 424 | Command = ecColSelRight 425 | ShortCut = 40999 426 | end 427 | item 428 | Command = ecColSelPageDown 429 | ShortCut = 40994 430 | end 431 | item 432 | Command = ecColSelPageBottom 433 | ShortCut = 57378 434 | end 435 | item 436 | Command = ecColSelPageUp 437 | ShortCut = 40993 438 | end 439 | item 440 | Command = ecColSelPageTop 441 | ShortCut = 57377 442 | end 443 | item 444 | Command = ecColSelLineStart 445 | ShortCut = 40996 446 | end 447 | item 448 | Command = ecColSelLineEnd 449 | ShortCut = 40995 450 | end 451 | item 452 | Command = ecColSelEditorTop 453 | ShortCut = 57380 454 | end 455 | item 456 | Command = ecColSelEditorBottom 457 | ShortCut = 57379 458 | end> 459 | MouseActions = <> 460 | MouseTextActions = <> 461 | MouseSelActions = <> 462 | Lines.Strings = ( 463 | 'a := 3;' 464 | 'b := 24;' 465 | '' 466 | 'while a < b do // Comment' 467 | ' a := a + ((5 * b) / (2 * 3));' 468 | 'end;' 469 | '' 470 | 'print(a);' 471 | ) 472 | VisibleSpecialChars = [vscSpace, vscTabAtLast] 473 | ReadOnly = True 474 | SelectedColor.BackPriority = 50 475 | SelectedColor.ForePriority = 50 476 | SelectedColor.FramePriority = 50 477 | SelectedColor.BoldPriority = 50 478 | SelectedColor.ItalicPriority = 50 479 | SelectedColor.UnderlinePriority = 50 480 | SelectedColor.StrikeOutPriority = 50 481 | BracketHighlightStyle = sbhsBoth 482 | BracketMatchColor.Background = clNone 483 | BracketMatchColor.Foreground = clNone 484 | BracketMatchColor.Style = [fsBold] 485 | FoldedCodeColor.Background = clNone 486 | FoldedCodeColor.Foreground = clGray 487 | FoldedCodeColor.FrameColor = clGray 488 | MouseLinkColor.Background = clNone 489 | MouseLinkColor.Foreground = clBlue 490 | LineHighlightColor.Background = clNone 491 | LineHighlightColor.Foreground = clNone 492 | inline SynLeftGutterPartList1: TSynGutterPartList 493 | object SynGutterMarks1: TSynGutterMarks 494 | Width = 36 495 | MouseActions = <> 496 | end 497 | object SynGutterLineNumber1: TSynGutterLineNumber 498 | Width = 27 499 | MouseActions = <> 500 | MarkupInfo.Background = clBtnFace 501 | MarkupInfo.Foreground = clNone 502 | DigitCount = 2 503 | ShowOnlyLineNumbersMultiplesOf = 1 504 | ZeroStart = False 505 | LeadingZeros = False 506 | end 507 | object SynGutterChanges1: TSynGutterChanges 508 | Width = 6 509 | MouseActions = <> 510 | ModifiedColor = 59900 511 | SavedColor = clGreen 512 | end 513 | object SynGutterSeparator1: TSynGutterSeparator 514 | Width = 3 515 | MouseActions = <> 516 | MarkupInfo.Background = clWhite 517 | MarkupInfo.Foreground = clGray 518 | end 519 | object SynGutterCodeFolding1: TSynGutterCodeFolding 520 | Width = 15 521 | MouseActions = <> 522 | MarkupInfo.Background = clNone 523 | MarkupInfo.Foreground = clGray 524 | MouseActionsExpanded = <> 525 | MouseActionsCollapsed = <> 526 | end 527 | end 528 | end 529 | object Panel1: TPanel 530 | Left = 0 531 | Height = 32 532 | Top = 0 533 | Width = 872 534 | Align = alTop 535 | BevelOuter = bvNone 536 | ClientHeight = 32 537 | ClientWidth = 872 538 | TabOrder = 2 539 | object FileNameEdit1: TFileNameEdit 540 | Left = 0 541 | Height = 32 542 | Top = 0 543 | Width = 759 544 | FileName = 'Integrated' 545 | Filter = 'GOLD Grammar Tables|*.egt;*.cgt' 546 | FilterIndex = 0 547 | HideDirectories = False 548 | ButtonWidth = 34 549 | NumGlyphs = 1 550 | Align = alClient 551 | MaxLength = 0 552 | TabOrder = 0 553 | Text = 'Integrated' 554 | end 555 | object Button1: TButton 556 | Left = 759 557 | Height = 32 558 | Top = 0 559 | Width = 113 560 | Align = alRight 561 | Caption = 'Parse' 562 | OnClick = Button1Click 563 | TabOrder = 1 564 | end 565 | end 566 | object Splitter1: TSplitter 567 | Left = 182 568 | Height = 659 569 | Top = 32 570 | Width = 8 571 | end 572 | object Button2: TButton 573 | Left = 728 574 | Height = 38 575 | Top = 624 576 | Width = 113 577 | Caption = 'File' 578 | OnClick = Button2Click 579 | TabOrder = 4 580 | end 581 | object OpenDialog1: TOpenDialog 582 | Left = 32 583 | Top = 32 584 | end 585 | end 586 | -------------------------------------------------------------------------------- /src/cgtgrammar.pas: -------------------------------------------------------------------------------- 1 | unit cgtgrammar; 2 | 3 | {$mode ObjFPC}{$H+} 4 | {$ModeSwitch arrayoperators} 5 | {$TypedAddress On} 6 | 7 | interface 8 | 9 | uses 10 | Classes, SysUtils, lexer, parser, Generics.Collections; 11 | 12 | type 13 | TFieldType = (ftBoolean = 'B', 14 | ftEmpty = 'E', 15 | ftInteger = 'I', 16 | ftMulti = 'M', 17 | ftString = 'S', 18 | ftChar = 'b'); 19 | 20 | { TCGTReader } 21 | 22 | TCGTReader = class 23 | private 24 | FOwnsStream: Boolean; 25 | FStream: TStream; 26 | FRemainingSize: Integer; 27 | public 28 | constructor Create(AStream: TStream; OwnsStream: Boolean = True); 29 | destructor Destroy; override; 30 | 31 | function ReadRawString: String; 32 | 33 | function ReadInteger: Word; 34 | function ReadBoolean: Boolean; 35 | function ReadString: String; 36 | function ReadChar: Char; 37 | function StartRecord: Integer; 38 | function SkipField: TFieldType; 39 | 40 | function RecordFinished: Boolean; inline; 41 | end; 42 | 43 | TRecordType = (rtCharset = 'C', 44 | rtDFAState = 'D', 45 | rtInitialStates = 'I', 46 | rtLRState = 'L', 47 | rtParameter = 'P', 48 | rtRule = 'R', 49 | rtSymbol = 'S', 50 | rtCountsV1 = 'T', 51 | rtCharRanges = 'c', 52 | rtGroup = 'g', 53 | rtProperty = 'p', 54 | rtCountsV5 = 't'); 55 | 56 | TGrammarVersion = (gv1, gv5); 57 | TParameter = class(specialize THashMap<string, string>); 58 | 59 | { TCGTGrammar } 60 | 61 | TCGTGrammar = class 62 | protected 63 | FVersion: TGrammarVersion; 64 | FSymbols: TGrammarSymbolTable; 65 | FParameter: TParameter; 66 | FDFA: TDFALexer; 67 | FLALR: TLALRParser; 68 | 69 | procedure Clear; 70 | 71 | private 72 | function ReadHeader(Reader: TCGTReader): TGrammarVersion; 73 | function LexNextUnskippable(var Iterator: TUTF8Iterator): TToken; inline; 74 | public 75 | constructor Create; 76 | destructor Destroy; override; 77 | 78 | procedure LoadFromFile(const CGTFile: string); 79 | 80 | procedure Prepare(SymbolList: TGrammarSymbolList); 81 | 82 | function LexToken(var Iterator: TUTF8Iterator): TToken; inline; 83 | function ParseString(const AString: String; BuildNode: TBuildParseTreeEvent; 84 | BuildLeaf: TBuildParseTreeLeafEvent; 85 | FreeNodesOnReset: Boolean = True): TObject; 86 | 87 | property Version: TGrammarVersion read FVersion; 88 | property Symbols: TGrammarSymbolTable read FSymbols; 89 | property DFA: TDFALexer read FDFA; 90 | property LALR: TLALRParser read FLALR; 91 | end; 92 | 93 | implementation 94 | 95 | { TCGTReader } 96 | 97 | constructor TCGTReader.Create(AStream: TStream; OwnsStream: Boolean); 98 | begin 99 | inherited Create; 100 | FStream := AStream; 101 | FOwnsStream := OwnsStream; 102 | end; 103 | 104 | destructor TCGTReader.Destroy; 105 | begin 106 | if FOwnsStream then 107 | FStream.Free; 108 | inherited Destroy; 109 | end; 110 | 111 | function TCGTReader.ReadRawString: String; 112 | var 113 | WString: WideString; 114 | NextChar: WideChar = #00; 115 | begin 116 | WString := ''; 117 | repeat 118 | if FStream.Read(NextChar, SizeOf(NextChar)) < sizeof(NextChar) then 119 | raise EReadError.Create('Unexpected EOF'); 120 | if NextChar <> #0000 then 121 | WString += NextChar; 122 | until NextChar = #0000; 123 | Result := UTF8Encode(WString); 124 | end; 125 | 126 | function TCGTReader.ReadInteger: Word; 127 | var 128 | FieldType: TFieldType = ftEmpty; 129 | begin 130 | Result := 0; 131 | if FStream.Read(FieldType, 1) < 1 then 132 | raise EReadError.Create('Unexpected EOF'); 133 | if FieldType <> ftInteger then 134 | raise EReadError.Create('Expected Integer got ' + char(FieldType)); 135 | if FStream.Read(Result, SizeOf(Result)) < SizeOf(Result) then 136 | raise EReadError.Create('Unexpected EOF'); 137 | Dec(FRemainingSize); 138 | end; 139 | 140 | function TCGTReader.ReadBoolean: Boolean; 141 | var 142 | FieldType: TFieldType = ftEmpty; 143 | IntVal: Byte = 0; 144 | begin 145 | if FStream.Read(FieldType, 1) < 1 then 146 | raise EReadError.Create('Unexpected EOF'); 147 | if FieldType <> ftBoolean then 148 | raise EReadError.Create('Expected Boolean got ' + char(FieldType)); 149 | if FStream.Read(IntVal, SizeOf(IntVal)) < SizeOf(IntVal) then 150 | raise EReadError.Create('Unexpected EOF'); 151 | Result := IntVal = 1; 152 | Dec(FRemainingSize); 153 | end; 154 | 155 | function TCGTReader.ReadString: String; 156 | var 157 | FieldType: TFieldType = ftEmpty; 158 | begin 159 | if FStream.Read(FieldType, 1) < 1 then 160 | raise EReadError.Create('Unexpected EOF'); 161 | if FieldType <> ftString then 162 | raise EReadError.Create('Expected String got ' + char(FieldType)); 163 | Result := ReadRawString; 164 | Dec(FRemainingSize); 165 | end; 166 | 167 | function TCGTReader.ReadChar: Char; 168 | var 169 | FieldType: TFieldType = ftEmpty; 170 | begin 171 | Result := #00; 172 | if FStream.Read(FieldType, 1) < 1 then 173 | raise EReadError.Create('Unexpected EOF'); 174 | if FieldType <> ftChar then 175 | raise EReadError.Create('Expected Byte got ' + char(FieldType)); 176 | if FStream.Read(Result, SizeOf(Result)) < SizeOf(Result) then 177 | raise EReadError.Create('Unexpected EOF'); 178 | Dec(FRemainingSize); 179 | end; 180 | 181 | function TCGTReader.StartRecord: Integer; 182 | var 183 | FieldType: TFieldType = ftEmpty; 184 | WordValue: Word = 0; 185 | begin 186 | if FStream.Read(FieldType, 1) < 1 then 187 | Exit(-1); 188 | if FieldType <> ftMulti then 189 | raise EReadError.Create('Expected Multi got ' + char(FieldType)); 190 | if FStream.Read(WordValue, SizeOf(WordValue)) < SizeOf(WordValue) then 191 | raise EReadError.Create('Unexpected EOF'); 192 | FRemainingSize := WordValue; 193 | Result := WordValue; 194 | end; 195 | 196 | function TCGTReader.SkipField: TFieldType; 197 | var 198 | Dummy: Integer = 0; 199 | begin 200 | Result := ftEmpty; 201 | if FStream.Read(Result, 1) < 1 then 202 | raise EReadError.Create('Unexpected EOF'); 203 | case Result of 204 | ftInteger: 205 | if FStream.Read(Dummy, SizeOf(Word)) < SizeOf(Word) then 206 | raise EReadError.Create('Unexpected EOF'); 207 | ftBoolean, ftChar: 208 | if FStream.Read(Dummy, SizeOf(Byte)) < SizeOf(Byte) then 209 | raise EReadError.Create('Unexpected EOF'); 210 | ftString: 211 | ReadRawString; 212 | ftEmpty:; 213 | else 214 | raise EReadError.Create('Unknown Field Type'); 215 | end; 216 | Dec(FRemainingSize); 217 | end; 218 | 219 | function TCGTReader.RecordFinished: Boolean; 220 | begin 221 | if FRemainingSize < 0 then 222 | raise EReadError.Create('Overread Record'); 223 | Result := FRemainingSize = 0; 224 | end; 225 | 226 | { TCGTGrammar } 227 | 228 | procedure TCGTGrammar.Clear; 229 | begin 230 | FDFA.Free; 231 | FLALR.Free; 232 | FSymbols := []; 233 | FParameter.Clear; 234 | FDFA := TDFALexer.Create; 235 | FLALR := TLALRParser.Create; 236 | end; 237 | 238 | function TCGTGrammar.ReadHeader(Reader: TCGTReader): TGrammarVersion; 239 | var 240 | Header: String; 241 | begin 242 | Header := Reader.ReadRawString; 243 | if Header = 'GOLD Parser Tables/v1.0' then 244 | Result := gv1 245 | else if Header = 'GOLD Parser Tables/v5.0' then 246 | Result := gv5 247 | else 248 | raise EReadError.Create('Unknown file version'); 249 | end; 250 | 251 | function TCGTGrammar.LexNextUnskippable(var Iterator: TUTF8Iterator): TToken; 252 | begin 253 | repeat 254 | Result := FDFA.NextToken(Iterator, FSymbols); 255 | until Result.Symbol^.SymbolType <> stSkippable; 256 | end; 257 | 258 | constructor TCGTGrammar.Create; 259 | begin 260 | inherited Create; 261 | FSymbols := []; 262 | FDFA := TDFALexer.Create; 263 | FParameter := TParameter.Create; 264 | FLALR := TLALRParser.Create; 265 | end; 266 | 267 | destructor TCGTGrammar.Destroy; 268 | begin 269 | FDFA.Free; 270 | FLALR.Free; 271 | FParameter.Free; 272 | inherited Destroy; 273 | end; 274 | 275 | procedure ParseParameter(Reader: TCGTReader; Parameters: TParameter); 276 | var 277 | Name, Author, Version, About: String; 278 | StartSymbol: Word; 279 | CaseSensetive: Boolean; 280 | begin 281 | Name := Reader.ReadString; 282 | Version := Reader.ReadString; 283 | Author := Reader.ReadString; 284 | About := Reader.ReadString; 285 | CaseSensetive := Reader.ReadBoolean; 286 | StartSymbol := Reader.ReadInteger; 287 | 288 | Parameters.Add('Name', Name); 289 | Parameters.Add('Version', Version); 290 | Parameters.Add('Author', Author); 291 | Parameters.Add('About', About); 292 | Parameters.Add('Case Sensetive', CaseSensetive.ToString(True)); 293 | Parameters.Add('Start Symbol', StartSymbol.ToString); 294 | end; 295 | 296 | procedure ParseProperty(Reader: TCGTReader; Parameters: TParameter); 297 | var 298 | Key, Value: String; 299 | begin 300 | Reader.SkipField; // Index 301 | Key := Reader.ReadString; 302 | Value := Reader.ReadString; 303 | Parameters.Add(Key, Value); 304 | end; 305 | 306 | function ParseCharset(Reader: TCGTReader; NextIndex: Integer): TStaticCharset; 307 | var 308 | Index: Word; 309 | CharString: String; 310 | begin 311 | Index := Reader.ReadInteger; 312 | if Index <> NextIndex then 313 | raise EReadError.Create('Records out of order'); 314 | CharString := Reader.ReadString; 315 | Result := TStaticCharset.FromString(CharString); 316 | end; 317 | 318 | function ParseCharRanges(Reader: TCGTReader; NextIndex: Integer): TRangeCharset; 319 | var 320 | Index, CodePage, RangeEnd, RangeStart: Word; 321 | Ranges: TCodePointRanges; 322 | Count, i: Integer; 323 | begin 324 | Index := Reader.ReadInteger; 325 | if Index <> NextIndex then 326 | raise EReadError.Create('Records out of order'); 327 | CodePage := Reader.ReadInteger; 328 | Count := Reader.ReadInteger; 329 | Reader.SkipField; // Reserved 330 | 331 | Ranges := []; 332 | SetLength(Ranges, Count); 333 | for i:=0 to Count - 1 do 334 | begin 335 | RangeStart := Reader.ReadInteger; 336 | RangeEnd := Reader.ReadInteger; 337 | Ranges[i] := CodepointRange(RangeStart, RangeEnd); 338 | end; 339 | 340 | Result := TRangeCharset.FromArray(CodePage, Ranges); 341 | end; 342 | 343 | function ParseSymbol(Reader: TCGTReader; NextIndex: Integer): TGrammarSymbol; 344 | var 345 | Index: Word; 346 | Name: String; 347 | SymbolType: TSymbolType; 348 | begin 349 | Index := Reader.ReadInteger; 350 | if Index <> NextIndex then 351 | raise EReadError.Create('Records out of order'); 352 | Name := Reader.ReadString; 353 | SymbolType := TSymbolType(Reader.ReadInteger); 354 | Result := Symbol(index, Name, SymbolType); 355 | end; 356 | 357 | procedure ParseDFAState(Reader: TCGTReader; DFA: TDFALexer); 358 | var 359 | Index, FinalResult: Integer; 360 | Edges: TDFAEdges; 361 | IsFinal: Boolean; 362 | charset, target: Word; 363 | begin 364 | Index := Reader.ReadInteger; 365 | if Index <> DFA.States.Count then 366 | raise EReadError.Create('Records out of order'); 367 | IsFinal := Reader.ReadBoolean; 368 | FinalResult := Reader.ReadInteger; 369 | if not IsFinal then 370 | FinalResult := -1; 371 | Reader.SkipField; 372 | 373 | Edges := []; 374 | while not Reader.RecordFinished do 375 | begin 376 | charset := Reader.ReadInteger; 377 | target := Reader.ReadInteger; 378 | Edges += [DFAEdge(charset, target)]; 379 | Reader.SkipField; // Reserved 380 | end; 381 | 382 | DFA.AddState(FinalResult, Edges); 383 | end; 384 | 385 | function ParseLRState(Reader: TCGTReader; NextIndex: Integer): TLRState; 386 | var 387 | Index: Integer; 388 | Transitions: TLRTransitions; 389 | LookAhead, Value: Word; 390 | Action: TLRActionType; 391 | begin 392 | Index := Reader.ReadInteger; 393 | if Index <> NextIndex then 394 | raise EReadError.Create('Records out of order'); 395 | Reader.SkipField; // Reserved 396 | Transitions := []; 397 | while not Reader.RecordFinished do 398 | begin 399 | LookAhead := Reader.ReadInteger; 400 | Action := TLRActionType(Reader.ReadInteger); 401 | Value := Reader.ReadInteger; 402 | Reader.SkipField; // Reserved 403 | Transitions += [LRTransition(LookAhead, Action, Value)]; 404 | end; 405 | 406 | Result := TLRState.Create(Transitions); 407 | end; 408 | 409 | function ParseLRRule(Reader: TCGTReader; NextIndex: Integer): TLRRule; 410 | var 411 | Index: Integer; 412 | Consumes: TConsumes; 413 | Produces: Word; 414 | begin 415 | Index := Reader.ReadInteger; 416 | if Index <> NextIndex then 417 | raise EReadError.Create('Records out of order'); 418 | 419 | Produces := Reader.ReadInteger; 420 | Reader.SkipField; // Reserved 421 | 422 | Consumes := []; 423 | while not Reader.RecordFinished do 424 | Consumes += [Reader.ReadInteger]; 425 | 426 | Result := LRRule(Produces, Consumes); 427 | end; 428 | 429 | function ParseGroup(Reader: TCGTReader; NextIndex: Integer): TLexicalGroup; 430 | var 431 | Index, GroupSymbol, EndSymbol, StartSymbol: Word; 432 | Name: String; 433 | AdvanceMode: TGroupAdvance; 434 | EndMode: TGroupEnding; 435 | Count, i: Integer; 436 | Nestable: TNestableGroups; 437 | begin 438 | Index := Reader.ReadInteger; 439 | if Index <> NextIndex then 440 | raise EReadError.Create('Records out of order'); 441 | Name := Reader.ReadString; 442 | GroupSymbol := Reader.ReadInteger; 443 | StartSymbol := Reader.ReadInteger; 444 | EndSymbol := Reader.ReadInteger; 445 | AdvanceMode := TGroupAdvance(Reader.ReadInteger); 446 | EndMode := TGroupEnding(Reader.ReadInteger); 447 | Reader.SkipField; // RFU 448 | 449 | Count := Reader.ReadInteger; 450 | Nestable := []; 451 | SetLength(Nestable, Count); 452 | for i:=0 to Count - 1 do 453 | Nestable[i] := Reader.ReadInteger; 454 | 455 | Result := Group(Name, GroupSymbol, StartSymbol, EndSymbol, AdvanceMode, EndMode, Nestable); 456 | end; 457 | 458 | procedure TCGTGrammar.LoadFromFile(const CGTFile: string); 459 | var 460 | Reader: TCGTReader; 461 | RecSize: Integer; 462 | RecordType: TRecordType; 463 | SymbolList: TGrammarSymbolList; 464 | begin 465 | SymbolList := TGrammarSymbolList.Create; 466 | try 467 | Clear; 468 | Reader := TCGTReader.Create(TFileStream.Create(CGTFile, fmOpenRead)); 469 | try 470 | FVersion := ReadHeader(Reader); 471 | While True do 472 | begin 473 | RecSize := Reader.StartRecord; 474 | if RecSize < 0 then 475 | Break; // EOF 476 | RecordType := TRecordType(Reader.ReadChar); 477 | case RecordType of 478 | rtParameter: 479 | ParseParameter(Reader, FParameter); 480 | rtProperty: 481 | ParseProperty(Reader, FParameter); 482 | rtCountsV1, rtCountsV5: // Not required in this implementation 483 | while not Reader.RecordFinished do 484 | Reader.SkipField; 485 | rtInitialStates: 486 | begin 487 | FDFA.SetInitialState(Reader.ReadInteger); 488 | Reader.SkipField; 489 | end; 490 | rtCharset: 491 | FDFA.AddCharset(ParseCharset(Reader, FDFA.Charsets.Count)); 492 | rtCharRanges: 493 | FDFA.AddCharset(ParseCharRanges(Reader, FDFA.Charsets.Count)); 494 | rtSymbol: 495 | SymbolList.Add(ParseSymbol(Reader, SymbolList.Count)); 496 | rtDFAState: 497 | ParseDFAState(Reader, FDFA); 498 | rtLRState: 499 | FLALR.AddState(ParseLRState(Reader, FLALR.States.Count)); 500 | rtRule: 501 | FLALR.AddRule(ParseLRRule(Reader, FLALR.Rules.Count)); 502 | rtGroup: 503 | FDFA.AddGroup(ParseGroup(Reader, FDFA.Groups.Count)); 504 | end; 505 | 506 | if not Reader.RecordFinished then 507 | raise EReadError.Create('Record not fully read'); 508 | end; 509 | finally 510 | Reader.Free; 511 | end; 512 | 513 | Prepare(SymbolList); 514 | finally 515 | SymbolList.Free; 516 | end; 517 | end; 518 | 519 | procedure TCGTGrammar.Prepare(SymbolList: TGrammarSymbolList); 520 | var 521 | EOFSymbol: Integer = -1; 522 | CommentStart: Integer = -1; 523 | CommentEnd: Integer = -1; 524 | CommentLine: Integer = -1; 525 | NewLineSymbol: Integer = -1; 526 | CommentSymbol: Integer = -1; 527 | i: Integer; 528 | CLSymbol, Sym: TGrammarSymbol; 529 | begin 530 | // Ensure EOF Symbol in list 531 | for i:=0 to SymbolList.Count - 1 do 532 | if SymbolList[i].SymbolType = stEOF then 533 | begin 534 | EOFSymbol := i; 535 | break; 536 | end; 537 | if EOFSymbol < 0 then 538 | SymbolList.Add(Symbol(SymbolList.Count, '(EOF)', stEOF)); 539 | 540 | // Upgrade v1 Groups 541 | if Version = gv1 then 542 | begin 543 | for i:=0 to SymbolList.Count - 1 do 544 | if SymbolList[i].SymbolType = stGroupStart then 545 | CommentStart := i 546 | else if SymbolList[i].SymbolType = stGroupEnd then 547 | CommentEnd := i 548 | else if SymbolList[i].SymbolType = stCommentLine then 549 | CommentLine := i 550 | else if (SymbolList[i].UnmangledName = 'newline') and 551 | ((SymbolList[i].SymbolType = stTerminal) Or 552 | (SymbolList[i].SymbolType = stSkippable)) then 553 | NewLineSymbol := i 554 | else if (SymbolList[i].UnmangledName = 'comment') and 555 | (SymbolList[i].SymbolType = stSkippable) then 556 | CommentSymbol := i; 557 | 558 | if CommentSymbol < 0 then 559 | CommentSymbol := SymbolList.Add(Symbol(SymbolList.Count, 'Comment', stSkippable)); 560 | 561 | if (CommentStart >= 0) and (CommentEnd >= 0) then 562 | FDFA.AddGroup(Group('Comment Block', CommentSymbol, CommentStart, CommentEnd, 563 | gaCharWise, geClosed, [])); 564 | if (CommentLine >= 0) and (NewLineSymbol>= 0) then 565 | begin 566 | CLSymbol := SymbolList[CommentLine]; 567 | CLSymbol.SymbolType := stGroupStart; 568 | SymbolList[CommentLine] := CLSymbol; 569 | FDFA.AddGroup(Group('Comment Line', CommentSymbol, CommentLine, NewLineSymbol, 570 | gaCharWise, geOpen, [])); 571 | end; 572 | end; 573 | 574 | // Create SymbolTable 575 | SetLength(FSymbols, SymbolList.Count); 576 | for i:=0 to SymbolList.Count - 1 do 577 | FSymbols[i] := SymbolList[i]; 578 | 579 | // Prepare DFA 580 | FDFA.Prepare(FSymbols); 581 | end; 582 | 583 | function TCGTGrammar.LexToken(var Iterator: TUTF8Iterator): TToken; 584 | begin 585 | Result := FDFA.NextToken(Iterator, FSymbols); 586 | end; 587 | 588 | function TCGTGrammar.ParseString(const AString: String; 589 | BuildNode: TBuildParseTreeEvent; BuildLeaf: TBuildParseTreeLeafEvent; 590 | FreeNodesOnReset: Boolean): TObject; 591 | var 592 | Iterator: TUTF8Iterator; 593 | LookAhead: TToken; 594 | LALRAction: TLRActionType; 595 | begin 596 | Iterator := IterateUTF8(AString); 597 | LALR.Reset; 598 | LALR.FreeNodes := FreeNodesOnReset; 599 | LALR.BuildNode := BuildNode; 600 | LALR.BuildLeaf := BuildLeaf; 601 | try 602 | LookAhead := LexNextUnskippable(Iterator); 603 | While True do 604 | begin 605 | LALRAction := FLALR.Step(LookAhead, FSymbols); 606 | if LALRAction = atShift then 607 | LookAhead := LexNextUnskippable(Iterator); 608 | if LALRAction = atAccept then 609 | break; 610 | end; 611 | Result := LALR.ExtractResult; 612 | finally 613 | LALR.Reset; 614 | end; 615 | end; 616 | 617 | end. 618 | 619 | -------------------------------------------------------------------------------- /src/lexer.pas: -------------------------------------------------------------------------------- 1 | unit lexer; 2 | 3 | {$mode ObjFPC}{$H+} 4 | {$ModeSwitch advancedrecords} 5 | {$ModeSwitch arrayoperators} 6 | {$TypedAddress On} 7 | 8 | interface 9 | 10 | uses 11 | SysUtils, Classes, generics.Collections; 12 | 13 | type 14 | 15 | { TUTF8Iterator } 16 | 17 | TUTF8Iterator = record 18 | Data: String; 19 | ScanHead: SizeInt; 20 | 21 | function GetEnumerator: TUTF8Iterator; inline; 22 | function GetCurrent: String; inline; 23 | function MoveNext: Boolean; inline; 24 | function MovePrevious: Boolean; inline; 25 | function EOS: Boolean; inline; 26 | procedure Backtrack(ToIndex: SizeInt); 27 | function CopyFrom(StartPos: SizeInt): String; inline; 28 | property Current: String read GetCurrent; 29 | end; 30 | 31 | TCharset = class 32 | public 33 | function CharInSet(const CharValue: String): Boolean; virtual; abstract; 34 | end; 35 | TCharsets = class(specialize TObjectList<TCharset>); 36 | 37 | { TStaticCharset } 38 | 39 | TStaticCharset = class(TCharset) 40 | private 41 | FCharset: specialize THashSet<String>; 42 | public 43 | constructor FromString(const Chars: String); 44 | destructor Destroy; override; 45 | 46 | function CharInSet(const CharValue: String): Boolean; override; 47 | end; 48 | 49 | { TCodePointRange } 50 | 51 | TCodePointRange = record 52 | RangeStart: Word; 53 | RangeEnd: Word; 54 | 55 | function InRange(CodePoint: Word): Boolean; inline; 56 | end; 57 | TCodePointRanges = Array of TCodePointRange; 58 | 59 | { TRangeCharset } 60 | 61 | TRangeCharset = class(TCharset) 62 | private 63 | FCodePage: Integer; 64 | FRanges: TCodePointRanges; 65 | private 66 | function DecodeUtf8(const CharValue: String): Word; inline; 67 | public 68 | constructor Create(const CodePage: Integer); 69 | constructor FromArray(const CodePage: Integer; const Ranges: TCodePointRanges); 70 | 71 | function CharInSet(const CharValue: String): Boolean; override; 72 | end; 73 | 74 | TSymbolType = (stNonTerminal = 0, stTerminal, stSkippable, stEOF, 75 | stGroupStart, stGroupEnd, stCommentLine, stError); 76 | 77 | { TGrammarSymbol } 78 | 79 | TGrammarSymbol = record 80 | private 81 | GroupReference: Integer; 82 | public 83 | Index: Integer; 84 | SymbolType: TSymbolType; 85 | Name: String; 86 | function UnmangledName: String; inline; 87 | end; 88 | PGrammarSymbol = ^TGrammarSymbol; 89 | TGrammarSymbolList = class(specialize TList<TGrammarSymbol>); 90 | TGrammarSymbolTable = array of TGrammarSymbol; 91 | 92 | TDFALexer = class; 93 | 94 | TDFAEdge = record 95 | Target: Integer; 96 | Charset: Integer; 97 | end; 98 | TDFAEdges = array of TDFAEdge; 99 | 100 | { TDFAState } 101 | 102 | TDFAState = class 103 | private 104 | FDFA: TDFALexer; 105 | FFinalResult: Integer; 106 | FEdges: TDFAEdges; 107 | public 108 | constructor Create(DFA: TDFALexer; FinalResult: Integer; const Edges: TDFAEdges); 109 | 110 | function GetEdge(const NextChar: String): TDFAState; 111 | function IsFinal: Boolean; inline; 112 | 113 | property FinalResult: Integer read FFinalResult; 114 | property Edges[const NextChar: String]: TDFAState read GetEdge; default; 115 | end; 116 | TDFAStates = class(specialize TObjectList<TDFAState>); 117 | 118 | TToken = record 119 | Symbol: PGrammarSymbol; 120 | StartPos: SizeInt; 121 | Value: String; 122 | NestedTokens: Array of TToken; 123 | end; 124 | 125 | TGroupAdvance = (gaTokenwise = 0, gaCharWise); 126 | TGroupEnding = (geOpen = 0, geClosed); 127 | TNestableGroups = Array of Integer; 128 | 129 | TLexicalGroup = record 130 | Name: String; 131 | Symbol: Integer; 132 | StartSymbol: Integer; 133 | EndSymbol: Integer; 134 | AdvanceMode: TGroupAdvance; 135 | EndingMode: TGroupEnding; 136 | 137 | Nestable: TNestableGroups; 138 | end; 139 | TLexicalGroups = class(specialize TList<TLexicalGroup>); 140 | 141 | EPreparationError = class(Exception); 142 | 143 | { TDFALexer } 144 | 145 | TDFALexer = class 146 | private 147 | FCharSets: TCharsets; 148 | FStates: TDFAStates; 149 | FGroups: TLexicalGroups; 150 | FInitialState: Integer; 151 | FEOFSymbol: PGrammarSymbol; 152 | 153 | public 154 | constructor Create; 155 | destructor Destroy; override; 156 | 157 | procedure AddState(FinalResult: Integer; const Edges: TDFAEdges); inline; 158 | procedure AddCharset(Charset: TCharset); inline; 159 | procedure AddGroup(const AGroup: TLexicalGroup); 160 | inline; 161 | procedure SetInitialState(InitialState: SizeInt); inline; 162 | 163 | function Match(var Iterator: TUTF8Iterator; 164 | const SymbolTable: TGrammarSymbolTable): TToken; 165 | function NextToken(var Iterator: TUTF8Iterator; 166 | const SymbolTable: TGrammarSymbolTable): TToken; 167 | 168 | procedure Prepare(const SymbolTable: TGrammarSymbolTable); 169 | 170 | property Charsets: TCharsets read FCharSets; 171 | property Groups: TLexicalGroups read FGroups; 172 | property States: TDFAStates read FStates; 173 | property EOFSymbol: PGrammarSymbol read FEOFSymbol; 174 | end; 175 | 176 | // Exceptions: 177 | 178 | { ELexicalError } 179 | 180 | ELexicalError = class(Exception) 181 | private 182 | FInputString: String; 183 | FErrorPosition: SizeInt; 184 | FErrorChar: String; 185 | public 186 | constructor Create(const AString: String; AToken: TToken); 187 | 188 | property InputString: String read FInputString; 189 | property ErrorPosition: SizeInt read FErrorPosition; 190 | property ErrorChar: String read FErrorChar; 191 | end; 192 | 193 | { EGroupError } 194 | 195 | EGroupError = class(Exception) 196 | private 197 | FGroupName: String; 198 | FInputString: String; 199 | FStartPos: SizeInt; 200 | public 201 | constructor Create(const AString: String; const AGroupName: String; 202 | const AStartPos: SizeInt); 203 | 204 | property InputString: String read FInputString; 205 | property GroupStartPosition: SizeInt read FStartPos; 206 | property GroupName: String read FGroupName; 207 | end; 208 | 209 | 210 | const 211 | ErrorSymbol = nil; 212 | 213 | function IterateUTF8(const AString: String; StartIndex: SizeInt = 0): TUTF8Iterator; inline; 214 | function UTF8CharLen(FirstChar: Char): SizeInt; inline; 215 | function InUTF8Sequence(CheckChar: Char): Boolean; inline; 216 | function CodepointRange(RangeStart: Word; RangeEnd: Word): TCodePointRange; inline; 217 | function DFAEdge(Charset: Integer; Target: Integer): TDFAEdge; inline; 218 | function Symbol(Index: Integer; const Name: String; SymbolType: TSymbolType): TGrammarSymbol; 219 | function Token(Symbol: PGrammarSymbol; Position: SizeInt; const Value: String): TToken; inline; 220 | function Group(const GroupName: String; GroupSymbol: Integer; 221 | StartSymbol: Integer; EndSymbol: Integer; 222 | AdvanceMode: TGroupAdvance; EndingMode: TGroupEnding; 223 | NestableGroups: TNestableGroups): TLexicalGroup; 224 | implementation 225 | 226 | function IterateUTF8(const AString: String; StartIndex: SizeInt): TUTF8Iterator; 227 | begin 228 | Result.Data := AString; 229 | Result.ScanHead := StartIndex; 230 | end; 231 | 232 | function UTF8CharLen(FirstChar: Char): SizeInt; 233 | begin 234 | Result := 1 + ord((ord(FirstChar) And %11000000) = %11000000) 235 | + ord((ord(FirstChar) And %11100000) = %11100000) 236 | + ord((ord(FirstChar) And %11110000) = %11110000); 237 | end; 238 | 239 | function InUTF8Sequence(CheckChar: Char): Boolean; 240 | begin 241 | Result := (ord(CheckChar) And %11000000) = %10000000; 242 | end; 243 | 244 | function CodepointRange(RangeStart: Word; RangeEnd: Word): TCodePointRange; 245 | begin 246 | Result.RangeStart := RangeStart; 247 | Result.RangeEnd := RangeEnd; 248 | end; 249 | 250 | function DFAEdge(Charset: Integer; Target: Integer): TDFAEdge; 251 | begin 252 | Result.Charset := Charset; 253 | Result.Target := Target; 254 | end; 255 | 256 | function Symbol(Index: Integer; const Name: String; SymbolType: TSymbolType 257 | ): TGrammarSymbol; 258 | begin 259 | Result.Index := Index; 260 | // Name mangling to ensure that symbols of different kinds have different names 261 | case SymbolType of 262 | stNonTerminal: 263 | Result.Name := '<' + Name + '>'; 264 | stTerminal: 265 | Result.Name := '''' + Name + ''''; 266 | stSkippable: 267 | Result.Name := '[' + Name + ']'; 268 | stEOF: 269 | Result.Name := '(EOF)'; 270 | stGroupStart: 271 | Result.Name := '^' + Name + '^'; 272 | stGroupEnd: 273 | Result.Name := 'v' + Name + 'v'; 274 | stCommentLine: 275 | Result.Name := '/' + Name + '/'; 276 | end; 277 | Result.SymbolType := SymbolType; 278 | Result.GroupReference := -1; 279 | end; 280 | 281 | function Token(Symbol: PGrammarSymbol; Position: SizeInt; const Value: String): TToken; 282 | begin 283 | Result.StartPos := Position; 284 | Result.Symbol := Symbol; 285 | Result.Value := Value; 286 | Result.NestedTokens := []; 287 | end; 288 | 289 | function Group(const GroupName: String; GroupSymbol: Integer; 290 | StartSymbol: Integer; EndSymbol: Integer; AdvanceMode: TGroupAdvance; 291 | EndingMode: TGroupEnding; NestableGroups: TNestableGroups): TLexicalGroup; 292 | begin 293 | Result.Name := GroupName; 294 | Result.Symbol := GroupSymbol; 295 | Result.StartSymbol := StartSymbol; 296 | Result.EndSymbol := EndSymbol; 297 | Result.AdvanceMode := AdvanceMode; 298 | Result.EndingMode := EndingMode; 299 | Result.Nestable := NestableGroups; 300 | end; 301 | 302 | { EGroupError } 303 | 304 | constructor EGroupError.Create(const AString: String; const AGroupName: String; 305 | const AStartPos: SizeInt); 306 | begin 307 | FInputString := AString; 308 | FGroupName := AGroupName; 309 | FStartPos := AStartPos; 310 | 311 | inherited CreateFmt('Unclosed Group %s at %d', [FGroupName, FStartPos]); 312 | end; 313 | 314 | { ELexicalError } 315 | 316 | constructor ELexicalError.Create(const AString: String; AToken: TToken); 317 | begin 318 | FInputString := AString; 319 | FErrorChar := AToken.Value; 320 | FErrorPosition := AToken.StartPos; 321 | 322 | inherited CreateFmt('Unreckognizable Token %s at %d', [FErrorChar, FErrorPosition]); 323 | end; 324 | 325 | { TGrammarSymbol } 326 | 327 | function TGrammarSymbol.UnmangledName: String; 328 | begin 329 | Result := Name.Substring(1, Name.Length - 2); 330 | end; 331 | 332 | { TUTF8Iterator } 333 | 334 | function TUTF8Iterator.GetEnumerator: TUTF8Iterator; 335 | begin 336 | Result := Self; 337 | end; 338 | 339 | function TUTF8Iterator.GetCurrent: String; 340 | var 341 | CharLen: SizeInt; 342 | begin 343 | CharLen := UTF8CharLen(Data[ScanHead]); 344 | Result := Copy(Data, ScanHead, CharLen); 345 | end; 346 | 347 | function TUTF8Iterator.MoveNext: Boolean; 348 | begin 349 | if ScanHead < 1 then 350 | Inc(ScanHead) 351 | else if ScanHead <= Data.Length then 352 | Inc(ScanHead, UTF8CharLen(Data[ScanHead])); 353 | Result := ScanHead <= Data.Length; 354 | end; 355 | 356 | function TUTF8Iterator.MovePrevious: Boolean; 357 | begin 358 | if ScanHead > Data.Length then 359 | ScanHead := Data.Length; 360 | if ScanHead <= 0 then 361 | Exit(False); 362 | Dec(ScanHead); 363 | while (ScanHead > 0) And InUTF8Sequence(Data[ScanHead]) do 364 | Dec(ScanHead); 365 | Result := ScanHead > 0; 366 | end; 367 | 368 | function TUTF8Iterator.EOS: Boolean; 369 | begin 370 | Result := (ScanHead > Data.Length) Or (Data.Length = 0); 371 | end; 372 | 373 | procedure TUTF8Iterator.Backtrack(ToIndex: SizeInt); 374 | begin 375 | ScanHead := ToIndex; 376 | if InUTF8Sequence(Data[ScanHead]) then 377 | MovePrevious; 378 | end; 379 | 380 | function TUTF8Iterator.CopyFrom(StartPos: SizeInt): String; 381 | begin 382 | Result := Copy(Data, StartPos, ScanHead - StartPos + 1); 383 | end; 384 | 385 | { TStaticCharset } 386 | 387 | constructor TStaticCharset.FromString(const Chars: String); 388 | var 389 | CharElem: String; 390 | begin 391 | inherited Create; 392 | FCharset := (specialize THashSet<string>).Create; 393 | for CharElem in IterateUTF8(Chars) do 394 | FCharset.Add(CharElem); 395 | end; 396 | 397 | destructor TStaticCharset.Destroy; 398 | begin 399 | FCharset.Free; 400 | inherited Destroy; 401 | end; 402 | 403 | function TStaticCharset.CharInSet(const CharValue: String): Boolean; 404 | begin 405 | Result := FCharset.Contains(CharValue); 406 | end; 407 | 408 | { TCodePointRange } 409 | 410 | function TCodePointRange.InRange(CodePoint: Word): Boolean; 411 | begin 412 | Result := (CodePoint >= RangeStart) And 413 | (CodePoint <= RangeEnd); 414 | end; 415 | 416 | { TRangeCharset } 417 | 418 | function TRangeCharset.DecodeUtf8(const CharValue: String): Word; 419 | var 420 | ConvLen: SizeUInt; 421 | begin 422 | // TODO: Handle codepage 423 | ConvLen := Utf8ToUnicode(PUnicodeChar(@Result), 1, @CharValue[1], CharValue.Length); 424 | Assert(ConvLen = 1, 'Should be exactly 1 widechar'); 425 | end; 426 | 427 | constructor TRangeCharset.Create(const CodePage: Integer); 428 | begin 429 | inherited Create; 430 | FCodePage := CodePage; 431 | end; 432 | 433 | constructor TRangeCharset.FromArray(const CodePage: Integer; 434 | const Ranges: TCodePointRanges); 435 | begin 436 | Create(CodePage); 437 | FRanges := Ranges; 438 | end; 439 | 440 | function TRangeCharset.CharInSet(const CharValue: String): Boolean; 441 | var 442 | CodePoint: Word; 443 | i: SizeInt; 444 | begin 445 | CodePoint := DecodeUtf8(CharValue); 446 | Result := False; 447 | for i:=0 to Length(FRanges) - 1 do 448 | if FRanges[i].InRange(CodePoint) then 449 | Exit(True); 450 | end; 451 | 452 | { TDFAState } 453 | 454 | constructor TDFAState.Create(DFA: TDFALexer; FinalResult: Integer; 455 | const Edges: TDFAEdges); 456 | begin 457 | inherited Create; 458 | FDFA := DFA; 459 | FFinalResult := FinalResult; 460 | FEdges := Edges; 461 | end; 462 | 463 | function TDFAState.GetEdge(const NextChar: String): TDFAState; 464 | var 465 | i: Integer; 466 | begin 467 | Result := nil; 468 | for i:=0 to Length(FEdges) - 1 do 469 | if FDFA.FCharSets[FEdges[i].Charset].CharInSet(NextChar) then 470 | Exit(FDFA.FStates[FEdges[i].Target]); 471 | end; 472 | 473 | function TDFAState.IsFinal: Boolean; 474 | begin 475 | Result := FFinalResult >= 0; 476 | end; 477 | 478 | { TDFALexer } 479 | 480 | constructor TDFALexer.Create; 481 | begin 482 | inherited Create; 483 | FCharSets := TCharsets.Create; 484 | FStates := TDFAStates.Create; 485 | FGroups := TLexicalGroups.Create; 486 | FEOFSymbol := nil; 487 | FInitialState := 0; 488 | end; 489 | 490 | destructor TDFALexer.Destroy; 491 | begin 492 | FStates.Free; 493 | FCharSets.Free; 494 | FGroups.Free; 495 | inherited Destroy; 496 | end; 497 | 498 | procedure TDFALexer.AddState(FinalResult: Integer; const Edges: TDFAEdges); 499 | begin 500 | FStates.Add(TDFAState.Create(Self, FinalResult, Edges)); 501 | end; 502 | 503 | procedure TDFALexer.AddCharset(Charset: TCharset); 504 | begin 505 | FCharsets.Add(Charset); 506 | end; 507 | 508 | procedure TDFALexer.AddGroup(const AGroup: TLexicalGroup); 509 | begin 510 | FGroups.Add(AGroup); 511 | end; 512 | 513 | procedure TDFALexer.SetInitialState(InitialState: SizeInt); 514 | begin 515 | FInitialState := InitialState; 516 | end; 517 | 518 | function TDFALexer.Match(var Iterator: TUTF8Iterator; 519 | const SymbolTable: TGrammarSymbolTable): TToken; 520 | var 521 | CurrentState: TDFAState; 522 | StartPos: SizeInt; 523 | begin 524 | // Check for EOF 525 | if not Iterator.MoveNext then 526 | begin 527 | Result := Token(FEOFSymbol, Iterator.ScanHead, '(EOF)'); 528 | Exit; 529 | end; 530 | StartPos := Iterator.ScanHead; 531 | // Default result if we don't match anything 532 | Result := Token(ErrorSymbol, StartPos, Iterator.GetCurrent); 533 | // Run DFA 534 | CurrentState := FStates[FInitialState]; 535 | // Assume that the initial state cannot be a final state, because matching an 536 | // empty token would result in a never ending lexer 537 | repeat 538 | CurrentState := CurrentState[Iterator.GetCurrent]; 539 | if Assigned(CurrentState) and CurrentState.IsFinal then 540 | Result := Token(@SymbolTable[CurrentState.FinalResult], 541 | StartPos, Iterator.CopyFrom(StartPos)); 542 | until not Assigned(CurrentState) or not Iterator.MoveNext; 543 | // Backtrack will always backtrack to the last UTF-8 char, so -1 can be used 544 | Iterator.Backtrack(Result.StartPos + Result.Value.Length - 1); 545 | end; 546 | 547 | type 548 | TGroupStackItem = record 549 | Token: TToken; 550 | GroupReference: Integer; 551 | end; 552 | TGroupStack = specialize TList<TGroupStackItem>; 553 | 554 | function TDFALexer.NextToken(var Iterator: TUTF8Iterator; 555 | const SymbolTable: TGrammarSymbolTable): TToken; 556 | 557 | function GroupStackItem(const StartToken: TToken; GroupReference: Integer): TGroupStackItem; {$IFDEF INLINE}inline;{$ENDIF} 558 | begin 559 | Result.Token := Token(@SymbolTable[FGroups[GroupReference].Symbol], StartToken.StartPos, StartToken.Value); 560 | Result.GroupReference := GroupReference; 561 | end; 562 | 563 | var 564 | GroupStack: TGroupStack; 565 | CurrentGroup: TLexicalGroup; 566 | IsNestable: Boolean; 567 | i: Integer; 568 | begin 569 | Result := Match(Iterator, SymbolTable); 570 | 571 | if not Assigned(Result.Symbol) then 572 | raise ELexicalError.Create(Iterator.Data, Result); 573 | 574 | if Result.Symbol^.SymbolType <> stGroupStart then 575 | Exit; 576 | 577 | GroupStack := TGroupStack.Create; 578 | try 579 | GroupStack.Add(GroupStackItem(Result, Result.Symbol^.GroupReference)); 580 | while not Iterator.EOS do 581 | begin 582 | CurrentGroup := FGroups[GroupStack.Last.GroupReference]; 583 | Result := Match(Iterator, SymbolTable); 584 | if not Assigned(Result.Symbol) then // Unknown token parsed, skip 585 | Continue; 586 | // Check for Beginning of Group 587 | if Result.Symbol^.SymbolType = stGroupStart then 588 | begin 589 | IsNestable := False; 590 | for i:=0 to Length(CurrentGroup.Nestable) - 1 do 591 | if CurrentGroup.Nestable[i] = Result.Symbol^.GroupReference then 592 | begin 593 | IsNestable := True; 594 | Break; 595 | end; 596 | if IsNestable then 597 | begin 598 | GroupStack.Add(GroupStackItem(Result, Result.Symbol^.GroupReference)); 599 | Continue; 600 | end; 601 | end; 602 | // Check if end of current group 603 | if CurrentGroup.EndSymbol = Result.Symbol^.Index then 604 | begin 605 | // Get token from stack 606 | Result := GroupStack.Last.Token; 607 | // Newline hack: Don't consume newline token 608 | // So we backtrack to before this token 609 | if Result.Symbol^.UnmangledName = 'newline' then 610 | Iterator.Backtrack(Result.StartPos - 1); 611 | // Update token text to include all up to (and including) end Token 612 | Result.Value := Iterator.CopyFrom(Result.StartPos); 613 | // Pop: If last, return, if not update new stack 614 | GroupStack.Delete(GroupStack.Count - 1); 615 | if GroupStack.Count > 0 then 616 | GroupStack.Last.Token.NestedTokens += [Result] 617 | else // Last group element poped, return 618 | Exit; 619 | Continue; 620 | end; 621 | 622 | // If charwise advance, backtrack 623 | if CurrentGroup.AdvanceMode = gaCharWise then 624 | Iterator.Backtrack(Result.StartPos); 625 | end; 626 | 627 | // We only get here when we Reached EOF 628 | // So we close all open ended groups still open 629 | while GroupStack.Count > 0 do 630 | begin 631 | CurrentGroup := FGroups[GroupStack.Last.GroupReference]; 632 | if CurrentGroup.EndingMode = geOpen then 633 | begin 634 | // Get token from stack 635 | Result := GroupStack.Last.Token; 636 | // Update token text to include all up to (and including) end Token 637 | Result.Value := Iterator.CopyFrom(Result.StartPos); 638 | // Pop: If last, return, if not update new stack 639 | GroupStack.Delete(GroupStack.Count - 1); 640 | end 641 | else 642 | raise EGroupError.Create(Iterator.Data, CurrentGroup.Name, GroupStack.Last.Token.StartPos); 643 | end; 644 | finally 645 | GroupStack.Free; 646 | end; 647 | end; 648 | 649 | procedure TDFALexer.Prepare(const SymbolTable: TGrammarSymbolTable); 650 | var 651 | i: Integer; 652 | begin 653 | // Find EOF Symbol 654 | FEOFSymbol := nil; 655 | for i:=0 to Length(SymbolTable) - 1 do 656 | if SymbolTable[i].SymbolType = stEOF then 657 | begin 658 | FEOFSymbol := @SymbolTable[i]; 659 | break; 660 | end; 661 | if not Assigned(FEOFSymbol) then 662 | raise EPreparationError.Create('No EOF found in SymbolTable'); 663 | 664 | // Backlink group symbols 665 | for i:=0 to FGroups.Count - 1 do 666 | begin 667 | SymbolTable[FGroups[i].StartSymbol].GroupReference := i; 668 | SymbolTable[FGroups[i].EndSymbol].GroupReference := i; 669 | end; 670 | end; 671 | 672 | end. 673 | 674 | -------------------------------------------------------------------------------- /example/simplegrammar.pas: -------------------------------------------------------------------------------- 1 | unit SimpleGrammar; 2 | 3 | // Grammar generated from CGT using GOLD Parser Tools: https://github.com/Warfley/gold-parser-tools 4 | 5 | {$mode ObjFPC}{$H+} 6 | 7 | interface 8 | 9 | uses 10 | Classes, SysUtils, lexer, parser, cgtgrammar; 11 | 12 | type 13 | TSimple = class(TCGTGrammar) 14 | public 15 | constructor Create; 16 | end; 17 | 18 | implementation 19 | 20 | constructor TSimple.Create; 21 | var 22 | SymbolList: TGrammarSymbolList; 23 | begin 24 | inherited Create; 25 | SymbolList := TGrammarSymbolList.Create; 26 | try 27 | FVersion := gv5; 28 | FParameter.Add('Name', 'Simple'); 29 | FParameter.Add('Version', '1'); 30 | FParameter.Add('Author', 'Frederic Kehrein'); 31 | FParameter.Add('About', 'Simple Test Language'); 32 | FParameter.Add('Character Set', 'Unicode'); 33 | FParameter.Add('Character Mapping', 'Windows-1252'); 34 | FParameter.Add('Generated By', 'GOLD Parser Builder 5.2.0.'); 35 | FParameter.Add('Generated Date', '2023-01-29 02:34'); 36 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 37 | CodepointRange(10, 10) 38 | ])); 39 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 40 | CodepointRange(13, 13) 41 | ])); 42 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 43 | CodepointRange(8232, 8232) 44 | ])); 45 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 46 | CodepointRange(8233, 8233) 47 | ])); 48 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 49 | CodepointRange(9, 9), 50 | CodepointRange(11, 12), 51 | CodepointRange(32, 32), 52 | CodepointRange(133, 133), 53 | CodepointRange(160, 160), 54 | CodepointRange(5760, 5760), 55 | CodepointRange(6158, 6158), 56 | CodepointRange(8192, 8202), 57 | CodepointRange(8230, 8230), 58 | CodepointRange(8239, 8239), 59 | CodepointRange(8287, 8287), 60 | CodepointRange(12288, 12288) 61 | ])); 62 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 63 | CodepointRange(33, 33) 64 | ])); 65 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 66 | CodepointRange(40, 40) 67 | ])); 68 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 69 | CodepointRange(41, 41) 70 | ])); 71 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 72 | CodepointRange(42, 42) 73 | ])); 74 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 75 | CodepointRange(43, 43) 76 | ])); 77 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 78 | CodepointRange(44, 44) 79 | ])); 80 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 81 | CodepointRange(45, 45) 82 | ])); 83 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 84 | CodepointRange(58, 58) 85 | ])); 86 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 87 | CodepointRange(59, 59) 88 | ])); 89 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 90 | CodepointRange(61, 61) 91 | ])); 92 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 93 | CodepointRange(49, 57) 94 | ])); 95 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 96 | CodepointRange(65, 90), 97 | CodepointRange(95, 95), 98 | CodepointRange(97, 99), 99 | CodepointRange(103, 115), 100 | CodepointRange(117, 118), 101 | CodepointRange(120, 122) 102 | ])); 103 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 104 | CodepointRange(47, 47) 105 | ])); 106 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 107 | CodepointRange(48, 48) 108 | ])); 109 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 110 | CodepointRange(60, 60) 111 | ])); 112 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 113 | CodepointRange(62, 62) 114 | ])); 115 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 116 | CodepointRange(100, 100) 117 | ])); 118 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 119 | CodepointRange(101, 101) 120 | ])); 121 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 122 | CodepointRange(102, 102) 123 | ])); 124 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 125 | CodepointRange(116, 116) 126 | ])); 127 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 128 | CodepointRange(119, 119) 129 | ])); 130 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 131 | CodepointRange(48, 57) 132 | ])); 133 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 134 | CodepointRange(48, 57), 135 | CodepointRange(65, 90), 136 | CodepointRange(95, 95), 137 | CodepointRange(97, 122) 138 | ])); 139 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 140 | CodepointRange(120, 120) 141 | ])); 142 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 143 | CodepointRange(48, 57), 144 | CodepointRange(65, 70), 145 | CodepointRange(97, 102) 146 | ])); 147 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 148 | CodepointRange(48, 57), 149 | CodepointRange(65, 90), 150 | CodepointRange(95, 95), 151 | CodepointRange(97, 110), 152 | CodepointRange(112, 122) 153 | ])); 154 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 155 | CodepointRange(111, 111) 156 | ])); 157 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 158 | CodepointRange(48, 57), 159 | CodepointRange(65, 90), 160 | CodepointRange(95, 95), 161 | CodepointRange(97, 109), 162 | CodepointRange(111, 122) 163 | ])); 164 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 165 | CodepointRange(110, 110) 166 | ])); 167 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 168 | CodepointRange(48, 57), 169 | CodepointRange(65, 90), 170 | CodepointRange(95, 95), 171 | CodepointRange(97, 99), 172 | CodepointRange(101, 122) 173 | ])); 174 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 175 | CodepointRange(48, 57), 176 | CodepointRange(65, 90), 177 | CodepointRange(95, 95), 178 | CodepointRange(98, 110), 179 | CodepointRange(112, 122) 180 | ])); 181 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 182 | CodepointRange(97, 97) 183 | ])); 184 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 185 | CodepointRange(48, 57), 186 | CodepointRange(65, 90), 187 | CodepointRange(95, 95), 188 | CodepointRange(97, 107), 189 | CodepointRange(109, 122) 190 | ])); 191 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 192 | CodepointRange(108, 108) 193 | ])); 194 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 195 | CodepointRange(48, 57), 196 | CodepointRange(65, 90), 197 | CodepointRange(95, 95), 198 | CodepointRange(97, 114), 199 | CodepointRange(116, 122) 200 | ])); 201 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 202 | CodepointRange(115, 115) 203 | ])); 204 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 205 | CodepointRange(48, 57), 206 | CodepointRange(65, 90), 207 | CodepointRange(95, 95), 208 | CodepointRange(97, 100), 209 | CodepointRange(102, 122) 210 | ])); 211 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 212 | CodepointRange(48, 57), 213 | CodepointRange(65, 90), 214 | CodepointRange(95, 95), 215 | CodepointRange(97, 113), 216 | CodepointRange(115, 122) 217 | ])); 218 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 219 | CodepointRange(114, 114) 220 | ])); 221 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 222 | CodepointRange(48, 57), 223 | CodepointRange(65, 90), 224 | CodepointRange(95, 95), 225 | CodepointRange(97, 110), 226 | CodepointRange(112, 113), 227 | CodepointRange(115, 122) 228 | ])); 229 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 230 | CodepointRange(48, 57), 231 | CodepointRange(65, 90), 232 | CodepointRange(95, 95), 233 | CodepointRange(97, 116), 234 | CodepointRange(118, 122) 235 | ])); 236 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 237 | CodepointRange(117, 117) 238 | ])); 239 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 240 | CodepointRange(48, 57), 241 | CodepointRange(65, 90), 242 | CodepointRange(95, 95), 243 | CodepointRange(97, 103), 244 | CodepointRange(105, 122) 245 | ])); 246 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 247 | CodepointRange(104, 104) 248 | ])); 249 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 250 | CodepointRange(48, 57), 251 | CodepointRange(65, 90), 252 | CodepointRange(95, 95), 253 | CodepointRange(97, 104), 254 | CodepointRange(106, 122) 255 | ])); 256 | FDFA.AddCharset(TRangeCharset.FromArray(0, [ 257 | CodepointRange(105, 105) 258 | ])); 259 | 260 | SymbolList.Add(Symbol(SymbolList.Count, 'EOF', TSymbolType(3))); 261 | SymbolList.Add(Symbol(SymbolList.Count, 'Error', TSymbolType(7))); 262 | SymbolList.Add(Symbol(SymbolList.Count, 'Comment', TSymbolType(2))); 263 | SymbolList.Add(Symbol(SymbolList.Count, 'NewLine', TSymbolType(2))); 264 | SymbolList.Add(Symbol(SymbolList.Count, 'Whitespace', TSymbolType(2))); 265 | SymbolList.Add(Symbol(SymbolList.Count, '//', TSymbolType(4))); 266 | SymbolList.Add(Symbol(SymbolList.Count, '!=', TSymbolType(1))); 267 | SymbolList.Add(Symbol(SymbolList.Count, '(', TSymbolType(1))); 268 | SymbolList.Add(Symbol(SymbolList.Count, ')', TSymbolType(1))); 269 | SymbolList.Add(Symbol(SymbolList.Count, '*', TSymbolType(1))); 270 | SymbolList.Add(Symbol(SymbolList.Count, '+', TSymbolType(1))); 271 | SymbolList.Add(Symbol(SymbolList.Count, ',', TSymbolType(1))); 272 | SymbolList.Add(Symbol(SymbolList.Count, '-', TSymbolType(1))); 273 | SymbolList.Add(Symbol(SymbolList.Count, '/', TSymbolType(1))); 274 | SymbolList.Add(Symbol(SymbolList.Count, ':=', TSymbolType(1))); 275 | SymbolList.Add(Symbol(SymbolList.Count, ';', TSymbolType(1))); 276 | SymbolList.Add(Symbol(SymbolList.Count, '<', TSymbolType(1))); 277 | SymbolList.Add(Symbol(SymbolList.Count, '<=', TSymbolType(1))); 278 | SymbolList.Add(Symbol(SymbolList.Count, '=', TSymbolType(1))); 279 | SymbolList.Add(Symbol(SymbolList.Count, '>', TSymbolType(1))); 280 | SymbolList.Add(Symbol(SymbolList.Count, '>=', TSymbolType(1))); 281 | SymbolList.Add(Symbol(SymbolList.Count, 'DecimanlNumber', TSymbolType(1))); 282 | SymbolList.Add(Symbol(SymbolList.Count, 'do', TSymbolType(1))); 283 | SymbolList.Add(Symbol(SymbolList.Count, 'end', TSymbolType(1))); 284 | SymbolList.Add(Symbol(SymbolList.Count, 'false', TSymbolType(1))); 285 | SymbolList.Add(Symbol(SymbolList.Count, 'for', TSymbolType(1))); 286 | SymbolList.Add(Symbol(SymbolList.Count, 'HexNumber', TSymbolType(1))); 287 | SymbolList.Add(Symbol(SymbolList.Count, 'Identifier', TSymbolType(1))); 288 | SymbolList.Add(Symbol(SymbolList.Count, 'to', TSymbolType(1))); 289 | SymbolList.Add(Symbol(SymbolList.Count, 'true', TSymbolType(1))); 290 | SymbolList.Add(Symbol(SymbolList.Count, 'while', TSymbolType(1))); 291 | SymbolList.Add(Symbol(SymbolList.Count, 'Assignment', TSymbolType(0))); 292 | SymbolList.Add(Symbol(SymbolList.Count, 'Constant', TSymbolType(0))); 293 | SymbolList.Add(Symbol(SymbolList.Count, 'Expression', TSymbolType(0))); 294 | SymbolList.Add(Symbol(SymbolList.Count, 'Expressions', TSymbolType(0))); 295 | SymbolList.Add(Symbol(SymbolList.Count, 'For Loop', TSymbolType(0))); 296 | SymbolList.Add(Symbol(SymbolList.Count, 'Function Call', TSymbolType(0))); 297 | SymbolList.Add(Symbol(SymbolList.Count, 'Operator', TSymbolType(0))); 298 | SymbolList.Add(Symbol(SymbolList.Count, 'Parameter', TSymbolType(0))); 299 | SymbolList.Add(Symbol(SymbolList.Count, 'Statement', TSymbolType(0))); 300 | SymbolList.Add(Symbol(SymbolList.Count, 'Statements', TSymbolType(0))); 301 | SymbolList.Add(Symbol(SymbolList.Count, 'While Loop', TSymbolType(0))); 302 | 303 | FDFA.AddState(-1, [ 304 | DFAEdge(0, 1), 305 | DFAEdge(1, 2), 306 | DFAEdge(2, 4), 307 | DFAEdge(3, 5), 308 | DFAEdge(4, 6), 309 | DFAEdge(5, 7), 310 | DFAEdge(6, 9), 311 | DFAEdge(7, 10), 312 | DFAEdge(8, 11), 313 | DFAEdge(9, 12), 314 | DFAEdge(10, 13), 315 | DFAEdge(11, 14), 316 | DFAEdge(12, 15), 317 | DFAEdge(13, 17), 318 | DFAEdge(14, 18), 319 | DFAEdge(15, 19), 320 | DFAEdge(16, 20), 321 | DFAEdge(17, 22), 322 | DFAEdge(18, 24), 323 | DFAEdge(19, 27), 324 | DFAEdge(20, 29), 325 | DFAEdge(21, 31), 326 | DFAEdge(22, 33), 327 | DFAEdge(23, 36), 328 | DFAEdge(24, 43), 329 | DFAEdge(25, 48) 330 | ]); 331 | FDFA.AddState(3, [ 332 | 333 | ]); 334 | FDFA.AddState(3, [ 335 | DFAEdge(0, 3) 336 | ]); 337 | FDFA.AddState(3, [ 338 | 339 | ]); 340 | FDFA.AddState(3, [ 341 | 342 | ]); 343 | FDFA.AddState(3, [ 344 | 345 | ]); 346 | FDFA.AddState(4, [ 347 | DFAEdge(4, 6) 348 | ]); 349 | FDFA.AddState(-1, [ 350 | DFAEdge(14, 8) 351 | ]); 352 | FDFA.AddState(6, [ 353 | 354 | ]); 355 | FDFA.AddState(7, [ 356 | 357 | ]); 358 | FDFA.AddState(8, [ 359 | 360 | ]); 361 | FDFA.AddState(9, [ 362 | 363 | ]); 364 | FDFA.AddState(10, [ 365 | 366 | ]); 367 | FDFA.AddState(11, [ 368 | 369 | ]); 370 | FDFA.AddState(12, [ 371 | 372 | ]); 373 | FDFA.AddState(-1, [ 374 | DFAEdge(14, 16) 375 | ]); 376 | FDFA.AddState(14, [ 377 | 378 | ]); 379 | FDFA.AddState(15, [ 380 | 381 | ]); 382 | FDFA.AddState(18, [ 383 | 384 | ]); 385 | FDFA.AddState(21, [ 386 | DFAEdge(26, 19) 387 | ]); 388 | FDFA.AddState(27, [ 389 | DFAEdge(27, 21) 390 | ]); 391 | FDFA.AddState(27, [ 392 | DFAEdge(27, 21) 393 | ]); 394 | FDFA.AddState(13, [ 395 | DFAEdge(17, 23) 396 | ]); 397 | FDFA.AddState(5, [ 398 | 399 | ]); 400 | FDFA.AddState(21, [ 401 | DFAEdge(26, 19), 402 | DFAEdge(28, 25) 403 | ]); 404 | FDFA.AddState(-1, [ 405 | DFAEdge(29, 26) 406 | ]); 407 | FDFA.AddState(26, [ 408 | DFAEdge(29, 26) 409 | ]); 410 | FDFA.AddState(16, [ 411 | DFAEdge(14, 28) 412 | ]); 413 | FDFA.AddState(17, [ 414 | 415 | ]); 416 | FDFA.AddState(19, [ 417 | DFAEdge(14, 30) 418 | ]); 419 | FDFA.AddState(20, [ 420 | 421 | ]); 422 | FDFA.AddState(27, [ 423 | DFAEdge(30, 21), 424 | DFAEdge(31, 32) 425 | ]); 426 | FDFA.AddState(22, [ 427 | DFAEdge(27, 21) 428 | ]); 429 | FDFA.AddState(27, [ 430 | DFAEdge(32, 21), 431 | DFAEdge(33, 34) 432 | ]); 433 | FDFA.AddState(27, [ 434 | DFAEdge(34, 21), 435 | DFAEdge(21, 35) 436 | ]); 437 | FDFA.AddState(23, [ 438 | DFAEdge(27, 21) 439 | ]); 440 | FDFA.AddState(27, [ 441 | DFAEdge(35, 21), 442 | DFAEdge(36, 37), 443 | DFAEdge(31, 41) 444 | ]); 445 | FDFA.AddState(27, [ 446 | DFAEdge(37, 21), 447 | DFAEdge(38, 38) 448 | ]); 449 | FDFA.AddState(27, [ 450 | DFAEdge(39, 21), 451 | DFAEdge(40, 39) 452 | ]); 453 | FDFA.AddState(27, [ 454 | DFAEdge(41, 21), 455 | DFAEdge(22, 40) 456 | ]); 457 | FDFA.AddState(24, [ 458 | DFAEdge(27, 21) 459 | ]); 460 | FDFA.AddState(27, [ 461 | DFAEdge(42, 21), 462 | DFAEdge(43, 42) 463 | ]); 464 | FDFA.AddState(25, [ 465 | DFAEdge(27, 21) 466 | ]); 467 | FDFA.AddState(27, [ 468 | DFAEdge(44, 21), 469 | DFAEdge(31, 44), 470 | DFAEdge(43, 45) 471 | ]); 472 | FDFA.AddState(28, [ 473 | DFAEdge(27, 21) 474 | ]); 475 | FDFA.AddState(27, [ 476 | DFAEdge(45, 21), 477 | DFAEdge(46, 46) 478 | ]); 479 | FDFA.AddState(27, [ 480 | DFAEdge(41, 21), 481 | DFAEdge(22, 47) 482 | ]); 483 | FDFA.AddState(29, [ 484 | DFAEdge(27, 21) 485 | ]); 486 | FDFA.AddState(27, [ 487 | DFAEdge(47, 21), 488 | DFAEdge(48, 49) 489 | ]); 490 | FDFA.AddState(27, [ 491 | DFAEdge(49, 21), 492 | DFAEdge(50, 50) 493 | ]); 494 | FDFA.AddState(27, [ 495 | DFAEdge(37, 21), 496 | DFAEdge(38, 51) 497 | ]); 498 | FDFA.AddState(27, [ 499 | DFAEdge(41, 21), 500 | DFAEdge(22, 52) 501 | ]); 502 | FDFA.AddState(30, [ 503 | DFAEdge(27, 21) 504 | ]); 505 | 506 | FLALR.AddState(TLRState.Create([ 507 | LRTransition(25, TLRActionType(1), 1), 508 | LRTransition(27, TLRActionType(1), 2), 509 | LRTransition(30, TLRActionType(1), 3), 510 | LRTransition(31, TLRActionType(3), 4), 511 | LRTransition(35, TLRActionType(3), 5), 512 | LRTransition(36, TLRActionType(3), 6), 513 | LRTransition(39, TLRActionType(3), 7), 514 | LRTransition(40, TLRActionType(3), 8), 515 | LRTransition(41, TLRActionType(3), 9), 516 | LRTransition(0, TLRActionType(2), 1) 517 | ])); 518 | FLALR.AddState(TLRState.Create([ 519 | LRTransition(27, TLRActionType(1), 10) 520 | ])); 521 | FLALR.AddState(TLRState.Create([ 522 | LRTransition(7, TLRActionType(1), 11), 523 | LRTransition(14, TLRActionType(1), 12) 524 | ])); 525 | FLALR.AddState(TLRState.Create([ 526 | LRTransition(7, TLRActionType(1), 13), 527 | LRTransition(21, TLRActionType(1), 14), 528 | LRTransition(24, TLRActionType(1), 15), 529 | LRTransition(26, TLRActionType(1), 16), 530 | LRTransition(27, TLRActionType(1), 17), 531 | LRTransition(29, TLRActionType(1), 18), 532 | LRTransition(32, TLRActionType(3), 19), 533 | LRTransition(33, TLRActionType(3), 20) 534 | ])); 535 | FLALR.AddState(TLRState.Create([ 536 | LRTransition(15, TLRActionType(2), 2) 537 | ])); 538 | FLALR.AddState(TLRState.Create([ 539 | LRTransition(15, TLRActionType(2), 4) 540 | ])); 541 | FLALR.AddState(TLRState.Create([ 542 | LRTransition(15, TLRActionType(2), 5) 543 | ])); 544 | FLALR.AddState(TLRState.Create([ 545 | LRTransition(15, TLRActionType(1), 21) 546 | ])); 547 | FLALR.AddState(TLRState.Create([ 548 | LRTransition(0, TLRActionType(4), 0) 549 | ])); 550 | FLALR.AddState(TLRState.Create([ 551 | LRTransition(15, TLRActionType(2), 3) 552 | ])); 553 | FLALR.AddState(TLRState.Create([ 554 | LRTransition(14, TLRActionType(1), 22) 555 | ])); 556 | FLALR.AddState(TLRState.Create([ 557 | LRTransition(7, TLRActionType(1), 13), 558 | LRTransition(21, TLRActionType(1), 14), 559 | LRTransition(24, TLRActionType(1), 15), 560 | LRTransition(26, TLRActionType(1), 16), 561 | LRTransition(27, TLRActionType(1), 17), 562 | LRTransition(29, TLRActionType(1), 18), 563 | LRTransition(32, TLRActionType(3), 19), 564 | LRTransition(33, TLRActionType(3), 23), 565 | LRTransition(34, TLRActionType(3), 24), 566 | LRTransition(38, TLRActionType(3), 25), 567 | LRTransition(8, TLRActionType(2), 11) 568 | ])); 569 | FLALR.AddState(TLRState.Create([ 570 | LRTransition(7, TLRActionType(1), 13), 571 | LRTransition(21, TLRActionType(1), 14), 572 | LRTransition(24, TLRActionType(1), 15), 573 | LRTransition(26, TLRActionType(1), 16), 574 | LRTransition(27, TLRActionType(1), 17), 575 | LRTransition(29, TLRActionType(1), 18), 576 | LRTransition(32, TLRActionType(3), 19), 577 | LRTransition(33, TLRActionType(3), 26) 578 | ])); 579 | FLALR.AddState(TLRState.Create([ 580 | LRTransition(7, TLRActionType(1), 13), 581 | LRTransition(21, TLRActionType(1), 14), 582 | LRTransition(24, TLRActionType(1), 15), 583 | LRTransition(26, TLRActionType(1), 16), 584 | LRTransition(27, TLRActionType(1), 17), 585 | LRTransition(29, TLRActionType(1), 18), 586 | LRTransition(32, TLRActionType(3), 19), 587 | LRTransition(33, TLRActionType(3), 27) 588 | ])); 589 | FLALR.AddState(TLRState.Create([ 590 | LRTransition(6, TLRActionType(2), 28), 591 | LRTransition(8, TLRActionType(2), 28), 592 | LRTransition(9, TLRActionType(2), 28), 593 | LRTransition(10, TLRActionType(2), 28), 594 | LRTransition(11, TLRActionType(2), 28), 595 | LRTransition(12, TLRActionType(2), 28), 596 | LRTransition(13, TLRActionType(2), 28), 597 | LRTransition(15, TLRActionType(2), 28), 598 | LRTransition(16, TLRActionType(2), 28), 599 | LRTransition(17, TLRActionType(2), 28), 600 | LRTransition(18, TLRActionType(2), 28), 601 | LRTransition(19, TLRActionType(2), 28), 602 | LRTransition(20, TLRActionType(2), 28), 603 | LRTransition(22, TLRActionType(2), 28), 604 | LRTransition(28, TLRActionType(2), 28) 605 | ])); 606 | FLALR.AddState(TLRState.Create([ 607 | LRTransition(6, TLRActionType(2), 31), 608 | LRTransition(8, TLRActionType(2), 31), 609 | LRTransition(9, TLRActionType(2), 31), 610 | LRTransition(10, TLRActionType(2), 31), 611 | LRTransition(11, TLRActionType(2), 31), 612 | LRTransition(12, TLRActionType(2), 31), 613 | LRTransition(13, TLRActionType(2), 31), 614 | LRTransition(15, TLRActionType(2), 31), 615 | LRTransition(16, TLRActionType(2), 31), 616 | LRTransition(17, TLRActionType(2), 31), 617 | LRTransition(18, TLRActionType(2), 31), 618 | LRTransition(19, TLRActionType(2), 31), 619 | LRTransition(20, TLRActionType(2), 31), 620 | LRTransition(22, TLRActionType(2), 31), 621 | LRTransition(28, TLRActionType(2), 31) 622 | ])); 623 | FLALR.AddState(TLRState.Create([ 624 | LRTransition(6, TLRActionType(2), 29), 625 | LRTransition(8, TLRActionType(2), 29), 626 | LRTransition(9, TLRActionType(2), 29), 627 | LRTransition(10, TLRActionType(2), 29), 628 | LRTransition(11, TLRActionType(2), 29), 629 | LRTransition(12, TLRActionType(2), 29), 630 | LRTransition(13, TLRActionType(2), 29), 631 | LRTransition(15, TLRActionType(2), 29), 632 | LRTransition(16, TLRActionType(2), 29), 633 | LRTransition(17, TLRActionType(2), 29), 634 | LRTransition(18, TLRActionType(2), 29), 635 | LRTransition(19, TLRActionType(2), 29), 636 | LRTransition(20, TLRActionType(2), 29), 637 | LRTransition(22, TLRActionType(2), 29), 638 | LRTransition(28, TLRActionType(2), 29) 639 | ])); 640 | FLALR.AddState(TLRState.Create([ 641 | LRTransition(6, TLRActionType(2), 17), 642 | LRTransition(8, TLRActionType(2), 17), 643 | LRTransition(9, TLRActionType(2), 17), 644 | LRTransition(10, TLRActionType(2), 17), 645 | LRTransition(11, TLRActionType(2), 17), 646 | LRTransition(12, TLRActionType(2), 17), 647 | LRTransition(13, TLRActionType(2), 17), 648 | LRTransition(15, TLRActionType(2), 17), 649 | LRTransition(16, TLRActionType(2), 17), 650 | LRTransition(17, TLRActionType(2), 17), 651 | LRTransition(18, TLRActionType(2), 17), 652 | LRTransition(19, TLRActionType(2), 17), 653 | LRTransition(20, TLRActionType(2), 17), 654 | LRTransition(22, TLRActionType(2), 17), 655 | LRTransition(28, TLRActionType(2), 17) 656 | ])); 657 | FLALR.AddState(TLRState.Create([ 658 | LRTransition(6, TLRActionType(2), 30), 659 | LRTransition(8, TLRActionType(2), 30), 660 | LRTransition(9, TLRActionType(2), 30), 661 | LRTransition(10, TLRActionType(2), 30), 662 | LRTransition(11, TLRActionType(2), 30), 663 | LRTransition(12, TLRActionType(2), 30), 664 | LRTransition(13, TLRActionType(2), 30), 665 | LRTransition(15, TLRActionType(2), 30), 666 | LRTransition(16, TLRActionType(2), 30), 667 | LRTransition(17, TLRActionType(2), 30), 668 | LRTransition(18, TLRActionType(2), 30), 669 | LRTransition(19, TLRActionType(2), 30), 670 | LRTransition(20, TLRActionType(2), 30), 671 | LRTransition(22, TLRActionType(2), 30), 672 | LRTransition(28, TLRActionType(2), 30) 673 | ])); 674 | FLALR.AddState(TLRState.Create([ 675 | LRTransition(6, TLRActionType(2), 16), 676 | LRTransition(8, TLRActionType(2), 16), 677 | LRTransition(9, TLRActionType(2), 16), 678 | LRTransition(10, TLRActionType(2), 16), 679 | LRTransition(11, TLRActionType(2), 16), 680 | LRTransition(12, TLRActionType(2), 16), 681 | LRTransition(13, TLRActionType(2), 16), 682 | LRTransition(15, TLRActionType(2), 16), 683 | LRTransition(16, TLRActionType(2), 16), 684 | LRTransition(17, TLRActionType(2), 16), 685 | LRTransition(18, TLRActionType(2), 16), 686 | LRTransition(19, TLRActionType(2), 16), 687 | LRTransition(20, TLRActionType(2), 16), 688 | LRTransition(22, TLRActionType(2), 16), 689 | LRTransition(28, TLRActionType(2), 16) 690 | ])); 691 | FLALR.AddState(TLRState.Create([ 692 | LRTransition(6, TLRActionType(1), 28), 693 | LRTransition(9, TLRActionType(1), 29), 694 | LRTransition(10, TLRActionType(1), 30), 695 | LRTransition(12, TLRActionType(1), 31), 696 | LRTransition(13, TLRActionType(1), 32), 697 | LRTransition(16, TLRActionType(1), 33), 698 | LRTransition(17, TLRActionType(1), 34), 699 | LRTransition(18, TLRActionType(1), 35), 700 | LRTransition(19, TLRActionType(1), 36), 701 | LRTransition(20, TLRActionType(1), 37), 702 | LRTransition(22, TLRActionType(1), 38), 703 | LRTransition(37, TLRActionType(3), 39) 704 | ])); 705 | FLALR.AddState(TLRState.Create([ 706 | LRTransition(25, TLRActionType(1), 1), 707 | LRTransition(27, TLRActionType(1), 2), 708 | LRTransition(30, TLRActionType(1), 3), 709 | LRTransition(31, TLRActionType(3), 4), 710 | LRTransition(35, TLRActionType(3), 5), 711 | LRTransition(36, TLRActionType(3), 6), 712 | LRTransition(39, TLRActionType(3), 7), 713 | LRTransition(40, TLRActionType(3), 40), 714 | LRTransition(41, TLRActionType(3), 9), 715 | LRTransition(0, TLRActionType(2), 1), 716 | LRTransition(23, TLRActionType(2), 1) 717 | ])); 718 | FLALR.AddState(TLRState.Create([ 719 | LRTransition(7, TLRActionType(1), 13), 720 | LRTransition(21, TLRActionType(1), 14), 721 | LRTransition(24, TLRActionType(1), 15), 722 | LRTransition(26, TLRActionType(1), 16), 723 | LRTransition(27, TLRActionType(1), 17), 724 | LRTransition(29, TLRActionType(1), 18), 725 | LRTransition(32, TLRActionType(3), 19), 726 | LRTransition(33, TLRActionType(3), 41) 727 | ])); 728 | FLALR.AddState(TLRState.Create([ 729 | LRTransition(6, TLRActionType(1), 28), 730 | LRTransition(9, TLRActionType(1), 29), 731 | LRTransition(10, TLRActionType(1), 30), 732 | LRTransition(11, TLRActionType(1), 42), 733 | LRTransition(12, TLRActionType(1), 31), 734 | LRTransition(13, TLRActionType(1), 32), 735 | LRTransition(16, TLRActionType(1), 33), 736 | LRTransition(17, TLRActionType(1), 34), 737 | LRTransition(18, TLRActionType(1), 35), 738 | LRTransition(19, TLRActionType(1), 36), 739 | LRTransition(20, TLRActionType(1), 37), 740 | LRTransition(37, TLRActionType(3), 39), 741 | LRTransition(8, TLRActionType(2), 13) 742 | ])); 743 | FLALR.AddState(TLRState.Create([ 744 | LRTransition(8, TLRActionType(2), 10) 745 | ])); 746 | FLALR.AddState(TLRState.Create([ 747 | LRTransition(8, TLRActionType(1), 43) 748 | ])); 749 | FLALR.AddState(TLRState.Create([ 750 | LRTransition(6, TLRActionType(1), 28), 751 | LRTransition(9, TLRActionType(1), 29), 752 | LRTransition(10, TLRActionType(1), 30), 753 | LRTransition(12, TLRActionType(1), 31), 754 | LRTransition(13, TLRActionType(1), 32), 755 | LRTransition(16, TLRActionType(1), 33), 756 | LRTransition(17, TLRActionType(1), 34), 757 | LRTransition(18, TLRActionType(1), 35), 758 | LRTransition(19, TLRActionType(1), 36), 759 | LRTransition(20, TLRActionType(1), 37), 760 | LRTransition(37, TLRActionType(3), 39), 761 | LRTransition(15, TLRActionType(2), 6) 762 | ])); 763 | FLALR.AddState(TLRState.Create([ 764 | LRTransition(6, TLRActionType(1), 28), 765 | LRTransition(8, TLRActionType(1), 44), 766 | LRTransition(9, TLRActionType(1), 29), 767 | LRTransition(10, TLRActionType(1), 30), 768 | LRTransition(12, TLRActionType(1), 31), 769 | LRTransition(13, TLRActionType(1), 32), 770 | LRTransition(16, TLRActionType(1), 33), 771 | LRTransition(17, TLRActionType(1), 34), 772 | LRTransition(18, TLRActionType(1), 35), 773 | LRTransition(19, TLRActionType(1), 36), 774 | LRTransition(20, TLRActionType(1), 37), 775 | LRTransition(37, TLRActionType(3), 39) 776 | ])); 777 | FLALR.AddState(TLRState.Create([ 778 | LRTransition(7, TLRActionType(2), 23), 779 | LRTransition(21, TLRActionType(2), 23), 780 | LRTransition(24, TLRActionType(2), 23), 781 | LRTransition(26, TLRActionType(2), 23), 782 | LRTransition(27, TLRActionType(2), 23), 783 | LRTransition(29, TLRActionType(2), 23) 784 | ])); 785 | FLALR.AddState(TLRState.Create([ 786 | LRTransition(7, TLRActionType(2), 20), 787 | LRTransition(21, TLRActionType(2), 20), 788 | LRTransition(24, TLRActionType(2), 20), 789 | LRTransition(26, TLRActionType(2), 20), 790 | LRTransition(27, TLRActionType(2), 20), 791 | LRTransition(29, TLRActionType(2), 20) 792 | ])); 793 | FLALR.AddState(TLRState.Create([ 794 | LRTransition(7, TLRActionType(2), 18), 795 | LRTransition(21, TLRActionType(2), 18), 796 | LRTransition(24, TLRActionType(2), 18), 797 | LRTransition(26, TLRActionType(2), 18), 798 | LRTransition(27, TLRActionType(2), 18), 799 | LRTransition(29, TLRActionType(2), 18) 800 | ])); 801 | FLALR.AddState(TLRState.Create([ 802 | LRTransition(7, TLRActionType(2), 19), 803 | LRTransition(21, TLRActionType(2), 19), 804 | LRTransition(24, TLRActionType(2), 19), 805 | LRTransition(26, TLRActionType(2), 19), 806 | LRTransition(27, TLRActionType(2), 19), 807 | LRTransition(29, TLRActionType(2), 19) 808 | ])); 809 | FLALR.AddState(TLRState.Create([ 810 | LRTransition(7, TLRActionType(2), 21), 811 | LRTransition(21, TLRActionType(2), 21), 812 | LRTransition(24, TLRActionType(2), 21), 813 | LRTransition(26, TLRActionType(2), 21), 814 | LRTransition(27, TLRActionType(2), 21), 815 | LRTransition(29, TLRActionType(2), 21) 816 | ])); 817 | FLALR.AddState(TLRState.Create([ 818 | LRTransition(7, TLRActionType(2), 24), 819 | LRTransition(21, TLRActionType(2), 24), 820 | LRTransition(24, TLRActionType(2), 24), 821 | LRTransition(26, TLRActionType(2), 24), 822 | LRTransition(27, TLRActionType(2), 24), 823 | LRTransition(29, TLRActionType(2), 24) 824 | ])); 825 | FLALR.AddState(TLRState.Create([ 826 | LRTransition(7, TLRActionType(2), 27), 827 | LRTransition(21, TLRActionType(2), 27), 828 | LRTransition(24, TLRActionType(2), 27), 829 | LRTransition(26, TLRActionType(2), 27), 830 | LRTransition(27, TLRActionType(2), 27), 831 | LRTransition(29, TLRActionType(2), 27) 832 | ])); 833 | FLALR.AddState(TLRState.Create([ 834 | LRTransition(7, TLRActionType(2), 22), 835 | LRTransition(21, TLRActionType(2), 22), 836 | LRTransition(24, TLRActionType(2), 22), 837 | LRTransition(26, TLRActionType(2), 22), 838 | LRTransition(27, TLRActionType(2), 22), 839 | LRTransition(29, TLRActionType(2), 22) 840 | ])); 841 | FLALR.AddState(TLRState.Create([ 842 | LRTransition(7, TLRActionType(2), 25), 843 | LRTransition(21, TLRActionType(2), 25), 844 | LRTransition(24, TLRActionType(2), 25), 845 | LRTransition(26, TLRActionType(2), 25), 846 | LRTransition(27, TLRActionType(2), 25), 847 | LRTransition(29, TLRActionType(2), 25) 848 | ])); 849 | FLALR.AddState(TLRState.Create([ 850 | LRTransition(7, TLRActionType(2), 26), 851 | LRTransition(21, TLRActionType(2), 26), 852 | LRTransition(24, TLRActionType(2), 26), 853 | LRTransition(26, TLRActionType(2), 26), 854 | LRTransition(27, TLRActionType(2), 26), 855 | LRTransition(29, TLRActionType(2), 26) 856 | ])); 857 | FLALR.AddState(TLRState.Create([ 858 | LRTransition(25, TLRActionType(1), 1), 859 | LRTransition(27, TLRActionType(1), 2), 860 | LRTransition(30, TLRActionType(1), 3), 861 | LRTransition(31, TLRActionType(3), 4), 862 | LRTransition(35, TLRActionType(3), 5), 863 | LRTransition(36, TLRActionType(3), 6), 864 | LRTransition(39, TLRActionType(3), 7), 865 | LRTransition(40, TLRActionType(3), 45), 866 | LRTransition(41, TLRActionType(3), 9), 867 | LRTransition(23, TLRActionType(2), 1) 868 | ])); 869 | FLALR.AddState(TLRState.Create([ 870 | LRTransition(7, TLRActionType(1), 13), 871 | LRTransition(21, TLRActionType(1), 14), 872 | LRTransition(24, TLRActionType(1), 15), 873 | LRTransition(26, TLRActionType(1), 16), 874 | LRTransition(27, TLRActionType(1), 17), 875 | LRTransition(29, TLRActionType(1), 18), 876 | LRTransition(32, TLRActionType(3), 19), 877 | LRTransition(33, TLRActionType(3), 46) 878 | ])); 879 | FLALR.AddState(TLRState.Create([ 880 | LRTransition(0, TLRActionType(2), 0), 881 | LRTransition(23, TLRActionType(2), 0) 882 | ])); 883 | FLALR.AddState(TLRState.Create([ 884 | LRTransition(6, TLRActionType(1), 28), 885 | LRTransition(9, TLRActionType(1), 29), 886 | LRTransition(10, TLRActionType(1), 30), 887 | LRTransition(12, TLRActionType(1), 31), 888 | LRTransition(13, TLRActionType(1), 32), 889 | LRTransition(16, TLRActionType(1), 33), 890 | LRTransition(17, TLRActionType(1), 34), 891 | LRTransition(18, TLRActionType(1), 35), 892 | LRTransition(19, TLRActionType(1), 36), 893 | LRTransition(20, TLRActionType(1), 37), 894 | LRTransition(28, TLRActionType(1), 47), 895 | LRTransition(37, TLRActionType(3), 39) 896 | ])); 897 | FLALR.AddState(TLRState.Create([ 898 | LRTransition(7, TLRActionType(1), 13), 899 | LRTransition(21, TLRActionType(1), 14), 900 | LRTransition(24, TLRActionType(1), 15), 901 | LRTransition(26, TLRActionType(1), 16), 902 | LRTransition(27, TLRActionType(1), 17), 903 | LRTransition(29, TLRActionType(1), 18), 904 | LRTransition(32, TLRActionType(3), 19), 905 | LRTransition(33, TLRActionType(3), 23), 906 | LRTransition(34, TLRActionType(3), 48) 907 | ])); 908 | FLALR.AddState(TLRState.Create([ 909 | LRTransition(15, TLRActionType(2), 9) 910 | ])); 911 | FLALR.AddState(TLRState.Create([ 912 | LRTransition(6, TLRActionType(2), 14), 913 | LRTransition(8, TLRActionType(2), 14), 914 | LRTransition(9, TLRActionType(2), 14), 915 | LRTransition(10, TLRActionType(2), 14), 916 | LRTransition(11, TLRActionType(2), 14), 917 | LRTransition(12, TLRActionType(2), 14), 918 | LRTransition(13, TLRActionType(2), 14), 919 | LRTransition(15, TLRActionType(2), 14), 920 | LRTransition(16, TLRActionType(2), 14), 921 | LRTransition(17, TLRActionType(2), 14), 922 | LRTransition(18, TLRActionType(2), 14), 923 | LRTransition(19, TLRActionType(2), 14), 924 | LRTransition(20, TLRActionType(2), 14), 925 | LRTransition(22, TLRActionType(2), 14), 926 | LRTransition(28, TLRActionType(2), 14) 927 | ])); 928 | FLALR.AddState(TLRState.Create([ 929 | LRTransition(23, TLRActionType(1), 49) 930 | ])); 931 | FLALR.AddState(TLRState.Create([ 932 | LRTransition(6, TLRActionType(1), 28), 933 | LRTransition(9, TLRActionType(1), 29), 934 | LRTransition(10, TLRActionType(1), 30), 935 | LRTransition(12, TLRActionType(1), 31), 936 | LRTransition(13, TLRActionType(1), 32), 937 | LRTransition(16, TLRActionType(1), 33), 938 | LRTransition(17, TLRActionType(1), 34), 939 | LRTransition(18, TLRActionType(1), 35), 940 | LRTransition(19, TLRActionType(1), 36), 941 | LRTransition(20, TLRActionType(1), 37), 942 | LRTransition(37, TLRActionType(3), 39), 943 | LRTransition(8, TLRActionType(2), 15), 944 | LRTransition(11, TLRActionType(2), 15), 945 | LRTransition(15, TLRActionType(2), 15), 946 | LRTransition(22, TLRActionType(2), 15), 947 | LRTransition(28, TLRActionType(2), 15) 948 | ])); 949 | FLALR.AddState(TLRState.Create([ 950 | LRTransition(7, TLRActionType(1), 13), 951 | LRTransition(21, TLRActionType(1), 14), 952 | LRTransition(24, TLRActionType(1), 15), 953 | LRTransition(26, TLRActionType(1), 16), 954 | LRTransition(27, TLRActionType(1), 17), 955 | LRTransition(29, TLRActionType(1), 18), 956 | LRTransition(32, TLRActionType(3), 19), 957 | LRTransition(33, TLRActionType(3), 50) 958 | ])); 959 | FLALR.AddState(TLRState.Create([ 960 | LRTransition(8, TLRActionType(2), 12) 961 | ])); 962 | FLALR.AddState(TLRState.Create([ 963 | LRTransition(15, TLRActionType(2), 7) 964 | ])); 965 | FLALR.AddState(TLRState.Create([ 966 | LRTransition(6, TLRActionType(1), 28), 967 | LRTransition(9, TLRActionType(1), 29), 968 | LRTransition(10, TLRActionType(1), 30), 969 | LRTransition(12, TLRActionType(1), 31), 970 | LRTransition(13, TLRActionType(1), 32), 971 | LRTransition(16, TLRActionType(1), 33), 972 | LRTransition(17, TLRActionType(1), 34), 973 | LRTransition(18, TLRActionType(1), 35), 974 | LRTransition(19, TLRActionType(1), 36), 975 | LRTransition(20, TLRActionType(1), 37), 976 | LRTransition(22, TLRActionType(1), 51), 977 | LRTransition(37, TLRActionType(3), 39) 978 | ])); 979 | FLALR.AddState(TLRState.Create([ 980 | LRTransition(25, TLRActionType(1), 1), 981 | LRTransition(27, TLRActionType(1), 2), 982 | LRTransition(30, TLRActionType(1), 3), 983 | LRTransition(31, TLRActionType(3), 4), 984 | LRTransition(35, TLRActionType(3), 5), 985 | LRTransition(36, TLRActionType(3), 6), 986 | LRTransition(39, TLRActionType(3), 7), 987 | LRTransition(40, TLRActionType(3), 52), 988 | LRTransition(41, TLRActionType(3), 9), 989 | LRTransition(23, TLRActionType(2), 1) 990 | ])); 991 | FLALR.AddState(TLRState.Create([ 992 | LRTransition(23, TLRActionType(1), 53) 993 | ])); 994 | FLALR.AddState(TLRState.Create([ 995 | LRTransition(15, TLRActionType(2), 8) 996 | ])); 997 | 998 | FDFA.SetInitialState(0); 999 | FLALR.SetInitialState(0); 1000 | 1001 | FLALR.AddRule(LRRule(40, [39, 15, 40])); 1002 | FLALR.AddRule(LRRule(40, [])); 1003 | FLALR.AddRule(LRRule(39, [31])); 1004 | FLALR.AddRule(LRRule(39, [41])); 1005 | FLALR.AddRule(LRRule(39, [35])); 1006 | FLALR.AddRule(LRRule(39, [36])); 1007 | FLALR.AddRule(LRRule(31, [27, 14, 33])); 1008 | FLALR.AddRule(LRRule(41, [30, 33, 22, 40, 23])); 1009 | FLALR.AddRule(LRRule(35, [25, 27, 14, 33, 28, 33, 22, 40, 23])); 1010 | FLALR.AddRule(LRRule(36, [27, 7, 38, 8])); 1011 | FLALR.AddRule(LRRule(38, [34])); 1012 | FLALR.AddRule(LRRule(38, [])); 1013 | FLALR.AddRule(LRRule(34, [33, 11, 34])); 1014 | FLALR.AddRule(LRRule(34, [33])); 1015 | FLALR.AddRule(LRRule(33, [7, 33, 8])); 1016 | FLALR.AddRule(LRRule(33, [33, 37, 33])); 1017 | FLALR.AddRule(LRRule(33, [32])); 1018 | FLALR.AddRule(LRRule(33, [27])); 1019 | FLALR.AddRule(LRRule(37, [10])); 1020 | FLALR.AddRule(LRRule(37, [12])); 1021 | FLALR.AddRule(LRRule(37, [9])); 1022 | FLALR.AddRule(LRRule(37, [13])); 1023 | FLALR.AddRule(LRRule(37, [18])); 1024 | FLALR.AddRule(LRRule(37, [6])); 1025 | FLALR.AddRule(LRRule(37, [16])); 1026 | FLALR.AddRule(LRRule(37, [19])); 1027 | FLALR.AddRule(LRRule(37, [20])); 1028 | FLALR.AddRule(LRRule(37, [17])); 1029 | FLALR.AddRule(LRRule(32, [21])); 1030 | FLALR.AddRule(LRRule(32, [26])); 1031 | FLALR.AddRule(LRRule(32, [29])); 1032 | FLALR.AddRule(LRRule(32, [24])); 1033 | 1034 | FDFA.AddGroup(Group('Comment Line', 2, 5, 3, gaCharwise, geOpen, [])); 1035 | 1036 | Prepare(SymbolList); 1037 | finally 1038 | SymbolList.Free; 1039 | end; 1040 | end; 1041 | 1042 | 1043 | end. 1044 | 1045 | --------------------------------------------------------------------------------