📄 xqlex.pas
字号:
// lexical analyzer template for TxQuery
// global definitions:
{**********************************************}
{ Lexical analizer for TxQuery component }
{ Copyright (c) 2002 by Alfonso Moreno }
{**********************************************}
unit XQLex;
{$I XQ_FLAG.INC}
interface
uses
SysUtils, Classes, QLexLib, xqYacc;
type
TxqLexer = Class( TCustomLexer)
private
FIsWhereActive : Boolean;
FDateFormat : String;
FIgnoreBadDates: Boolean;
public
// utility functions
function IsKeyword(const id : String; var token : integer) : boolean;
// Lexer main functions
function yylex : Integer; override;
procedure yyaction( yyruleno : integer);
procedure commenteof;
property IsWhereActive: Boolean read FIsWhereActive write FIsWhereActive;
property DateFormat: String read FDateFormat write FDateFormat;
property IgnoreBadDates: Boolean read FIgnoreBadDates write FIgnoreBadDates;
end;
//===============================================
// reserved words definition
//===============================================
type
TRWord = record
rword: string[10];
token: smallint;
end;
const
rwords : array [1..101] of TRword = (
(rword:'TOP'; token: RW_TOP),
(rword:'SELECT'; token: RW_SELECT),
(rword:'DISTINCT'; token: RW_DISTINCT),
(rword:'TRUE'; token: RW_TRUE),
(rword:'FALSE'; token: RW_FALSE),
(rword:'AND'; token: RW_AND),
(rword:'OR'; token: RW_OR),
(rword:'NOT'; token: RW_NOT),
(rword:'FROM'; token: RW_FROM),
(rword:'WHERE'; token: RW_WHERE),
(rword:'ORDER'; token: RW_ORDER),
(rword:'BY'; token: RW_BY),
(rword:'ASC'; token: RW_ASC),
(rword:'DESC'; token: RW_DESC),
(rword:'AS'; token: RW_AS),
(rword:'INNER'; token: RW_INNER),
(rword:'OUTER'; token: RW_OUTER),
(rword:'FULL'; token: RW_FULL),
(rword:'JOIN'; token: RW_JOIN),
(rword:'ON'; token: RW_ON),
(rword:'GROUP'; token: RW_GROUP),
(rword:'ANY'; token: RW_ANY),
(rword:'ALL'; token: RW_ALL),
(rword:'SUM'; token: RW_SUM),
(rword:'AVG'; token: RW_AVG),
(rword:'COUNT'; token: RW_COUNT),
(rword:'MIN'; token: RW_MIN),
(rword:'MAX'; token: RW_MAX),
(rword:'STDEV'; token: RW_STDEV),
(rword:'BETWEEN'; token: RW_BETWEEN),
(rword:'IN'; token: RW_IN),
(rword:'LIKE'; token: RW_LIKE),
(rword:'LEFT'; token: RW_LEFT),
(rword:'RIGHT'; token: RW_RIGHT),
(rword:'HAVING'; token: RW_HAVING),
(rword:'LEADING'; token: RW_LEADING),
(rword:'TRAILING'; token: RW_TRAILING),
(rword:'BOTH'; token: RW_BOTH),
(rword:'TRIM'; token: RW_TRIM),
(rword:'EXTRACT'; token: RW_EXTRACT),
(rword:'YEAR'; token: RW_YEAR),
(rword:'MONTH'; token: RW_MONTH),
(rword:'DAY'; token: RW_DAY),
(rword:'HOUR'; token: RW_HOUR),
(rword:'MINUTE'; token: RW_MINUTE),
(rword:'SECOND'; token: RW_SECOND),
(rword:'SUBSTRING'; token: RW_SUBSTRING),
(rword:'FOR'; token: RW_FOR),
(rword:'DELETE'; token: RW_DELETE),
(rword:'UPDATE'; token: RW_UPDATE),
(rword:'INSERT'; token: RW_INSERT),
(rword:'INTO'; token: RW_INTO),
(rword:'VALUES'; token: RW_VALUES),
(rword:'SET'; token: RW_SET),
(rword:'CAST'; token: RW_CAST),
(rword:'CHAR'; token: RW_CHAR),
(rword:'INTEGER'; token: RW_INTEGER),
(rword:'BOOLEAN'; token: RW_BOOLEAN),
(rword:'DATE'; token: RW_DATE),
(rword:'DATETIME'; token: RW_DATETIME),
(rword:'TIME'; token: RW_TIME),
(rword:'FLOAT'; token: RW_FLOAT),
(rword:'NUMERIC'; token: RW_FLOAT),
(rword:'ESCAPE'; token: RW_ESCAPE),
(rword:'CREATE'; token: RW_CREATE),
(rword:'TABLE'; token: RW_TABLE),
(rword:'SMALLINT'; token: RW_SMALLINT),
(rword:'MONEY'; token: RW_MONEY),
(rword:'AUTOINC'; token: RW_AUTOINC),
(rword:'PRIMARY'; token: RW_PRIMARY),
(rword:'KEY'; token: RW_KEY),
(rword:'BLOB'; token: RW_BLOB),
(rword:'INDEX'; token: RW_INDEX),
(rword:'UNIQUE'; token: RW_UNIQUE),
(rword:'DROP'; token: RW_DROP),
(rword:'TRANSFORM'; token: RW_TRANSFORM),
(rword:'PIVOT'; token: RW_PIVOT),
(rword:'UNION'; token: RW_UNION),
(rword:'WITH'; token: RW_WITH),
(rword:'IS'; token: RW_IS),
(rword:'NULL'; token: RW_NULL),
(rword:'MOD'; token: RW_MOD),
(rword:'DIV'; token: RW_IDIV),
(rword:'SHL'; token: RW_SHL),
(rword:'SHR'; token: RW_SHR),
(rword:'ALTER'; token: RW_ALTER),
(rword:'COLUMN'; token: RW_COLUMN),
(rword:'ADD'; token: RW_ADD),
(rword:'APPEND'; token: RW_APPEND),
(rword:'CASE'; token: RW_CASE),
(rword:'WHEN'; token: RW_WHEN),
(rword:'THEN'; token: RW_THEN),
(rword:'ELSE'; token: RW_ELSE),
(rword:'END'; token: RW_END),
(rword:'PACK'; token: RW_PACK),
(rword:'ZAP'; token: RW_ZAP),
(rword:'REINDEX'; token: RW_REINDEX),
(rword:'FIELDS'; token: RW_FIELDS),
(rword:'USING'; token: RW_USING),
(rword:'RANGE'; token: RW_RANGE),
(rword:'TO'; token: RW_TO)
);
implementation
uses xqConsts, xquery;
function TxqLexer.IsKeyword(const id : string; var token : integer) : boolean;
(* returns corresponding token number in token *)
var
k : integer;
begin
Result:= false;
for k:= Low(rwords) to High(rwords) do
if AnsiCompareText(id, rwords[k].rword)=0 then
begin
Result:= True;
token := rwords[k].token;
Exit;
end;
end;
procedure TxqLexer.commenteof;
begin
writeln(yyErrorfile, 'unexpected EOF inside comment at line '
+intToStr( yylineno));
end;
procedure TXQLexer.yyaction ( yyruleno : Integer );
(* local definitions: *)
var
c: char;
token, code, value: Integer;
SaveDate: String;
Function ReturnDate( const ADate: String ): string;
begin
SaveDate := ShortDateFormat;
if Length( Self.FDateFormat ) = 0 then
Self.FDateFormat := ShortDateFormat;//SDefaultDateFormat;
ShortDateFormat := Self.FDateFormat;
try
Result := FloatToStr( StrToDate( ADate ) );
if FIsWhereActive then
Result := 'DummyDate(' + Result + ')';
ShortDateFormat := SaveDate;
returni( _NUMERIC );
except
if not FIgnoreBadDates then
begin
FIgnoreBadDates:= False;
raise;
end;
end;
end;
begin
GetyyText (yylval.yystring);
(* actions: *)
case yyruleno of
1:
begin
If AnsiCompareText( yylval.yystring, 'NOW' ) = 0 Then
Begin
SaveDate := ShortDateFormat;
if Length( Self.FDateFormat ) = 0 then
Self.FDateFormat := ShortDateFormat;//SDefaultDateFormat;
ShortDateFormat := Self.FDateFormat;
try
yylval.yystring := FloatToStr( Now );
if FIsWhereActive then
yylval.yystring := 'DummyDate(' + yylval.yystring + ')';
ShortDateFormat := SaveDate;
returni( _NUMERIC );
except
if not FIgnoreBadDates then
begin
FIgnoreBadDates:= False;
raise;
end;
end;
Exit;
End;
if IsKeyword(yylval.yystring, token) then
begin
if token = RW_WHERE then
FIsWhereActive:= True
else if FIsWhereActive and ( (token = RW_GROUP) or
(token =RW_ORDER) or (token = RW_SELECT) or (token =RW_PIVOT) ) then
FIsWhereActive := False;
returni(token);
end
else
returni(_IDENTIFIER);
end;
2:
returni( _COMMENT );
3:
returni( _COMMENT );
4:
returni( _COMMENT );
5:
begin
// extended identifier
//yylval.yystring := yylval.yystring;
returni( _IDENTIFIER );
end;
6:
returni( _NUMERIC );
7:
returni( _UINTEGER );
8:
returni( _SINTEGER );
9:
begin
Val(yylval.yystring,value,code);
if code=0 then
begin
yylval.yystring:= IntToStr(value);
returni(_NUMERIC);
end else
returni(_ILLEGAL);
end;
10:
begin
c := get_char;
unget_char(c);
if c = #39 then
yymore
else
returni( _STRING );
end;
11:
begin
c := get_char;
unget_char(c);
if c = #34 then
yymore
else
returni( _STRING );
end;
12:
begin
// previously this "#"{DIGIT}{1,2}"/"{DIGIT}{1,2}"/"({DIGIT}{2}|{DIGIT}{4})"#"
if yytextlen >= 10 then
begin
yylval.yystring := ReturnDate( Copy( yylval.yystring, 2, yyTextLen - 2) );
end;
end;
13:
returni( _COMA );
14:
returni( _LPAREN );
15:
returni( _RPAREN );
16:
returni( _LSQUARE );
17:
returni( _RSQUARE );
18:
returni( _GT );
19:
returni( _LT );
20:
returni( _PERIOD );
21:
returni( _COLON );
22:
returni( _SEMICOLON );
23:
returni( _EQ );
24:
returni( _MULT );
25:
returni( _PLUS );
26:
returni( _SUB );
27:
returni( _EXP );
28:
returni( _DIV );
29:
returni( _NEQ );
30:
returni( _GE );
31:
returni( _LE );
32:
begin
yylval.yystring := '+';
returni( _PLUS );
end;
33:
returni( _BLANK );
34:
returni( _NEWLINE );
35:
returni( _TAB );
36:
returni( _ILLEGAL );
end;
end(*yyaction*);
function TXQLexer.yylex : Integer;
(* DFA table: *)
type YYTRec = record
cc : set of Char;
s : SmallInt;
end;
const
yynmarks = 67;
yynmatches = 67;
yyntrans = 112;
yynstates = 62;
yyk : array [1..yynmarks] of SmallInt = (
{ 0: }
{ 1: }
{ 2: }
1,
36,
{ 3: }
28,
36,
{ 4: }
16,
36,
{ 5: }
26,
36,
{ 6: }
25,
36,
{ 7: }
7,
36,
{ 8: }
20,
36,
{ 9: }
36,
{ 10: }
36,
{ 11: }
36,
{ 12: }
36,
{ 13: }
13,
36,
{ 14: }
14,
36,
{ 15: }
15,
36,
{ 16: }
17,
36,
{ 17: }
18,
36,
{ 18: }
19,
36,
{ 19: }
21,
36,
{ 20: }
22,
36,
{ 21: }
23,
36,
{ 22: }
24,
36,
{ 23: }
27,
36,
{ 24: }
36,
{ 25: }
33,
36,
{ 26: }
34,
{ 27: }
35,
36,
{ 28: }
36,
{ 29: }
1,
{ 30: }
{ 31: }
{ 32: }
{ 33: }
5,
{ 34: }
{ 35: }
8,
{ 36: }
7,
{ 37: }
6,
{ 38: }
6,
{ 39: }
9,
{ 40: }
{ 41: }
10,
{ 42: }
{ 43: }
11,
{ 44: }
{ 45: }
12,
{ 46: }
30,
{ 47: }
29,
{ 48: }
31,
{ 49: }
32,
{ 50: }
{ 51: }
5,
{ 52: }
{ 53: }
{ 54: }
{ 55: }
2,
{ 56: }
{ 57: }
3,
5,
{ 58: }
4,
{ 59: }
3
{ 60: }
{ 61: }
);
yym : array [1..yynmatches] of SmallInt = (
{ 0: }
{ 1: }
{ 2: }
1,
36,
{ 3: }
28,
36,
{ 4: }
16,
36,
{ 5: }
26,
36,
{ 6: }
25,
36,
{ 7: }
7,
36,
{ 8: }
20,
36,
{ 9: }
36,
{ 10: }
36,
{ 11: }
36,
{ 12: }
36,
{ 13: }
13,
36,
{ 14: }
14,
36,
{ 15: }
15,
36,
{ 16: }
17,
36,
{ 17: }
18,
36,
{ 18: }
19,
36,
{ 19: }
21,
36,
{ 20: }
22,
36,
{ 21: }
23,
36,
{ 22: }
24,
36,
{ 23: }
27,
36,
{ 24: }
36,
{ 25: }
33,
36,
{ 26: }
34,
{ 27: }
35,
36,
{ 28: }
36,
{ 29: }
1,
{ 30: }
{ 31: }
{ 32: }
{ 33: }
5,
{ 34: }
{ 35: }
8,
{ 36: }
7,
{ 37: }
6,
{ 38: }
6,
{ 39: }
9,
{ 40: }
{ 41: }
10,
{ 42: }
{ 43: }
11,
{ 44: }
{ 45: }
12,
{ 46: }
30,
{ 47: }
29,
{ 48: }
31,
{ 49: }
32,
{ 50: }
{ 51: }
5,
{ 52: }
{ 53: }
{ 54: }
{ 55: }
2,
{ 56: }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -