⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dxjs_parser.pas

📁 Well known and usefull component for delphi 7
💻 PAS
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////////////////////////////////////////
//    Component: DXJS_PARSER
//       Author: Alexander Baranovsky (ab@virtlabor.donbass.com)
//               G.E. Ozz Nixon Jr. (staff@bpdx.com)
// ========================================================================
// Source Owner: DX, Inc. 2002, 2004
//    Copyright: All code is the property of DX, Inc. Licensed for
//               resell by Brain Patchwork DX (tm) and part of the
//               DX (r) product lines, which are (c) 1999-2002
//               DX, Inc. Source may not be distributed without
//               written permission from both Brain Patchwork DX,
//               and DX, Inc.
//      License: (Reminder), None of this code can be added to other
//               developer products without permission. This includes
//               but not limited to DCU's, DCP's, DLL's, OCX's, or
//               any other form of merging our technologies. All of
//               your products released to a public consumer be it
//               shareware, freeware, commercial, etc. must contain a
//               license notification somewhere visible in the
//               application.
// Code Version: (3rd Generation)
// ========================================================================
//  Description: parse the supplied script source code into our token code
// ========================================================================
////////////////////////////////////////////////////////////////////////////

unit DXJS_PARSER;

interface

uses
   Classes,
   DXJS_SHARE,
   DXJS_LIST;

type
   TParser=class
      JScript:Pointer;
      CurrToken:TToken;
      CurrLevel:Integer;
      EntryStack:TEntryStack;
      StatementLabel:string;
      NewID,IsFormalParameter,IsDeclareSwitch:boolean;
      FuncDecl:string;
      WithStack:Integer;
      IncList,DecList:TList;
      constructor Create (aJScript:Pointer) ;
      destructor Destroy;override;
      procedure App_POSTFIX (Const I:Integer) ;
      procedure Call_SCANNER (FieldID:boolean=false) ;
      function NextToken:TToken;
      procedure Match (I:Integer) ;
      function AppLabel:Integer;
      procedure SetLabelHere (Const L:Integer) ;
      function AppConstant (const Value:Variant) :Integer;
      procedure AppIncList (Const K:Integer) ;
      procedure AppDecList (Const K:Integer) ;
// Expressions
      function Parse_Identifier:Integer;
      procedure Parse_PrimaryExpression;
      procedure Parse_ArrayLiteral;
      procedure Parse_ObjectLiteral;
      procedure Parse_MemberExpression;
      procedure Parse_NewExpression;
      function Parse_Arguments:Integer;
      function Parse_ArgumentList:Integer;
      procedure Parse_LeftHandSideExpression;
      procedure Parse_PostfixExpression (Const Left:boolean) ;
      procedure Parse_UnaryExpression (Const Left:boolean) ;
      procedure Parse_MultiplicativeExpression (Const Left:boolean) ;
      procedure Parse_AdditiveExpression (Const Left:boolean) ;
      procedure Parse_ShiftExpression (Const Left:boolean) ;
      procedure Parse_RelationalExpression (Const Left:boolean) ;
      procedure Parse_EqualityExpression (Const Left:boolean) ;
      procedure Parse_BitwiseANDExpression (Const Left:boolean) ;
      procedure Parse_BitwiseXORExpression (Const Left:boolean) ;
      procedure Parse_BitwiseORExpression (Const Left:boolean) ;
      procedure Parse_LogicalANDExpression (Const Left:boolean) ;
      procedure Parse_LogicalORExpression (Const Left:boolean) ;
      procedure Parse_ConditionalExpression (Const Left:boolean) ;
      procedure Parse_AssignmentExpression;
      function Parse_AssignmentOperator:Integer;
      procedure Parse_Expression;
// Statements
      procedure Parse_Statement;
      procedure Parse_Block;
      procedure Parse_VariableDeclarationList;
      procedure Parse_VariableDeclaration;
      procedure EmptyStatement;
      procedure Parse_IfStatement;
      procedure Parse_ForStatement;
      procedure Parse_DoStatement;
      procedure Parse_WhileStatement;
      procedure Parse_ContinueStatement;
      procedure Parse_BreakStatement;
      procedure Parse_ReturnStatement;
      procedure Parse_WithStatement;
      procedure Parse_SwitchStatement;
      procedure Parse_ThrowStatement;
      procedure Parse_TryStatement;
      procedure Parse_ExpressionStatement;
      procedure Parse_PrintStatement;
