////////////////////////////////////////////////// // SQL Server Data Access Components // Copyright © 1998-2007 Core Lab. All right reserved. // MS Parser ////////////////////////////////////////////////// {$IFNDEF CLR} {$I Sdac.inc} unit MSParser; {$ENDIF} interface uses CRParser; const lxALTER = 7 {MSSymbolCount} + 1; lxAND = lxALTER; lxAS = lxAND + 1; lxBEGIN = lxAS + 1; lxBY = lxBEGIN + 1; lxCOMPUTE = lxBY + 1; lxCREATE = lxCOMPUTE + 1; lxCROSS = lxCREATE + 1; lxDECLARE = lxCROSS + 1; lxDEFAULT = lxDECLARE + 1; lxDELETE = lxDEFAULT + 1; lxEND = lxDELETE + 1; lxFOR = lxEND + 1; lxFROM = lxFOR + 1; lxFULL = lxFROM + 1; lxFUNCTION = lxFULL + 1; lxGO = lxFUNCTION + 1; lxGROUP = lxGO + 1; lxHAVING = lxGROUP + 1; lxINNER = lxHAVING + 1; lxINSERT = lxINNER + 1; lxINTO = lxINSERT + 1; lxIS = lxINTO + 1; lxJOIN = lxIS + 1; lxLEFT = lxJOIN + 1; lxOPTION = lxLEFT + 1; lxOR = lxOPTION + 1; lxORDER = lxOR + 1; lxOUTER = lxORDER + 1; lxPROCEDURE = lxOUTER + 1; lxREPLACE = lxPROCEDURE + 1; lxRIGHT = lxREPLACE + 1; lxRULE = lxRIGHT + 1; lxSELECT = lxRULE + 1; lxTABLE = lxSELECT + 1; lxTRIGGER = lxTABLE + 1; lxUPDATE = lxTRIGGER + 1; lxUNION = lxUPDATE + 1; lxVIEW = lxUNION + 1; lxWHERE = lxVIEW + 1; lxWITH = lxWHERE + 1; type TMSParser = class (TParser) protected function IsAlpha(Ch: char): boolean; override; function IsStringQuote(Ch: char): boolean; override; function IsIdentQuote(Ch: char): boolean; override; function IsInlineComment(Pos: integer): boolean; override; procedure ToRightQuote(LeftQuote: Char); override; // Search right quote of quoted string value or quoted identifier procedure InitParser; override; public function IsSemicolon(Code: integer): boolean; override; end; implementation uses Classes, SysUtils; var MSSymbolLexems, MSKeywordLexems: TStringList; { TMSParser } procedure TMSParser.InitParser; begin inherited; (* SELECT statement ::= < query_expression > [ ORDER BY { order_by_expression | column_position [ ASC | DESC ] } [ ,...n ] ] [ COMPUTE { { AVG | COUNT | MAX | MIN | SUM } ( expression ) } [ ,...n ] [ BY expression [ ,...n ] ] ] [ FOR { BROWSE | XML { RAW | AUTO | EXPLICIT } [ , XMLDATA ] [ , ELEMENTS ] [ , BINARY base64 ] } ] [ OPTION ( < query_hint > [ ,...n ]) ] < query expression > ::= { < query specification > | ( < query expression > ) } [ UNION [ ALL ] < query specification | ( < query expression > ) [...n ] ] < query specification > ::= SELECT [ ALL | DISTINCT ] [ { TOP integer | TOP integer PERCENT } [ WITH TIES ] ] < select_list > [ INTO new_table ] [ FROM { < table_source > } [ ,...n ] ] [ WHERE < search_condition > ] [ GROUP BY [ ALL ] group_by_expression [ ,...n ] [ WITH { CUBE | ROLLUP } ] ] [ HAVING < search_condition > ] *) SetLength(FClauses, 7); FClauses[0] := lxWHERE; FClauses[1] := lxGROUP; FClauses[2] := lxHAVING; FClauses[3] := lxORDER; FClauses[4] := lxCOMPUTE; FClauses[5] := lxFOR; FClauses[6] := lxOPTION; FSymbolLexems := MSSymbolLexems; FKeywordLexems := MSKeywordLexems; CommentBegin := '/*'; CommentEnd := '*/'; end; function TMSParser.IsAlpha(Ch: char): boolean; begin Result := inherited IsAlpha(Ch) or (Ch = '$') or (Ch = '#'); end; function TMSParser.IsStringQuote(Ch: char): boolean; begin Result := Ch = ''''; end; function TMSParser.IsIdentQuote(Ch: char): boolean; begin case Ch of '"', '[', ']': Result := True; else Result := False; end; end; function TMSParser.IsInlineComment(Pos: integer): boolean; begin // cr 7788 Result := (TextLength >= Pos + 3) and (Text[Pos] = '-') and (Text[Pos + 1] = '-') and (Text[Pos + 2] = ' '); Result := (TextLength >= Pos + 2) and (Text[Pos] = '-') and (Text[Pos + 1] = '-'); end; procedure TMSParser.ToRightQuote(LeftQuote: Char); begin if LeftQuote = '[' then inherited ToRightQuote(']') else inherited; end; function TMSParser.IsSemicolon(Code: integer): boolean; begin Result := Code = 7; {';'} end; initialization MSSymbolLexems := TStringList.Create; MSKeywordLexems := TStringList.Create; MSSymbolLexems.AddObject('*', TObject(Integer(1))); MSSymbolLexems.AddObject('=', TObject(Integer(2))); MSSymbolLexems.AddObject(':', TObject(Integer(3))); MSSymbolLexems.AddObject(',', TObject(Integer(4))); MSSymbolLexems.AddObject('.', TObject(Integer(5))); MSSymbolLexems.AddObject('/', TObject(Integer(6))); MSSymbolLexems.AddObject(';', TObject(Integer(7))); MSSymbolLexems.CustomSort(CRCmpStrings); MSKeywordLexems.AddObject('SELECT', TObject(Integer(lxSELECT))); MSKeywordLexems.AddObject('FROM', TObject(Integer(lxFROM))); MSKeywordLexems.AddObject('WHERE', TObject(Integer(lxWHERE))); MSKeywordLexems.AddObject('ORDER', TObject(Integer(lxORDER))); MSKeywordLexems.AddObject('BY', TObject(Integer(lxBY))); MSKeywordLexems.AddObject('GROUP', TObject(Integer(lxGROUP))); MSKeywordLexems.AddObject('PROCEDURE', TObject(Integer(lxPROCEDURE))); MSKeywordLexems.AddObject('IS', TObject(Integer(lxIS))); MSKeywordLexems.AddObject('AS', TObject(Integer(lxAS))); MSKeywordLexems.AddObject('AND', TObject(Integer(lxAND))); MSKeywordLexems.AddObject('OR', TObject(Integer(lxOR))); MSKeywordLexems.AddObject('CREATE', TObject(Integer(lxCREATE))); MSKeywordLexems.AddObject('REPLACE', TObject(Integer(lxREPLACE))); MSKeywordLexems.AddObject('INTO', TObject(Integer(lxINTO))); MSKeywordLexems.AddObject('UPDATE', TObject(Integer(lxUPDATE))); MSKeywordLexems.AddObject('DELETE', TObject(Integer(lxDELETE))); MSKeywordLexems.AddObject('INSERT', TObject(Integer(lxINSERT))); MSKeywordLexems.AddObject('COMPUTE', TObject(Integer(lxCOMPUTE))); MSKeywordLexems.AddObject('CROSS', TObject(Integer(lxCROSS))); MSKeywordLexems.AddObject('FOR', TObject(Integer(lxFOR))); MSKeywordLexems.AddObject('FULL', TObject(Integer(lxFULL))); MSKeywordLexems.AddObject('HAVING', TObject(Integer(lxHAVING))); MSKeywordLexems.AddObject('INNER', TObject(Integer(lxINNER))); MSKeywordLexems.AddObject('JOIN', TObject(Integer(lxJOIN))); MSKeywordLexems.AddObject('LEFT', TObject(Integer(lxLEFT))); MSKeywordLexems.AddObject('OPTION', TObject(Integer(lxOPTION))); MSKeywordLexems.AddObject('OUTER', TObject(Integer(lxOUTER))); MSKeywordLexems.AddObject('RIGHT', TObject(Integer(lxRIGHT))); MSKeywordLexems.AddObject('UNION', TObject(Integer(lxUNION))); MSKeywordLexems.AddObject('WITH', TObject(Integer(lxWITH))); MSKeywordLexems.AddObject('BEGIN', TObject(Integer(lxBEGIN))); MSKeywordLexems.AddObject('END', TObject(Integer(lxEND))); MSKeywordLexems.AddObject('DECLARE', TObject(Integer(lxDECLARE))); MSKeywordLexems.AddObject('FUNCTION', TObject(Integer(lxFUNCTION))); MSKeywordLexems.AddObject('GO', TObject(Integer(lxGO))); MSKeywordLexems.AddObject('TABLE', TObject(Integer(lxTABLE))); MSKeywordLexems.AddObject('DEFAULT', TObject(Integer(lxDEFAULT))); MSKeywordLexems.AddObject('RULE', TObject(Integer(lxRULE))); MSKeywordLexems.AddObject('VIEW', TObject(Integer(lxVIEW))); MSKeywordLexems.CustomSort(CRCmpStrings); finalization MSSymbolLexems.Free; MSKeywordLexems.Free; end.