Update scansup.cpp #17
|
|
@ -1,90 +1,52 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
*
|
||||
* kwlookup.cpp
|
||||
* lexical token lookup for key words in openGauss
|
||||
*
|
||||
* NB - this file is also used by ECPG and several frontend programs in
|
||||
* src/bin/ including pg_dump and psql
|
||||
*
|
||||
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/common/backend/parser/kwlookup.cpp
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* use c.h so this can be built as either frontend or backend */
|
||||
#include "c.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "parser/keywords.h"
|
||||
|
||||
/*
|
||||
* ScanKeywordLookup - see if a given word is a keyword
|
||||
*
|
||||
* Returns a pointer to the ScanKeyword table entry, or NULL if no match.
|
||||
*
|
||||
* The match is done case-insensitively. Note that we deliberately use a
|
||||
* dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
|
||||
* even if we are in a locale where tolower() would produce more or different
|
||||
* translations. This is to conform to the SQL99 spec, which says that
|
||||
* keywords are to be matched in this way even though non-keyword identifiers
|
||||
* receive a different case-normalization mapping.
|
||||
*/
|
||||
//返回指向ScanKeyword表项的指针,如果不匹配则返回NULL。
|
||||
/* 匹配是不区分大小写的。注意,我们故意使用简化的大小写转换,只将'A'-' Z'翻译成'a'-' z',即使我们在tolower()会产生更多或不同的翻译。这是为了符合SQL99规范,该规范规定即使非关键字标识符接收不同的大小写规范化映射,也要以这种方式匹配关键字。*/
|
||||
//用于判断信息的关键字,从而将关键词返回为具体的token给程序
|
||||
const ScanKeyword* ScanKeywordLookup(const char* text, const ScanKeyword* keywords, int num_keywords)
|
||||
{
|
||||
int len, i;
|
||||
char word[NAMEDATALEN] = {0};
|
||||
const ScanKeyword* low = NULL;
|
||||
const ScanKeyword* high = NULL;
|
||||
|
||||
if (text == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen(text);
|
||||
/* We assume all keywords are shorter than NAMEDATALEN. */
|
||||
/* 我们假设所有关键字都比NAMEDATALEN短。 */
|
||||
if (len >= NAMEDATALEN) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply an ASCII-only downcasing. We must not use tolower() since it may
|
||||
* produce the wrong translation in some locales (eg, Turkish).
|
||||
应用仅限ascII的下标。我们一定不要使用tolower(),因为它可能在某些地区产生错误的翻译(如土耳其语)。
|
||||
*/
|
||||
for (i = 0; i < len; i++) {
|
||||
char ch = text[i];
|
||||
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
ch += 'a' - 'A';
|
||||
}
|
||||
word[i] = ch;
|
||||
}
|
||||
word[len] = '\0';
|
||||
|
||||
/*
|
||||
* Now do a binary search using plain strcmp() comparison.
|
||||
*使用strcmp()比较执行二进制搜索。
|
||||
*/
|
||||
low = keywords;
|
||||
high = keywords + (num_keywords - 1);
|
||||
while (low <= high) {
|
||||
const ScanKeyword* middle = NULL;
|
||||
int difference;
|
||||
|
||||
middle = low + (high - low) / 2;
|
||||
difference = strcmp(middle->name, word);
|
||||
if (difference == 0) {
|
||||
return middle;
|
||||
} else if (difference < 0) {
|
||||
}
|
||||
//如果middle->name比word短,返回-1
|
||||
else if (difference < 0) {
|
||||
low = middle + 1;
|
||||
} else {
|
||||
}
|
||||
//如果middle->name比word长,返回1
|
||||
else {
|
||||
high = middle - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -43,76 +43,57 @@ char* scanstr(const char* s)
|
|||
|
||||
newStr = (char*)palloc(len + 1); /* string cannot get longer */
|
||||
|
||||
for (i = 0, j = 0; i < len; i++) {
|
||||
if (s[i] == '\'') {
|
||||
/*
|
||||
* Note: if scanner is working right, unescaped quotes can only
|
||||
* appear in pairs, so there should be another character.
|
||||
*/
|
||||
i++;
|
||||
newStr[j] = s[i];
|
||||
} else if (s[i] == '\\') {
|
||||
i++;
|
||||
switch (s[i]) {
|
||||
case 'b':
|
||||
newStr[j] = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
newStr[j] = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
newStr[j] = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
newStr[j] = '\r';
|
||||
break;
|
||||
case 't':
|
||||
newStr[j] = '\t';
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': {
|
||||
int k;
|
||||
unsigned long octVal = 0;
|
||||
for (i = 0, j = 0; i < len; i++) {
|
||||
if (s[i] == '\'') {
|
||||
i++;
|
||||
newStr[j] = s[i];//说明不是转义字符
|
||||
} else if (s[i] == '\\') {
|
||||
i++;
|
||||
switch (s[i]) {
|
||||
case 'b':
|
||||
newStr[j] = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
newStr[j] = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
newStr[j] = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
newStr[j] = '\r';
|
||||
break;
|
||||
case 't':
|
||||
newStr[j] = '\t';
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': {
|
||||
int k;
|
||||
unsigned long octVal = 0;
|
||||
for (k = 0; s[i + k] >= '0' && s[i + k] <= '7' && k < 3; k++){
|
||||
octVal = (octVal << 3) + (s[i + k] - '0');
|
||||
}
|
||||
i += k - 1;
|
||||
newStr[j] = ((char)octVal);
|
||||
} break;
|
||||
default:
|
||||
newStr[j] = s[i];
|
||||
break;
|
||||
} /* switch */
|
||||
} /* s[i] == '\\' */
|
||||
else {
|
||||
newStr[j] = s[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
newStr[j] = '\0';
|
||||
|
||||
for (k = 0; s[i + k] >= '0' && s[i + k] <= '7' && k < 3; k++){
|
||||
octVal = (octVal << 3) + (s[i + k] - '0');
|
||||
}
|
||||
i += k - 1;
|
||||
newStr[j] = ((char)octVal);
|
||||
} break;
|
||||
default:
|
||||
newStr[j] = s[i];
|
||||
break;
|
||||
} /* switch */
|
||||
} /* s[i] == '\\' */
|
||||
else {
|
||||
newStr[j] = s[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
newStr[j] = '\0';
|
||||
return newStr;
|
||||
}
|
||||
|
||||
/*
|
||||
* downcase_truncate_identifier() --- do appropriate downcasing and
|
||||
* truncation of an unquoted identifier. Optionally warn of truncation.
|
||||
*
|
||||
* Returns a palloc'd string containing the adjusted identifier.
|
||||
*
|
||||
* Note: in some usages the passed string is not null-terminated.
|
||||
*
|
||||
* Note: the API of this function is designed to allow for downcasing
|
||||
* transformations that increase the string length, but we don't yet
|
||||
* support that. If you want to implement it, you'll need to fix
|
||||
* SplitIdentifierString() in utils/adt/varlena.c.
|
||||
*/
|
||||
//对未加引号的标识符进行适当的大小写转换和截断。可选的截断警告。
|
||||
char* downcase_truncate_identifier(const char* ident, int len, bool warn)
|
||||
{
|
||||
char* result = NULL;
|
||||
|
|
@ -180,15 +161,8 @@ void truncate_identifier(char* ident, int len, bool warn)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* scanner_isspace() --- return TRUE if flex scanner considers char whitespace
|
||||
*
|
||||
* This should be used instead of the potentially locale-dependent isspace()
|
||||
* function when it's important to match the lexer's behavior.
|
||||
*
|
||||
* In principle we might need similar functions for isalnum etc, but for the
|
||||
* moment only isspace seems needed.
|
||||
*/
|
||||
// 如果flex scanner识别出字符空白,则返回TRUE
|
||||
bool scanner_isspace(char ch)
|
||||
{
|
||||
/* This must match scan.l's list of {space} characters */
|
||||
|
|
|
|||
Loading…
Reference in New Issue