// Functions and Programs
      procedure Parse_FunctionDeclaration;
      procedure Parse_FunctionExpression;
      function Parse_FormalParameterList:Integer;
      procedure Parse_FunctionBody;
      function Parse_Program:boolean;
      procedure Parse_SourceElements;
      procedure Parse_SourceElement;
   end;

implementation

uses
   SysUtils,// Exception
   DXJS_MAIN,
   DXJS_OBJECT,
   DXJS_CONV;

constructor TParser.Create (aJScript:Pointer) ;
begin
   JScript:=aJScript;
   CurrLevel:=0;
   EntryStack:=TEntryStack.Create;
   StatementLabel:='';
   IsFormalParameter:=false;
   IsDeclareSwitch:=false;
   WithStack:=0;
   IncList:=TList.Create;
   DecList:=TList.Create;
end;

destructor TParser.Destroy;
begin
   EntryStack.Free;
   IncList.Free;
   DecList.Free;

   inherited;
end;

procedure TParser.AppIncList (Const K:Integer) ;
var
   I,ID:Integer;
begin
   while IncList.Count>K do begin
      I:=IncList.Count-1;
      ID:=Integer (IncList[I]) ;
      App_POSTFIX (ID) ;
      App_POSTFIX (OP_INC) ;
      App_POSTFIX (OP_POP_RET) ;
      IncList.Delete (I) ;
   end;
end;

procedure TParser.AppDecList (Const K:Integer) ;
var
   I,ID:Integer;
begin
   while DecList.Count>K do begin
      I:=DecList.Count-1;
      ID:=Integer (DecList[I]) ;
      App_POSTFIX (ID) ;
      App_POSTFIX (OP_DEC) ;
      App_POSTFIX (OP_POP_RET) ;
      DecList.Delete (I) ;
   end;
end;

procedure TParser.Call_SCANNER;
begin
   NewID:=false;
   TJScript (JScript) .Scanner.GetToken (CurrToken) ;
   if CurrToken.AClass=classSEPARATOR then begin
      App_POSTFIX (CurrToken.ID) ;
      Call_SCANNER;
      Exit;
   end
   else if CurrToken.ID=OP_EOF then begin
      Exit;
   end;
   if CurrLevel>0 then FuncDecl:=FuncDecl+CurrToken.Text+' ';
   if FieldID then begin
      CurrToken.ID:=AppConstant (CurrToken.Text) ;
      Exit;
   end;
   if IsDeclareSwitch then
      with TJScript (JScript) .SymbolTable do begin
         CurrToken.ID:=AppVariant (Undefined) ;
         SetName (CurrToken.ID,CurrToken.Text) ;
         A[CurrToken.ID].Level:=CurrLevel;
         NewID:=true;
         Exit;
      end;
   if CurrToken.ID=0 then
      if CurrToken.AClass=classID then begin
         CurrToken.ID:=TJScript (JScript) .SymbolTable.LookUpID (CurrToken.Text,CurrLevel) ;
         if not IsFormalParameter then begin
            if CurrToken.ID=0 then
               if CurrLevel>0 then
                  CurrToken.ID:=TJScript (JScript) .SymbolTable.LookUpID (CurrToken.Text,0) ;
         end;
         if CurrToken.ID=0 then
            with TJScript (JScript) .SymbolTable do begin
               CurrToken.ID:=AppVariant (Undefined) ;
               SetName (CurrToken.ID,CurrToken.Text) ;
               A[CurrToken.ID].Level:=CurrLevel;
               NewID:=true;
            end;
      end;
end;

function TParser.NextToken:TToken;
begin
   TJScript (JScript) .Scanner.GetNextToken (result) ;
end;

procedure TParser.App_POSTFIX (Const I:Integer) ;
begin
   TJScript (JScript) .Postfix.App (I) ;
end;

