951 lines
39 KiB
ObjectPascal
951 lines
39 KiB
ObjectPascal
unit dpglib.GrammarBehavior;
|
|
|
|
interface
|
|
uses
|
|
System.Classes,
|
|
dpgrtl.types,
|
|
dpglib.Types;
|
|
|
|
type
|
|
TGrammarBehavior = class( TInterfacedObject, IGrammarBehavior)
|
|
protected
|
|
fGrammar : IGrammar;
|
|
fTool : ITool;
|
|
fAnalyzer : ILLkAnalyzer;
|
|
fUsesList : TStringList;
|
|
|
|
fIsLexer : boolean;
|
|
fIsParser : boolean;
|
|
fIsTreeWalker : boolean;
|
|
|
|
fLexerGrammar : ILexerGrammar;
|
|
fParserGrammar : IParserGrammar;
|
|
fTreeWalkerGrammar: ITreeWalkerGrammar;
|
|
|
|
fLanguage : AnsiString;
|
|
fExchangeDir : AnsiString;
|
|
|
|
fConstAction : IToken;
|
|
fTypeAction : IToken;
|
|
|
|
protected
|
|
// ------------------------------------------------------------
|
|
// _RefRule
|
|
// ------------------------------------------------------------
|
|
procedure _RefStringLiteral( pLiteral : IToken);
|
|
procedure _RefToken( pToken : IToken);
|
|
procedure _RefRule( pRuleName : IToken);
|
|
|
|
public
|
|
constructor Create( pTool : ITool;
|
|
pAnalyzer : ILLkAnalyzer;
|
|
pExchangeDir : AnsiString);
|
|
destructor Destroy; override;
|
|
|
|
public
|
|
// ------------------------------------------------------------
|
|
// IGrammarBehavior methods
|
|
// ------------------------------------------------------------
|
|
function Grammar: IGrammar;
|
|
|
|
procedure AbortGrammar; virtual;
|
|
|
|
procedure BeginAlt( pDoAST: boolean); virtual; abstract;
|
|
procedure BeginExceptionGroup; virtual; abstract;
|
|
procedure BeginExceptionSpec( pLabel : IToken); virtual; abstract;
|
|
|
|
procedure BeginSubRule( pLabel : IToken;
|
|
pStart : IToken;
|
|
pNot : boolean); virtual; abstract;
|
|
|
|
procedure BeginTree( pStart : IToken); virtual; abstract;
|
|
procedure BeginChildList; virtual; abstract;
|
|
|
|
|
|
|
|
procedure DefineGrammarUnit( pUnit : AnsiString); virtual;
|
|
procedure DefineRuleName( pRule : IToken;
|
|
pAccess : AnsiString;
|
|
pRuleAutoGen : boolean;
|
|
pDocComment : AnsiString); virtual;
|
|
|
|
procedure DefineToken( pTokenName : IToken;
|
|
pTokenLiteral : IToken); virtual;
|
|
|
|
procedure DefineUses( pUses : AnsiString); virtual;
|
|
|
|
procedure EndAlt; virtual; abstract;
|
|
procedure EndExceptionGroup; virtual; abstract;
|
|
procedure EndExceptionSpec; virtual; abstract;
|
|
procedure EndGrammar; virtual; abstract;
|
|
procedure EndOptions; virtual;
|
|
procedure EndRule( pRuleName : AnsiString); virtual; abstract;
|
|
procedure EndSubRule; virtual; abstract;
|
|
procedure EndTree; virtual; abstract;
|
|
procedure EndChildList; virtual; abstract;
|
|
|
|
procedure HasError; virtual; abstract;
|
|
|
|
procedure NoASTSubRule; virtual; abstract;
|
|
procedure OneOrMoreSubRule; virtual; abstract;
|
|
procedure NMSubRule; virtual; abstract;
|
|
procedure OptionalSubRule; virtual; abstract;
|
|
|
|
procedure refRangeLow( M : integer); virtual; abstract;
|
|
procedure refRangeHigh( N : integer); virtual; abstract;
|
|
|
|
procedure RefAction( pAction : IToken); virtual; abstract;
|
|
procedure RefArgAction( pAction : IToken); virtual; abstract;
|
|
|
|
procedure RefCharLiteral( pLiteral : IToken;
|
|
pLabel : IToken;
|
|
pInverted : boolean;
|
|
pAutoGenType : integer;
|
|
pLastInRule : boolean); virtual; abstract;
|
|
|
|
procedure RefCharRange( pToken1 : IToken;
|
|
pToken2 : IToken;
|
|
pLabel : IToken;
|
|
pAutoGenType : integer;
|
|
pLastInRule : boolean); virtual; abstract;
|
|
|
|
procedure RefConstAction( pConstAction : IToken); virtual;
|
|
procedure RefTypeAction( pTypeAction : IToken); virtual;
|
|
|
|
|
|
procedure RefElemOption( pOption : IToken;
|
|
pValue : IToken); virtual; abstract;
|
|
|
|
procedure RefTokenSpecElemOption( pToken : IToken;
|
|
pOption : IToken;
|
|
pValue : IToken); virtual; abstract;
|
|
|
|
procedure RefExceptionHandler( pTypeAndName : IToken;
|
|
pAction : IToken); virtual; abstract;
|
|
|
|
procedure RefInitAction( pAction : IToken); virtual; abstract;
|
|
procedure RefMemberDecl( pDecl : IToken); virtual;
|
|
procedure RefMemberDef( pDef : IToken); virtual;
|
|
procedure RefReturnAction( pAction : IToken); virtual; abstract;
|
|
|
|
procedure RefRule( pAssignId : IToken;
|
|
pRuleName : IToken;
|
|
pLabel : IToken;
|
|
pArguments : IToken;
|
|
pAutoGenType : integer); virtual;
|
|
|
|
procedure RefRuleExHandler( pExHandlerType : IToken;
|
|
pExHandlerCode : IToken); virtual; abstract;
|
|
procedure RefAltExHandler( pExHandlerType : IToken;
|
|
pExHandlerCode : IToken); virtual; abstract;
|
|
|
|
procedure RefRuleLocals( pLocals : IToken); virtual; abstract;
|
|
procedure RefSemPred( pSemPred : IToken); virtual; abstract;
|
|
|
|
procedure RefStringLiteral( pLiteral : IToken;
|
|
pLabel : IToken;
|
|
pAutoGenType : integer;
|
|
pLastInRule : boolean); virtual;
|
|
|
|
procedure RefToken( pAssignId : IToken;
|
|
pToken : IToken;
|
|
pLabel : IToken;
|
|
pArguments : IToken;
|
|
pInverted : boolean;
|
|
pAutoGenType : integer;
|
|
pLAstInRule : boolean); virtual;
|
|
|
|
procedure RefTokenRange( pToken1 : IToken;
|
|
pToken2 : IToken;
|
|
pLabel : IToken;
|
|
pAutoGenType : integer;
|
|
pLastInRule : boolean); virtual;
|
|
|
|
|
|
procedure RefWildCard( pToken : IToken;
|
|
pLabel : IToken;
|
|
pAutoGenType : integer); virtual; abstract;
|
|
|
|
|
|
procedure Reset; virtual;
|
|
|
|
procedure SetArgOfRuleRef( pArguments : IToken); virtual; abstract;
|
|
procedure SetCharVocabulary( pVocabulary : TByteSet);virtual;
|
|
|
|
procedure setFileOption( poption : IToken;
|
|
pValue : IToken;
|
|
pFileName : AnsiString); virtual;
|
|
|
|
procedure SetGrammarOption( pOption : IToken;
|
|
pValue : IToken); virtual;
|
|
|
|
procedure setRuleOption( pOption : IToken;
|
|
pValue : IToken); virtual; abstract;
|
|
|
|
procedure SetSubRuleOption( pOption : IToken;
|
|
pValue : IToken); virtual; abstract;
|
|
|
|
procedure SetUserExceptions( pException : AnsiString); virtual; abstract;
|
|
|
|
procedure StartLexer( pFileName : AnsiString;
|
|
pLexerName : IToken;
|
|
pSuperClass : IToken);
|
|
|
|
procedure StartParser( pFileName : AnsiString;
|
|
pParserName : IToken;
|
|
pSuperClass : IToken);
|
|
|
|
|
|
procedure StartTreeWalker( pFileName : AnsiString;
|
|
pParserName : IToken;
|
|
pSuperClass : IToken);
|
|
|
|
procedure SynPred; virtual; abstract;
|
|
procedure ZeroOrMoreSubRule; virtual; abstract;
|
|
end;
|
|
|
|
implementation
|
|
uses
|
|
System.SysUtils,
|
|
dpglib.Utils,
|
|
dpglib.Messages,
|
|
dpglib.DpgParserTokens,
|
|
dpglib.TokenSymbol,
|
|
dpglib.StringSymbol,
|
|
dpglib.RuleSymbol,
|
|
dpglib.LexerGrammar,
|
|
dpglib.ParserGrammar,
|
|
dpglib.TreeParserGrammar,
|
|
dpglib.CodeGenerator;
|
|
|
|
// ****************************************************************************
|
|
// Constructor/destructor
|
|
// ****************************************************************************
|
|
// ----------------------------------------------------------------------------
|
|
// Constructor
|
|
// ----------------------------------------------------------------------------
|
|
constructor TGrammarBehavior.Create(pTool : ITool;
|
|
pAnalyzer : ILLkAnalyzer;
|
|
pExchangeDir: AnsiString);
|
|
|
|
begin
|
|
inherited Create;
|
|
|
|
fTool := pTool;
|
|
fAnalyzer := pAnalyzer;
|
|
|
|
fLexerGrammar := nil;
|
|
fParserGrammar := nil;
|
|
fTreeWalkerGrammar:= nil;
|
|
|
|
fIsLexer := false;
|
|
fIsParser := false;
|
|
fIsTreeWalker := false;
|
|
|
|
fConstAction := nil;
|
|
fTypeAction := nil;
|
|
|
|
fLanguage := 'Delphi';
|
|
fExchangeDir := pExchangeDir;
|
|
|
|
if fExchangeDir <> '' then
|
|
if fExchangeDir[Length(fExchangeDir)] <> '\' then
|
|
fExchangeDir := fExchangeDir + '\';
|
|
end;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Destructor
|
|
// ----------------------------------------------------------------------------
|
|
destructor TGrammarBehavior.Destroy;
|
|
begin
|
|
fTool := nil;
|
|
fAnalyzer := nil;
|
|
|
|
fLexerGrammar := nil;
|
|
fParserGrammar := nil;
|
|
fTreeWalkerGrammar:= nil;
|
|
|
|
fIsLexer := false;
|
|
fIsParser := false;
|
|
fIsTreeWalker := false;
|
|
|
|
inherited;
|
|
end;
|
|
|
|
// @@@: IGrammarBehavior implementation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// IGrammarBehavior implementation
|
|
//
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ================================================================================================
|
|
// DefineGrammarUnit
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.DefineGrammarUnit(pUnit: AnsiString);
|
|
begin
|
|
fGrammar.UnitName := pUnit;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// DefineRuleName
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.DefineRuleName( pRule : IToken;
|
|
pAccess : AnsiString;
|
|
pRuleAutoGen: boolean;
|
|
pDocComment : AnsiString);
|
|
var
|
|
id: AnsiString;
|
|
ts: ITokenSymbol;
|
|
rs: IRuleSymbol;
|
|
|
|
begin
|
|
id := pRule.TokenText;
|
|
|
|
// ---------------------------------------------------------------
|
|
// Handle lexer rule definition. Lexer rule name must be TOKENREF,
|
|
// what means: must begin with capital letter.
|
|
// ---------------------------------------------------------------
|
|
if( pRule.TokenType = TT_TOKENREF) then
|
|
begin
|
|
// ------------------------------------------------------------
|
|
// construct valid name for it...
|
|
// ------------------------------------------------------------
|
|
id := TCodeGenerator.encodeLexerRuleName( id);
|
|
|
|
// ------------------------------------------------------------
|
|
// If this token not defined in TokenManager, define it. This
|
|
// happens when the rule definition is before any reference to
|
|
// this rule.
|
|
// ------------------------------------------------------------
|
|
if not fGrammar.TokenManager.TokenDefined[ pRule.TokenText] then
|
|
begin
|
|
ts := TTokenSymbol.Create( pRule.TokenText);
|
|
ts.TokenType:= fGrammar.TokenManager.NextTokenType;
|
|
|
|
fGrammar.TokenManager.Define( ts);
|
|
end;
|
|
end;
|
|
|
|
// ---------------------------------------------------------------
|
|
// Check if the rule is already defined in the grammar. If so,
|
|
// show an error message. In this case the generated code is not
|
|
// usable....
|
|
// ---------------------------------------------------------------
|
|
if fGrammar.Defined( id) then
|
|
begin
|
|
fGrammar.Symbol[id].QueryInterface(IRuleSymbol,rs);
|
|
|
|
if rs.Defined then
|
|
begin
|
|
fTool.Error( Format( MSG_E_RULEREDEF,[ id]),
|
|
fGrammar.GrammarFile,
|
|
pRule.TokenLine,
|
|
pRule.TokenColumn);
|
|
end;
|
|
end
|
|
|
|
// ---------------------------------------------------------------
|
|
// ... else the grammar isn't defined, so define it.
|
|
// ---------------------------------------------------------------
|
|
else
|
|
begin
|
|
rs := TRuleSymbol.Create( id);
|
|
fGrammar.Define( rs);
|
|
end;
|
|
|
|
rs.Defined := true;
|
|
rs.Access := pAccess;
|
|
rs.Comment := pDocComment;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// DefineToken
|
|
//
|
|
// Define a token from tokens {...}.
|
|
// Must be label and literal or just label or just a literal.
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.DefineToken( pTokenName : IToken;
|
|
pTokenLiteral : IToken);
|
|
var
|
|
i : integer;
|
|
name : AnsiString;
|
|
literal : AnsiString;
|
|
ss : IStringSymbol;
|
|
sx : IStringSymbol;
|
|
ts : ITokenSymbol;
|
|
|
|
begin
|
|
name := '';
|
|
literal := '';
|
|
|
|
if pTokenName <> nil then name := pTokenName.TokenText;
|
|
if pTokenLiteral <> nil then literal := pTokenLiteral.TokenText;
|
|
|
|
// ---------------------------------------------------------------
|
|
// The literal must be a string of printable characters surrounded
|
|
// by '"'s. See: dpglib.utils.
|
|
// ---------------------------------------------------------------
|
|
if literal <> '' then
|
|
begin
|
|
for i:=2 to Length(literal) -1 do
|
|
begin
|
|
if not IsPrint( literal[i]) then
|
|
begin
|
|
fTool.Error( Format( MSG_E_INVSTRINGLITERAL,[ literal]),
|
|
fGrammar.GrammarFile,
|
|
pTokenLiteral.TokenLine,
|
|
pTokenLiteral.TokenColumn);
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// ---------------------------------------------------------------
|
|
// OK the literal passed the test, so go...
|
|
// ---------------------------------------------------------------
|
|
if literal <> '' then
|
|
begin
|
|
ss := nil;
|
|
ts := fGrammar.TokenManager.TokenSymbol[ literal];
|
|
|
|
if ts <> nil then
|
|
ts.QueryInterface( IStringSymbol,ss);
|
|
|
|
if ss <> nil then
|
|
begin
|
|
// ---------------------------------------------------------
|
|
// This literal is known already.
|
|
// If the literal has no label already, but we can provide
|
|
// one here, then no problem, just map the label to the literal
|
|
// and don't change anything else.
|
|
// Otherwise, labels conflict: error.
|
|
// ---------------------------------------------------------
|
|
if (name = '') or (ss.Lbl <> '') then
|
|
begin
|
|
fTool.Warning( Format( MSG_W_TOKENSREDEF,[ literal]),
|
|
fGrammar.GrammarFile,
|
|
pTokenLiteral.TokenLine,
|
|
pTokenLiteral.TokenColumn);
|
|
exit;
|
|
end
|
|
|
|
// ---------------------------------------------------------
|
|
// The literal had no label, but new def does. Set it.
|
|
// ---------------------------------------------------------
|
|
else if name <> '' then
|
|
begin
|
|
ss.Lbl := name;
|
|
fGrammar.TokenManager.MapToTokenSymbol( name, ss);
|
|
end;
|
|
end;
|
|
|
|
// ------------------------------------------------------------
|
|
// if they provide a name/label and that name/label already
|
|
// exists, just hook this literal onto old token.
|
|
// ------------------------------------------------------------
|
|
if name <> '' then
|
|
begin
|
|
ts := fGrammar.TokenManager.TokenSymbol[ name];
|
|
|
|
if ts <> nil then
|
|
begin
|
|
// ------------------------------------------------------
|
|
// Watch out that the label is not more than just a token.
|
|
// If it already has a literal attached, then: conflict.
|
|
// ------------------------------------------------------
|
|
if ts.QueryInterface( IStringSymbol, sx) = S_OK then
|
|
begin
|
|
fTool.Warning( Format( MSG_W_TOKENSREDEF,[ name]),
|
|
fGrammar.GrammarFile,
|
|
pTokenName.TokenLine,
|
|
pTokenName.TokenColumn);
|
|
exit;
|
|
end;
|
|
|
|
// ------------------------------------------------------
|
|
// A simple token symbol such as DECL is defined must
|
|
// convert it to a AnsiStringLiteralSymbol with a label by
|
|
// co-opting token type and killing old TokenSymbol.
|
|
// Kill mapping and entry in vector of token manager.
|
|
// ------------------------------------------------------
|
|
|
|
// ------------------------------------------------------
|
|
// Now create AnsiString literal with label.
|
|
// ------------------------------------------------------
|
|
ss := TStringSymbol.Create( literal);
|
|
ss.TokenType := ts.TokenType;
|
|
ss.Lbl := name;
|
|
|
|
// ------------------------------------------------------
|
|
// Redefine this critter as a AnsiString literal.
|
|
// ------------------------------------------------------
|
|
fGrammar.TokenManager.Define( ss);
|
|
|
|
// ------------------------------------------------------
|
|
// Make sure the label can be used also.
|
|
// ------------------------------------------------------
|
|
fGrammar.TokenManager.MapToTokenSymbol( name, ss);
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
// ------------------------------------------------------------
|
|
// Here, literal was labeled but not by a known token symbol.
|
|
// ------------------------------------------------------------
|
|
ss := TStringSymbol.Create( literal);
|
|
ss.TokenType:= fGrammar.TokenManager.NextTokenType;
|
|
ss.Lbl := name;
|
|
|
|
fGrammar.TokenManager.Define(ss);
|
|
|
|
if name <> '' then
|
|
fGrammar.TokenManager.MapToTokenSymbol( name, ss);
|
|
end
|
|
|
|
// ---------------------------------------------------------------
|
|
// Create a token in the token manager not a literal.
|
|
// ---------------------------------------------------------------
|
|
else
|
|
begin
|
|
if fGrammar.TokenManager.TokenDefined[ name] then
|
|
begin
|
|
fTool.Warning( Format( MSG_W_TOKENSREDEF,[ name]),
|
|
fGrammar.GrammarFile,
|
|
pTokenName.TokenLine,
|
|
pTokenname.TokenColumn);
|
|
exit;
|
|
end;
|
|
|
|
ts := TTokenSymbol.Create( name);
|
|
ts.TokenType:= fGrammar.TokenManager.NextTokenType;
|
|
|
|
fGrammar.TokenManager.Define(ts);
|
|
end;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// DefineUses
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.DefineUses(pUses: AnsiString);
|
|
begin
|
|
fGrammar.UsesList.Add( pUses);
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// EndOptions
|
|
//
|
|
// Called after the optional options section, to compensate for options that
|
|
// may not have been set.
|
|
// This method is bigger than it needs to be, but is much more clear if I
|
|
// delineate all the cases.
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.EndOptions;
|
|
begin
|
|
{ TODO : EndOptions not implemented... }
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// refRule
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.refRule( pAssignId : IToken;
|
|
pRuleName : IToken;
|
|
pLabel : IToken;
|
|
pArguments : IToken;
|
|
pAutoGenType: integer);
|
|
begin
|
|
_refRule( pRuleName);
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// RefStringLiteral
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.refStringLiteral( pLiteral : IToken;
|
|
pLabel : IToken;
|
|
pAutoGenType : integer;
|
|
pLastInRule : boolean);
|
|
begin
|
|
_refStringLiteral( pLiteral);
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// RefToken
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.refToken( pAssignId : IToken;
|
|
pToken : IToken;
|
|
pLabel : IToken;
|
|
pArguments : IToken;
|
|
pInverted : boolean;
|
|
pAutoGenType : integer;
|
|
pLAstInRule : boolean);
|
|
begin
|
|
_refToken( pToken);
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// RefTokenRange
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.refTokenRange( pToken1 : IToken;
|
|
pToken2 : IToken;
|
|
pLabel : IToken;
|
|
pAutoGenType : integer;
|
|
pLastInRule : boolean);
|
|
begin
|
|
// ---------------------------------------------------------------
|
|
// Ensure that the DefineGrammar methods are called;
|
|
// otherwise a range addes more token refs to the alternative by
|
|
// calling MakeGrammar.refToken etc...
|
|
// ---------------------------------------------------------------
|
|
if pToken1.TokenText[1] = '"' then
|
|
_refStringLiteral( pToken1)
|
|
else
|
|
_RefToken( pToken1);
|
|
|
|
if pToken2.TokenText[1] = '"' then
|
|
_RefStringLiteral( pToken2)
|
|
else
|
|
_RefToken( pToken2);
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// SetCharVocabulary
|
|
//
|
|
// Set the character vocabulary for a lexer.
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.SetCharVocabulary(pVocabulary: TByteSet);
|
|
begin
|
|
if fIsLexer then
|
|
fLexerGrammar.CharVocabulary := pVocabulary;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// SetFileOption
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.SetFileOption( pOption : IToken;
|
|
pValue : IToken;
|
|
pFileName: AnsiString);
|
|
begin
|
|
// ---------------------------------------------------------------
|
|
// Option: language
|
|
// ---------------------------------------------------------------
|
|
if pOption.TokenText = 'language' then
|
|
if pValue.TokenType = TT_STRINGLIT then
|
|
fLanguage := Copy(pValue.TokenText,2,Length(pValue.TokenText)-2)
|
|
|
|
else if pValue.TokenType in [TT_TOKENREF,TT_RULEREF] then
|
|
fLanguage := pValue.TokenText
|
|
|
|
else
|
|
fTool.Error( 'option "language" must be a AnsiString or identifier',
|
|
fGrammar.GrammarFile,
|
|
pValue.TokenLine,
|
|
pValue.TokenColumn)
|
|
|
|
// ---------------------------------------------------------------
|
|
// Other option is error
|
|
// ---------------------------------------------------------------
|
|
else
|
|
fTool.Error( 'Invalid file-level option: "' + poption.TokenText + '"',
|
|
fGrammar.GrammarFile,
|
|
pValue.TokenLine,
|
|
pValue.TokenColumn)
|
|
end;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// SetGrammarOption
|
|
// ----------------------------------------------------------------------------
|
|
procedure TGrammarBehavior.SetGrammarOption( pOption : IToken;
|
|
pValue : IToken);
|
|
begin
|
|
// ---------------------------------------------------------------
|
|
// Option: exportVocab
|
|
// ---------------------------------------------------------------
|
|
if pOption.TokenText = 'exportVocab' then
|
|
if pValue.TokenType in [TT_TOKENREF,TT_RULEREF] then
|
|
// fGrammar.ExportVocab := fExchangeDir + pValue.TokenText
|
|
fGrammar.ExportVocab := pValue.TokenText
|
|
else
|
|
fTool.Error( 'option "exportVocab" must be an identifier',
|
|
fGrammar.GrammarFile,
|
|
pValue.TokenLine,
|
|
pValue.TokenColumn)
|
|
|
|
// ---------------------------------------------------------------
|
|
// Option: importVocab
|
|
// ---------------------------------------------------------------
|
|
else if pOption.TokenText = 'importVocab' then
|
|
if pValue.TokenType in [TT_TOKENREF,TT_RULEREF] then
|
|
begin
|
|
pValue.TokenText := fExchangeDir + pValue.TokenText;
|
|
fGrammar.ImportVocab := pValue
|
|
end
|
|
else
|
|
fTool.Error( 'option "importVocab" must be an identifier',
|
|
fGrammar.GrammarFile,
|
|
pValue.TokenLine,
|
|
pValue.TokenColumn)
|
|
|
|
// ---------------------------------------------------------------
|
|
// Other options sent to the grammar
|
|
// ---------------------------------------------------------------
|
|
else
|
|
fGrammar.SetOption( pOption, pValue);
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// Start Lexer
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.StartLexer( pFileName : AnsiString;
|
|
pLexerName : IToken;
|
|
pSuperClass : IToken);
|
|
begin
|
|
// ---------------------------------------------------------------
|
|
// Create lexer, and initialize it
|
|
// ---------------------------------------------------------------
|
|
if fGrammar = nil then
|
|
begin
|
|
fLexerGrammar := TLexerGrammar.Create(pLexerName,fTool,pSuperClass);
|
|
|
|
fGrammar := fLexerGrammar;
|
|
fGrammar.LLkAnalyzer := fAnalyzer;
|
|
fGrammar.GrammarFile := pFileName;
|
|
|
|
fAnalyzer.Grammar := fGrammar;
|
|
fIsLexer := true;
|
|
|
|
// ------------------------------------------------------------
|
|
// Append uses list...
|
|
// ------------------------------------------------------------
|
|
fGrammar.UsesList.AddStrings( fUsesList);
|
|
|
|
fGrammar.ConstAction := fConstAction;
|
|
fGrammar.TypeAction := fTypeAction;
|
|
end
|
|
else
|
|
fTool.Panic('A grammar already started');
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// Start Parser
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.StartParser( pFileName : AnsiString;
|
|
pParserName : IToken;
|
|
pSuperClass : IToken);
|
|
begin
|
|
// ---------------------------------------------------------------
|
|
// Create parser, and initialize it
|
|
// ---------------------------------------------------------------
|
|
if fGrammar = nil then
|
|
begin
|
|
fParserGrammar := TParserGrammar.Create(pParserName,fTool,pSuperClass);
|
|
|
|
fGrammar := fParserGrammar;
|
|
fGrammar.LLkAnalyzer := fAnalyzer;
|
|
fGrammar.GrammarFile := pFileName;
|
|
|
|
fAnalyzer.Grammar := fGrammar;
|
|
fIsParser := true;
|
|
|
|
// ------------------------------------------------------------
|
|
// Append uses list...
|
|
// ------------------------------------------------------------
|
|
fGrammar.UsesList.AddStrings( fUsesList);
|
|
|
|
fGrammar.ConstAction := fConstAction;
|
|
fGrammar.TypeAction := fTypeAction;
|
|
end
|
|
|
|
else
|
|
fTool.Panic('A grammar already started');
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// Start TreeWalker
|
|
// ================================================================================================
|
|
procedure TGrammarBehavior.StartTreeWalker( pFileName : AnsiString;
|
|
pParserName : IToken;
|
|
pSuperClass : IToken);
|
|
begin
|
|
// ---------------------------------------------------------------
|
|
// Create parser, and initialize it
|
|
// ---------------------------------------------------------------
|
|
if fGrammar = nil then
|
|
begin
|
|
fTreeWalkerGrammar := TTreeParserGrammar.Create( pParserName,fTool,pSuperClass);
|
|
|
|
fGrammar := fTreeWalkerGrammar;
|
|
fGrammar.GrammarFile := pFileName;
|
|
fGrammar.LLkAnalyzer := fAnalyzer;
|
|
|
|
fAnalyzer.Grammar := fGrammar;
|
|
fIsParser := true;
|
|
|
|
// ------------------------------------------------------------
|
|
// Append uses list...
|
|
// ------------------------------------------------------------
|
|
fGrammar.UsesList.AddStrings( fUsesList);
|
|
|
|
fGrammar.ConstAction := fConstAction;
|
|
fGrammar.TypeAction := fTypeAction;
|
|
end
|
|
|
|
else
|
|
fTool.Panic('A grammar already started');
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// RefMemberDecl
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.RefMemberDecl(pDecl: IToken);
|
|
begin
|
|
if pDecl <> nil then
|
|
fGrammar.MemberDecl := pDecl.TokenText;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// RefMemberDef
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.RefMemberDef(pDef: IToken);
|
|
begin
|
|
if pDef <> nil then
|
|
fGrammar.MemberDef := pDef.TokenText;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// Grammar
|
|
// ============================================================================
|
|
function TGrammarBehavior.Grammar: IGrammar;
|
|
begin
|
|
result := fGrammar;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// AbortGrammar
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.AbortGrammar;
|
|
begin
|
|
Reset;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// Reset
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.Reset;
|
|
begin
|
|
fGrammar := nil;
|
|
fLexerGrammar := nil;
|
|
fParserGrammar := nil;
|
|
fTreeWalkerGrammar:= nil;
|
|
end;
|
|
|
|
// ****************************************************************************
|
|
// Internals
|
|
// ****************************************************************************
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// _RefStringLiteral
|
|
//
|
|
// AnsiStringLiterals are treated like tokens except by the lexer.
|
|
// ============================================================================
|
|
procedure TGrammarBehavior._RefStringLiteral( pLiteral: IToken);
|
|
var
|
|
ss : IStringSymbol;
|
|
str: AnsiString;
|
|
|
|
begin
|
|
if not fIsLexer then
|
|
begin
|
|
str := pLiteral.TokenText;
|
|
|
|
if fGrammar.TokenManager.TokenSymbol[str] = nil then
|
|
begin
|
|
// fTool.Warning( 'String literal "' + str + '" not defined.',
|
|
// fGrammar.GrammarFile,
|
|
// pLiteral.TokenLine,
|
|
// pLiteral.TokenColumn);
|
|
|
|
// ss := TStringSymbol.Create( str);
|
|
// ss.TokenType:= fGrammar.TokenManager.NextTokenType;
|
|
|
|
// fGrammar.TokenManager.Define( ss);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// _RefToken
|
|
// ============================================================================
|
|
procedure TGrammarBehavior._RefToken( pToken: IToken);
|
|
var
|
|
id: AnsiString;
|
|
ts: ITokenSymbol;
|
|
|
|
begin
|
|
id := pToken.TokenText;
|
|
|
|
if not fGrammar.TokenManager.TokenDefined[ id] then
|
|
begin
|
|
// ------------------------------------------------------------
|
|
// Defining new TOKENREF is only allowed in lexer..
|
|
// ------------------------------------------------------------
|
|
if fIsLexer then
|
|
begin
|
|
ts := TTokenSymbol.Create( id);
|
|
ts.TokenType:= fGrammar.TokenManager.NextTokenType;
|
|
|
|
fGrammar.TokenManager.Define( ts);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// _refRule
|
|
// ============================================================================
|
|
procedure TGrammarBehavior._RefRule( pRuleName: IToken);
|
|
var
|
|
id: AnsiString;
|
|
|
|
begin
|
|
id := pRuleName.TokenText;
|
|
|
|
if pRuleName.TokenType = TT_TOKENREF then
|
|
id := TCodeGenerator.encodeLexerRuleName( id);
|
|
|
|
if not fGrammar.Defined( id) then
|
|
fGrammar.Define( TRuleSymbol.Create( id));
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// RefConstAction
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.RefConstAction(pConstAction: IToken);
|
|
begin
|
|
fConstAction := pConstAction;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// ============================================================================
|
|
// RefTypeAction
|
|
// ============================================================================
|
|
procedure TGrammarBehavior.RefTypeAction(pTypeAction: IToken);
|
|
begin
|
|
fTypeAction := pTypeAction;
|
|
end;
|
|
|
|
end.
|