procedure TParser.Match (I:Integer) ; // Sept 2003
begin
   if I<>CurrToken.ID then Begin
      if I = SP_SEMICOLON then begin
        TJScript(JScript).Scanner.BuffToken := CurrToken;
        CurrToken.Text := ';';
        CurrToken.ID := SP_SEMICOLON;
      end
      Else begin
         raise TScriptFailure.Create (ParseErrors.GetCode (I)) ;
      End;
   End;
end;

function TParser.AppLabel:Integer;
begin
   result:=TJScript (JScript) .SymbolTable.AppLabel;
end;

procedure TParser.SetLabelHere (Const L:Integer) ;
begin
   with TJScript (JScript) do SymbolTable.A[L].Entry :=Postfix.Card+1 ;
end;

function TParser.AppConstant (const Value:Variant) :Integer;
begin
   result:=TJScript (JScript) .SymbolTable.AppVariantConst (Value) ;
end;

/////////////////////////////////
//// EXPRESSIONS ////////////////
/////////////////////////////////

function TParser.Parse_Identifier:Integer;
begin
   result:=CurrToken.ID;
   if not (CurrToken.AClass in [classID,classCONST]) then
      raise TScriptFailure.Create (peIdentifierExpected) ;
   App_POSTFIX (CurrToken.ID) ;
   Call_SCANNER;
end;

procedure TParser.Parse_PrimaryExpression;
var
   S:string;
   ID,L,K:Integer;
begin
   case CurrToken.ID of
      SP_ROUND_BRACKET_L:begin// (Expression)
            Call_SCANNER;
            Parse_Expression;
            Match (SP_ROUND_BRACKET_R) ;
            Call_SCANNER;
         end;
      SP_BRACKET_L:Parse_ArrayLiteral;// (array literal)
      SP_BRACE_L:Parse_ObjectLiteral;// (object literal)
      OP_DIV:begin// (regexp literal)
            K:=1;
            App_POSTFIX (OP_CREATE_OBJECT) ;
            App_POSTFIX (TJScript (JScript) .SymbolTable.RegExpID) ;
            App_POSTFIX (OP_SAVE_CALL) ;
            L:=AppLabel;
            App_POSTFIX (L) ;
            S:=TJScript (Jscript) .Scanner.GetRegExpBody;
            App_POSTFIX (AppConstant (S) ) ;
            Call_SCANNER;
            Match (OP_DIV) ;
            if NextToken.AClass=ClassID then begin
               Inc (K) ;
               Call_SCANNER;
               App_POSTFIX (AppConstant (CurrToken.Text) ) ;
            end;
            App_POSTFIX (AppConstant (K) ) ;
            App_POSTFIX (OP_CALL) ;
            SetLabelHere (L) ;
            App_POSTFIX (OP_POP_RET) ;
            Call_SCANNER;
         end;
   else begin// Identifier
         S:=CurrToken.Text;
         if (S='arguments') and (CurrLevel>0) then begin
            with TJScript (JScript) .SymbolTable do begin
               SetName (CurrToken.ID,'') ;
               A[CurrToken.ID].Level:=0;
               ID:=AppVariantConst ('arguments') ;
            end;
            App_POSTFIX (CurrLevel) ;
            App_POSTFIX (ID) ;
            App_POSTFIX (OP_CREATE_REFERENCE) ;
            Call_SCANNER;
         end
         Else Begin
            Parse_Identifier;
            if WithStack>0 then App_POSTFIX (OP_EVAL_IDENTIFIER) ;
         End;
      end;
   end;{case}
end;

procedure TParser.Parse_ArrayLiteral;
var
   K,L,ID:Integer;
begin
// Match SP_BRACKET_L
   K:=0;
   App_POSTFIX (OP_CREATE_OBJECT) ;
   App_POSTFIX (TJScript (JScript) .SymbolTable.ArrayID) ;
   App_POSTFIX (OP_SAVE_CALL) ;
   L:=AppLabel;
   App_POSTFIX (L) ;
   Call_SCANNER;
   if CurrToken.ID<>SP_BRACKET_R then
      repeat
         if CurrToken.ID=SP_COMMA then begin
            Inc (K) ;
            App_POSTFIX (TJScript (JScript) .SymbolTable.UndefinedID) ;
            Call_SCANNER;
            if CurrToken.ID=SP_BRACKET_R then begin
               Inc (K) ;
               App_POSTFIX (TJScript (JScript) .SymbolTable.UndefinedID) ;
               Break;
            end;
         end
         else begin
            Inc (K) ;
            Parse_AssignmentExpression;
            if CurrToken.ID=SP_BRACKET_R then
               Break;
            Call_SCANNER;
         end;
      until false;
   ID:=AppConstant (K) ;
   App_POSTFIX (ID) ;
   App_POSTFIX (OP_CALL) ;
   SetLabelHere (L) ;
   App_POSTFIX (OP_POP_RET) ;
   Call_SCANNER;
end;

procedure TParser.Parse_ObjectLiteral;
var
   ID:Integer;
begin
// Match SP_BRACE_L
   App_POSTFIX (OP_CREATE_OBJECT) ;
   ID:=TJScript (JScript) .SymbolTable.AppVariant (Undefined) ;
   App_POSTFIX (ID) ;
   App_POSTFIX (OP_SWAP) ;
   App_POSTFIX (OP_ASSIGN) ;
   Call_SCANNER (true) ;
   App_POSTFIX (CurrToken.ID) ;
   App_POSTFIX (OP_CREATE_REFERENCE) ;
   Call_SCANNER;
   Match (SP_COLON) ;
   Call_SCANNER;
   Parse_AssignmentExpression;
   App_POSTFIX (OP_ASSIGN) ;
   App_POSTFIX (OP_POP_RET) ;
   while CurrToken.ID=SP_COMMA do begin
      App_POSTFIX (ID) ;
      Call_SCANNER (true) ;
      App_POSTFIX (CurrToken.ID) ;
      App_POSTFIX (OP_CREATE_REFERENCE) ;
      Call_SCANNER;
      Match (SP_COLON) ;
      Call_SCANNER;
      Parse_AssignmentExpression;
      App_POSTFIX (OP_ASSIGN) ;
      App_POSTFIX (OP_POP_RET) ;
   end;
   Match (SP_BRACE_R) ;
   App_POSTFIX (ID) ;
   Call_SCANNER;
end;

procedure TParser.Parse_MemberExpression;
var
   I,K,L:Integer;
begin
   if CurrToken.ID=WD_FUNCTION then begin
      IsDeclareSwitch:=true;
      Call_SCANNER;
      if CurrToken.AClass<>classID then
         with TJScript (JScript) .SymbolTable do begin
            CurrToken.AClass:=ClassID;
            CurrToken.Text:='';
            CurrToken.ID:=AppVariant (Undefined) ;
            A[CurrToken.ID].Level:=0;
         end;
      App_POSTFIX (CurrToken.ID) ;
      IsDeclareSwitch:=false;
      FuncDecl:='function '+CurrToken.Text;
      Parse_FunctionExpression;
   end
   else begin
      Parse_PrimaryExpression;
      while (CurrToken.ID=SP_BRACKET_L) or (CurrToken.ID=SP_POINT) or
         (CurrToken.ID=SP_ROUND_BRACKET_L) do begin
         Case CurrToken.ID of
            SP_BRACKET_L:begin
               Call_SCANNER;
               Parse_EXPRESSION;
               Match (SP_BRACKET_R) ;
               App_POSTFIX (OP_CREATE_REFERENCE) ;
               Call_SCANNER;
            end;
            SP_POINT:begin
               Call_SCANNER (true) ;
               App_POSTFIX (CurrToken.ID) ;
               App_POSTFIX (OP_CREATE_REFERENCE) ;
               Call_SCANNER;
            end;
            SP_ROUND_BRACKET_L:begin
               App_POSTFIX (OP_SAVE_CALL) ;
               L:=AppLabel;
               App_POSTFIX (L) ;
               K:=Parse_Arguments;
               I:=AppConstant (K) ;
               App_POSTFIX (I) ;
               App_POSTFIX (OP_CALL) ;
               SetLabelHere (L) ;
            end;
         end; {case}
      end;
   end;
end;

procedure TParser.Parse_NewExpression;
var
   ID:Integer;
begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -