♻️ 重构tree-sitter-tsf
This commit is contained in:
@@ -0,0 +1,306 @@
|
||||
# 完整的 TSLX 块匹配规则
|
||||
|
||||
## 基本原则
|
||||
- 在 `<?tslx>` 之后进入 `tslx_block`,默认所有内容都是文本(`tslx_content`)
|
||||
- Scanner 通过 lookahead 判断 `<?tsl` 和 `<?=` 的行为
|
||||
|
||||
---
|
||||
|
||||
## 匹配规则
|
||||
|
||||
### 规则 1:配对的 `<?tsl ... ?>`
|
||||
**条件**:遇到 `<?tsl` 且能找到对应的 `?>`
|
||||
**行为**:匹配为 `tsl_statement_block`
|
||||
**Token 序列**:`tsl_statement_start_tag` → `statement...` → `tsl_statement_end_tag`
|
||||
**结果**:`tslx_block` 继续
|
||||
|
||||
---
|
||||
|
||||
### 规则 2:配对的 `<?= ... ?>`
|
||||
**条件**:遇到 `<?=` 且能找到对应的 `?>`
|
||||
**行为**:匹配为 `tsl_expression_block`
|
||||
**Token 序列**:`tsl_expression_start_tag` → `expression` → `tsl_expression_end_tag`
|
||||
**结果**:`tslx_block` 继续
|
||||
|
||||
---
|
||||
|
||||
### 规则 3:未配对的 `<?tsl`(关键特性)
|
||||
**条件**:遇到 `<?tsl` 但找不到对应的 `?>`
|
||||
**行为**:
|
||||
- Scanner 通过 lookahead 判断后面没有 `?>`
|
||||
- **`<?tsl` 本身被识别为 `tslx_end_tag`**(不是生成额外的 token)
|
||||
- `tslx_block` 结束
|
||||
- Parser 跳出 `tslx_block`,继续解析后续内容(如 `a := 1;`)
|
||||
|
||||
**Token 序列**:
|
||||
```
|
||||
tslx_end_tag: "<?tsl" ← 这个 token 的文本内容就是 "<?tsl"
|
||||
```
|
||||
|
||||
**结果**:`tslx_block` 结束,后续内容由 `root` 的其他规则处理
|
||||
|
||||
---
|
||||
|
||||
### 规则 4:未配对的 `<?=`(错误情况)
|
||||
**条件**:遇到 `<?=` 但找不到对应的 `?>`
|
||||
**行为**:
|
||||
- Scanner 返回 `tsl_expression_start_tag`
|
||||
- Parser 期望 `expression` 和 `tsl_expression_end_tag`
|
||||
- 找不到 `?>` 导致**语法错误**
|
||||
|
||||
**结果**:Parser 报错
|
||||
|
||||
---
|
||||
|
||||
### 规则 5:到达 EOF
|
||||
**条件**:到达文件末尾,且之前没有遇到未配对的 `<?tsl`
|
||||
**行为**:在 EOF 位置生成 `tslx_end_tag`
|
||||
**结果**:`tslx_block` 正常结束
|
||||
|
||||
---
|
||||
|
||||
## Scanner Lookahead 策略
|
||||
|
||||
Scanner 需要判断 `<?tsl` 或 `<?=` 后面是否有匹配的 `?>`:
|
||||
|
||||
### 推荐策略(需选择其一):
|
||||
|
||||
**策略 A:扫描到换行或分号**
|
||||
```
|
||||
<?tsl ← 向前扫描
|
||||
a := 1; ← 遇到 ; 前没有 ?>,判定为未配对
|
||||
```
|
||||
- 优点:快速判断,符合单行语句的直觉
|
||||
- 缺点:多行语句可能误判
|
||||
|
||||
**策略 B:扫描到下一个 `<?` 或 EOF**
|
||||
```
|
||||
<?tsl ← 向前扫描
|
||||
a := 1;
|
||||
<?tsl ... ← 遇到下一个 <? 前没有 ?>,判定为未配对
|
||||
```
|
||||
- 优点:支持多行语句
|
||||
- 缺点:扫描距离可能较长
|
||||
|
||||
**策略 C:扫描固定距离(如 1000 字符)**
|
||||
```
|
||||
<?tsl ← 向前看 N 个字符
|
||||
... ← 如果在范围内找不到 ?>,判定为未配对
|
||||
```
|
||||
- 优点:性能可控
|
||||
- 缺点:可能误判超长的配对块
|
||||
|
||||
**当前实现**:_[填入你选择的策略]_
|
||||
|
||||
---
|
||||
|
||||
## 示例解析
|
||||
|
||||
### 示例 1:未配对的 `<?tsl`
|
||||
|
||||
#### 输入:
|
||||
```typescript
|
||||
|
||||
aaaa
|
||||
<?tsl
|
||||
a := 1;
|
||||
```
|
||||
|
||||
#### Token 序列:
|
||||
```
|
||||
1. tslx_tag "<?tslx>"
|
||||
2. tslx_content "\naaaa\n"
|
||||
3. tslx_end_tag "<?tsl" ← <?tsl 本身就是这个 token
|
||||
4. identifier "a"
|
||||
5. := ":="
|
||||
6. number "1"
|
||||
7. ; ";"
|
||||
```
|
||||
|
||||
#### AST 结构:
|
||||
```
|
||||
root
|
||||
├── tslx_block
|
||||
│ ├── tslx_tag: "<?tslx>"
|
||||
│ ├── tslx_content: "\naaaa\n"
|
||||
│ └── tslx_end_tag: "<?tsl"
|
||||
└── var_declaration
|
||||
├── name: "a"
|
||||
└── value: 1
|
||||
```
|
||||
|
||||
#### 说明:
|
||||
- `<?tsl` 触发 `tslx_block` 结束
|
||||
- `a := 1;` 在 `tslx_block` **外部**,由 `root` 的 `var_declaration` 匹配
|
||||
|
||||
---
|
||||
|
||||
### 示例 2:全部配对 + EOF
|
||||
|
||||
#### 输入:
|
||||
```typescript
|
||||
|
||||
aaaa
|
||||
|
||||
bbb
|
||||
```
|
||||
|
||||
#### Token 序列:
|
||||
```
|
||||
1. tslx_tag "<?tslx>"
|
||||
2. tslx_content "\naaaa\n"
|
||||
3. tsl_statement_start_tag "<?tsl"
|
||||
4. identifier "echo"
|
||||
5. number "1"
|
||||
6. ; ";"
|
||||
7. tsl_statement_end_tag "?>"
|
||||
8. tslx_content "\nbbb\n"
|
||||
9. tslx_end_tag "" ← EOF 位置生成
|
||||
```
|
||||
|
||||
#### AST 结构:
|
||||
```
|
||||
root
|
||||
└── tslx_block
|
||||
├── tslx_tag: "<?tslx>"
|
||||
├── tslx_content: "\naaaa\n"
|
||||
├── tsl_statement_block
|
||||
│ └── expression_statement
|
||||
│ └── call_expression: echo(1)
|
||||
├── tslx_content: "\nbbb\n"
|
||||
└── tslx_end_tag: (EOF)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 示例 3:未配对的 `<?=`(错误)
|
||||
|
||||
#### 输入:
|
||||
```typescript
|
||||
|
||||
<?=
|
||||
a + 1
|
||||
```
|
||||
|
||||
#### Token 序列:
|
||||
```
|
||||
1. tslx_tag "<?tslx>"
|
||||
2. tslx_content "\n"
|
||||
3. tsl_expression_start_tag "<?="
|
||||
4. identifier "a"
|
||||
5. + "+"
|
||||
6. number "1"
|
||||
[ERROR] 期望 tsl_expression_end_tag (?>),但遇到 EOF
|
||||
```
|
||||
|
||||
#### 结果:
|
||||
**语法错误**:`<?=` 必须有匹配的 `?>`
|
||||
|
||||
---
|
||||
|
||||
### 示例 4:混合使用
|
||||
|
||||
#### 输入:
|
||||
```typescript
|
||||
|
||||
text1
|
||||
|
||||
text2
|
||||
<?= 1 + 1 ?>
|
||||
text3
|
||||
<?tsl
|
||||
var x := 1;
|
||||
```
|
||||
|
||||
#### Token 序列:
|
||||
```
|
||||
1. tslx_tag "<?tslx>"
|
||||
2. tslx_content "\ntext1\n"
|
||||
3. tsl_statement_start_tag "<?tsl"
|
||||
4. ... (echo "hello")
|
||||
5. tsl_statement_end_tag "?>"
|
||||
6. tslx_content "\ntext2\n"
|
||||
7. tsl_expression_start_tag "<?="
|
||||
8. ... (1 + 1)
|
||||
9. tsl_expression_end_tag "?>"
|
||||
10. tslx_content "\ntext3\n"
|
||||
11. tslx_end_tag "<?tsl" ← 未配对,结束 tslx_block
|
||||
12. identifier "var"
|
||||
13. ... (x := 1)
|
||||
```
|
||||
|
||||
#### AST 结构:
|
||||
```
|
||||
root
|
||||
├── tslx_block
|
||||
│ ├── tslx_tag
|
||||
│ ├── tslx_content: "\ntext1\n"
|
||||
│ ├── tsl_statement_block: echo("hello")
|
||||
│ ├── tslx_content: "\ntext2\n"
|
||||
│ ├── tsl_expression_block: 1 + 1
|
||||
│ ├── tslx_content: "\ntext3\n"
|
||||
│ └── tslx_end_tag: "<?tsl"
|
||||
└── var_declaration: x := 1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Grammar.js 修改建议
|
||||
|
||||
### 当前定义:
|
||||
```javascript
|
||||
tslx_block: ($) =>
|
||||
prec.right(
|
||||
seq(
|
||||
$.tslx_tag,
|
||||
repeat(
|
||||
choice(
|
||||
$.tslx_content,
|
||||
$._tsl_statement_block,
|
||||
$._tsl_expression_block,
|
||||
$.tslx_end_tag // ❌ 问题:允许 end_tag 后继续匹配
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
### 建议修改:
|
||||
```javascript
|
||||
tslx_block: ($) =>
|
||||
prec.right(
|
||||
seq(
|
||||
$.tslx_tag,
|
||||
repeat(
|
||||
choice(
|
||||
$.tslx_content,
|
||||
$._tsl_statement_block,
|
||||
$._tsl_expression_block,
|
||||
),
|
||||
),
|
||||
$.tslx_end_tag // ✅ 移到 repeat 外面,作为结束标记
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- `tslx_end_tag` 是 `tslx_block` 的**终结符**,不应该在循环体内
|
||||
- 这样确保 `tslx_end_tag` 后不会再匹配 `tslx_content` 等内容
|
||||
|
||||
---
|
||||
|
||||
## 核心要点总结
|
||||
|
||||
1. ✅ `<?tsl` 有**双重身份**:
|
||||
- 有 `?>` → `tsl_statement_start_tag`
|
||||
- 无 `?>` → `tslx_end_tag`
|
||||
|
||||
2. ✅ `<?=` **必须配对**,否则语法错误
|
||||
|
||||
3. ✅ `<?tsl` 作为 `tslx_end_tag` 时,其文本内容就是 `"<?tsl"`
|
||||
|
||||
4. ✅ Scanner 通过 **lookahead** 判断是否有匹配的 `?>`
|
||||
|
||||
5. ✅ `tslx_end_tag` 在 Grammar 中应该是 `tslx_block` 的**终结符**
|
||||
|
||||
6. ✅ EOF 时自动生成 `tslx_end_tag` 来正常结束 `tslx_block`
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "tree-sitter-tsf_binding",
|
||||
"dependencies": [
|
||||
"<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except"
|
||||
],
|
||||
"include_dirs": [
|
||||
"src"
|
||||
],
|
||||
"sources": [
|
||||
"bindings/node/binding.cc",
|
||||
"src/parser.c",
|
||||
"src/scanner.c"
|
||||
],
|
||||
"conditions": [
|
||||
["OS!='win'", {
|
||||
"cflags_c": [
|
||||
"-std=c11"
|
||||
]
|
||||
}, {
|
||||
"cflags_c": [
|
||||
"/std:c11",
|
||||
"/utf-8"
|
||||
]
|
||||
}]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <napi.h>
|
||||
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
|
||||
extern "C" TSLanguage *tree_sitter_tsf();
|
||||
|
||||
// "tree_sitter_your_language_binding" is the symbol that Node.js looks for.
|
||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||
exports["name"] = Napi::String::New(env, "tsf");
|
||||
auto language = Napi::External<TSLanguage>::New(env, tree_sitter_tsf());
|
||||
exports["language"] = language;
|
||||
return exports;
|
||||
}
|
||||
|
||||
NODE_API_MODULE(tree_sitter_tsf_binding, Init)
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+6251
-6779
File diff suppressed because it is too large
Load Diff
+2016
-2169
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,437 @@
|
||||
#include <wctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "tree_sitter/parser.h"
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
#if DEBUG
|
||||
#define LOG(...) fprintf(stderr, "[SCANNER] " __VA_ARGS__)
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
enum TokenType
|
||||
{
|
||||
TSLX_CONTENT,
|
||||
TSL_STATEMENT_START_TAG,
|
||||
TSL_STATEMENT_END_TAG,
|
||||
TSL_EXPRESSION_START_TAG,
|
||||
TSL_EXPRESSION_END_TAG,
|
||||
TSLX_END_TAG
|
||||
};
|
||||
|
||||
enum State
|
||||
{
|
||||
STATE_ROOT,
|
||||
STATE_TSLX,
|
||||
STATE_TSL_STATEMENT,
|
||||
STATE_TSL_EXPRESSION
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
enum State* states;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
} StateStack;
|
||||
|
||||
static void stack_init(StateStack* stack)
|
||||
{
|
||||
stack->capacity = 8;
|
||||
stack->size = 0;
|
||||
stack->states = malloc(stack->capacity * sizeof(enum State));
|
||||
if (stack->states)
|
||||
{
|
||||
stack->states[0] = STATE_ROOT;
|
||||
stack->size = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void stack_free(StateStack* stack)
|
||||
{
|
||||
if (stack->states)
|
||||
{
|
||||
free(stack->states);
|
||||
stack->states = NULL;
|
||||
}
|
||||
stack->size = 0;
|
||||
stack->capacity = 0;
|
||||
}
|
||||
|
||||
static void stack_push(StateStack* stack, enum State state)
|
||||
{
|
||||
if (stack->size >= stack->capacity)
|
||||
{
|
||||
stack->capacity *= 2;
|
||||
stack->states = realloc(stack->states, stack->capacity * sizeof(enum State));
|
||||
}
|
||||
if (stack->states)
|
||||
{
|
||||
stack->states[stack->size++] = state;
|
||||
}
|
||||
}
|
||||
|
||||
static enum State stack_pop(StateStack* stack)
|
||||
{
|
||||
if (stack->size > 1)
|
||||
{
|
||||
return stack->states[--stack->size];
|
||||
}
|
||||
return STATE_ROOT;
|
||||
}
|
||||
|
||||
static enum State stack_top(const StateStack* stack)
|
||||
{
|
||||
return stack->size > 0 ? stack->states[stack->size - 1] : STATE_ROOT;
|
||||
}
|
||||
|
||||
void* tree_sitter_tsf_external_scanner_create()
|
||||
{
|
||||
StateStack* stack = malloc(sizeof(StateStack));
|
||||
if (stack)
|
||||
{
|
||||
stack_init(stack);
|
||||
}
|
||||
LOG("Scanner created\n");
|
||||
return stack;
|
||||
}
|
||||
|
||||
void tree_sitter_tsf_external_scanner_destroy(void* payload)
|
||||
{
|
||||
StateStack* stack = (StateStack*)payload;
|
||||
if (stack)
|
||||
{
|
||||
stack_free(stack);
|
||||
free(stack);
|
||||
}
|
||||
LOG("Scanner destroyed\n");
|
||||
}
|
||||
|
||||
unsigned tree_sitter_tsf_external_scanner_serialize(void* payload, char* buffer)
|
||||
{
|
||||
StateStack* stack = (StateStack*)payload;
|
||||
if (!stack || stack->size == 0)
|
||||
return 0;
|
||||
|
||||
size_t bytes_to_copy = stack->size * sizeof(enum State);
|
||||
if (bytes_to_copy > TREE_SITTER_SERIALIZATION_BUFFER_SIZE)
|
||||
{
|
||||
bytes_to_copy = TREE_SITTER_SERIALIZATION_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
memcpy(buffer, stack->states, bytes_to_copy);
|
||||
return bytes_to_copy;
|
||||
}
|
||||
|
||||
void tree_sitter_tsf_external_scanner_deserialize(void* payload, const char* buffer, unsigned length)
|
||||
{
|
||||
StateStack* stack = (StateStack*)payload;
|
||||
if (!stack)
|
||||
return;
|
||||
|
||||
stack_free(stack);
|
||||
stack_init(stack);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
size_t count = length / sizeof(enum State);
|
||||
for (size_t i = 0; i < count && i < stack->capacity; i++)
|
||||
{
|
||||
enum State state;
|
||||
memcpy(&state, buffer + i * sizeof(enum State), sizeof(enum State));
|
||||
if (i == 0)
|
||||
{
|
||||
stack->states[0] = state;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack_push(stack, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void skip_whitespace(TSLexer* lexer)
|
||||
{
|
||||
while (iswspace(lexer->lookahead))
|
||||
{
|
||||
lexer->advance(lexer, true);
|
||||
}
|
||||
}
|
||||
|
||||
static bool lookahead_for_close_tag(TSLexer* lexer)
|
||||
{
|
||||
LOG(" [lookahead_for_close_tag] Starting lookahead\n");
|
||||
|
||||
while (lexer->lookahead != '\0')
|
||||
{
|
||||
if (lexer->lookahead == '?')
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead == '>')
|
||||
{
|
||||
LOG(" [lookahead_for_close_tag] Found ?>, returning true\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (lexer->lookahead == '<')
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead == '?')
|
||||
{
|
||||
LOG(" [lookahead_for_close_tag] Found next <?, returning false\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
}
|
||||
}
|
||||
|
||||
LOG(" [lookahead_for_close_tag] Reached EOF, returning false\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static int peek_special_tag(TSLexer* lexer)
|
||||
{
|
||||
if (lexer->lookahead != '<')
|
||||
return 0;
|
||||
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead != '?')
|
||||
return 0;
|
||||
|
||||
lexer->advance(lexer, false);
|
||||
|
||||
if (lexer->lookahead == '=')
|
||||
{
|
||||
LOG(" [peek_special_tag] Found <?=\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (towlower(lexer->lookahead) == 't')
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
if (towlower(lexer->lookahead) == 's')
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
if (towlower(lexer->lookahead) == 'l')
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
if (!iswalnum(lexer->lookahead) && lexer->lookahead != '_')
|
||||
{
|
||||
LOG(" [peek_special_tag] Found <?tsl\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool scan_tslx_content(TSLexer* lexer)
|
||||
{
|
||||
bool has_content = false;
|
||||
LOG(" [scan_tslx_content] Starting scan\n");
|
||||
|
||||
while (lexer->lookahead != '\0')
|
||||
{
|
||||
if (lexer->lookahead == '<')
|
||||
{
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
int tag_type = peek_special_tag(lexer);
|
||||
|
||||
if (tag_type > 0)
|
||||
{
|
||||
LOG(" [scan_tslx_content] Found special tag, stopping. has_content=%d\n", has_content);
|
||||
return has_content;
|
||||
}
|
||||
|
||||
has_content = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
has_content = true;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(" [scan_tslx_content] Reached EOF, has_content=%d\n", has_content);
|
||||
return has_content;
|
||||
}
|
||||
|
||||
bool tree_sitter_tsf_external_scanner_scan(void* payload, TSLexer* lexer, const bool* valid_symbols)
|
||||
{
|
||||
StateStack* stack = (StateStack*)payload;
|
||||
if (!stack)
|
||||
{
|
||||
LOG("ERROR: stack is NULL\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
enum State current_state = stack_top(stack);
|
||||
|
||||
LOG("\n=== SCAN START ===\n");
|
||||
LOG("Current state: %d (0=ROOT, 1=TSLX, 2=TSL_STATEMENT, 3=TSL_EXPRESSION)\n", current_state);
|
||||
LOG("Current char: '%c' (0x%02x)\n", lexer->lookahead, lexer->lookahead);
|
||||
LOG("Valid symbols: CONTENT=%d, TSL_START=%d, TSL_END=%d, EXPR_START=%d, EXPR_END=%d, TSLX_END=%d\n",
|
||||
valid_symbols[TSLX_CONTENT],
|
||||
valid_symbols[TSL_STATEMENT_START_TAG],
|
||||
valid_symbols[TSL_STATEMENT_END_TAG],
|
||||
valid_symbols[TSL_EXPRESSION_START_TAG],
|
||||
valid_symbols[TSL_EXPRESSION_END_TAG],
|
||||
valid_symbols[TSLX_END_TAG]);
|
||||
|
||||
// ⚠️ 关键修复:通过 valid_symbols 推断状态切换
|
||||
// 如果当前在 ROOT 状态,但 parser 期望 TSLX 内部的 token,说明刚匹配完 <?tslx>
|
||||
if (current_state == STATE_ROOT &&
|
||||
(valid_symbols[TSLX_CONTENT] ||
|
||||
valid_symbols[TSL_STATEMENT_START_TAG] ||
|
||||
valid_symbols[TSL_EXPRESSION_START_TAG] ||
|
||||
valid_symbols[TSLX_END_TAG]))
|
||||
{
|
||||
LOG("State transition: ROOT -> TSLX (inferred from valid_symbols)\n");
|
||||
stack_push(stack, STATE_TSLX);
|
||||
current_state = STATE_TSLX;
|
||||
}
|
||||
|
||||
if (current_state == STATE_TSL_STATEMENT || current_state == STATE_TSL_EXPRESSION)
|
||||
{
|
||||
skip_whitespace(lexer);
|
||||
LOG("After skip whitespace: '%c' (0x%02x)\n", lexer->lookahead, lexer->lookahead);
|
||||
}
|
||||
|
||||
if (current_state == STATE_TSLX)
|
||||
{
|
||||
LOG("In STATE_TSLX\n");
|
||||
|
||||
if (lexer->lookahead == '\0' && valid_symbols[TSLX_END_TAG])
|
||||
{
|
||||
LOG("Found EOF, returning TSLX_END_TAG\n");
|
||||
lexer->mark_end(lexer);
|
||||
lexer->result_symbol = TSLX_END_TAG;
|
||||
stack_pop(stack);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lexer->lookahead == '<')
|
||||
{
|
||||
LOG("Found '<', checking for tag\n");
|
||||
lexer->advance(lexer, false);
|
||||
|
||||
if (lexer->lookahead == '?')
|
||||
{
|
||||
LOG("Found '<?', checking tag type\n");
|
||||
lexer->advance(lexer, false);
|
||||
|
||||
if (lexer->lookahead == '=' && valid_symbols[TSL_EXPRESSION_START_TAG])
|
||||
{
|
||||
LOG("Found '<?=', returning TSL_EXPRESSION_START_TAG\n");
|
||||
lexer->advance(lexer, false);
|
||||
lexer->mark_end(lexer);
|
||||
lexer->result_symbol = TSL_EXPRESSION_START_TAG;
|
||||
stack_push(stack, STATE_TSL_EXPRESSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (towlower(lexer->lookahead) == 't')
|
||||
{
|
||||
LOG("Found 't', checking for 'tsl'\n");
|
||||
lexer->advance(lexer, false);
|
||||
|
||||
if (towlower(lexer->lookahead) == 's')
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
|
||||
if (towlower(lexer->lookahead) == 'l')
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
|
||||
LOG("Found 'tsl', next char: '%c' (0x%02x)\n", lexer->lookahead, lexer->lookahead);
|
||||
|
||||
if (!iswalnum(lexer->lookahead) && lexer->lookahead != '_')
|
||||
{
|
||||
LOG("Valid <?tsl delimiter, performing lookahead\n");
|
||||
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
bool has_close_tag = lookahead_for_close_tag(lexer);
|
||||
LOG("Lookahead result: has_close_tag = %d\n", has_close_tag);
|
||||
|
||||
if (has_close_tag && valid_symbols[TSL_STATEMENT_START_TAG])
|
||||
{
|
||||
LOG("Returning TSL_STATEMENT_START_TAG\n");
|
||||
lexer->result_symbol = TSL_STATEMENT_START_TAG;
|
||||
stack_push(stack, STATE_TSL_STATEMENT);
|
||||
return true;
|
||||
}
|
||||
else if (!has_close_tag && valid_symbols[TSLX_END_TAG])
|
||||
{
|
||||
LOG("Returning TSLX_END_TAG (<?tsl without ?>)\n");
|
||||
lexer->result_symbol = TSLX_END_TAG;
|
||||
stack_pop(stack);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_symbols[TSLX_CONTENT])
|
||||
{
|
||||
LOG("Trying to scan TSLX_CONTENT\n");
|
||||
if (scan_tslx_content(lexer))
|
||||
{
|
||||
LOG("Successfully scanned TSLX_CONTENT\n");
|
||||
lexer->result_symbol = TSLX_CONTENT;
|
||||
return true;
|
||||
}
|
||||
LOG("Failed to scan TSLX_CONTENT\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (current_state == STATE_TSL_STATEMENT)
|
||||
{
|
||||
LOG("In STATE_TSL_STATEMENT\n");
|
||||
if (lexer->lookahead == '?' && valid_symbols[TSL_STATEMENT_END_TAG])
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead == '>')
|
||||
{
|
||||
LOG("Found '?>', returning TSL_STATEMENT_END_TAG\n");
|
||||
lexer->advance(lexer, false);
|
||||
lexer->mark_end(lexer);
|
||||
lexer->result_symbol = TSL_STATEMENT_END_TAG;
|
||||
stack_pop(stack);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_state == STATE_TSL_EXPRESSION)
|
||||
{
|
||||
LOG("In STATE_TSL_EXPRESSION\n");
|
||||
if (lexer->lookahead == '?' && valid_symbols[TSL_EXPRESSION_END_TAG])
|
||||
{
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead == '>')
|
||||
{
|
||||
LOG("Found '?>', returning TSL_EXPRESSION_END_TAG\n");
|
||||
lexer->advance(lexer, false);
|
||||
lexer->mark_end(lexer);
|
||||
lexer->result_symbol = TSL_EXPRESSION_END_TAG;
|
||||
stack_pop(stack);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG("Returning false (no match)\n");
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,725 @@
|
||||
type IDS_AuditExpr = class
|
||||
|
||||
class function FormulaeCount(data, precision);
|
||||
class function FormulaeConvert(v);
|
||||
class function GetReportInfo(data);
|
||||
class function analysisFormulae(Formulae); //解析勾稽表达式
|
||||
class function specialStrReplace(str, r_type); //针对部分特殊字符进行临时转换 r_type: 1. 转化为特殊串 2. 转化为原字符串
|
||||
class function encryptFormulae(s); //base64编码
|
||||
class function decryptFormulae(s); //base64解码
|
||||
class function XBRLInsert(Formulae, FundType, Classify, isencrypt); //勾稽条目插入
|
||||
|
||||
end;
|
||||
|
||||
|
||||
class function IDS_AuditExpr.FormulaeCount(data, precision);
|
||||
begin
|
||||
if not precision then
|
||||
precision := 0;
|
||||
|
||||
if ansipos("#替换文本#", data) then // 将替换标志去除
|
||||
data := ansireplaceText(data, "#替换文本#", "");
|
||||
|
||||
sysparams["LResult"] := "";
|
||||
sysparams["RResult"] := "";
|
||||
sysparams["chaE"] := "";
|
||||
|
||||
fStr := "##0"$(precision>0?"."$DupeString('0', precision):"");
|
||||
data := ansireplaceText(data, "≠", "<>"); // eval不支持 ≠ , 需要转为<> 才能进行计算
|
||||
WCZ := GetSysParam("WuChaZhi");
|
||||
|
||||
if data like "\\) or \\(" or data like ":true" or data like "nil" or data like ' in ' or data like ' without ' or data like "\\) and \\("
|
||||
or data like '<>' or data like "funcOfIf" or data like "ifThen" or data like "isNull" or data like " and "
|
||||
or ansipos("公募基金代码", data) or ansipos("公募基金简称(", data) or ansipos("公募基金全称", data) or ansipos("textMatch", data) or ansipos("getMonthSpan", data)
|
||||
or ansipos("fundInfo", data) or ansipos(" or ", data) or ansipos("基金存续起始日", data) then
|
||||
begin
|
||||
//修复 XXX=nil xxx<>nil xxx为字符串时eval执行报错问题 -by fangf
|
||||
if data like '<>nil' and not (data like "\\) and \\(") then
|
||||
begin
|
||||
if str2array(data,"<>")[0]='0' or ifstring(str2array(data,"<>")[0]) then
|
||||
begin
|
||||
if str2array(data,"<>")[0]='nil' then data:='nil<>nil';
|
||||
else if data like "\\) or \\(" then //修复(XXX<>nil) or (XXX<>nil) 勾稽不生效问题 ex-wanzl
|
||||
begin
|
||||
data:= replaceText(data, ")", "");
|
||||
data:= replaceText(data, "(", "");
|
||||
end
|
||||
else
|
||||
data:="'"$tostring(str2array(data,"<>")[0])$"'"$'<>nil';
|
||||
end
|
||||
|
||||
end
|
||||
if data like '=nil' and not (data like "\\) and \\(") and not (data like "\\) or \\(") then
|
||||
begin
|
||||
if str2array(data,"=")[0]='0' or ifstring(str2array(data,"=")[0]) then
|
||||
begin
|
||||
if str2array(data,"=")[0]='nil' then data:='nil=nil';
|
||||
else
|
||||
data:="'"$tostring(str2array(data,"=")[0])$"'"$'=nil';
|
||||
end
|
||||
end
|
||||
//用于处理<> 条件下左右两边都不等于nil的情况下勾稽不到的情况 -by fangf
|
||||
if data like '<>' and not (data like "\\) and \\(") and not (data like "\\) or \\(") and not (data like "ifThen") then
|
||||
begin
|
||||
if not ( str2array(data,"<>")[0] like 'nil') and not (str2array(data,"<>")[1] like 'nil') then
|
||||
begin
|
||||
try
|
||||
StrToCurr(str2array(data,"<>")[0]);
|
||||
except
|
||||
LSTR:=1;
|
||||
end;
|
||||
try
|
||||
StrToCurr(str2array(data,"<>")[1]);
|
||||
except
|
||||
RSTR:=1;
|
||||
end;
|
||||
IF LSTR AND RSTR THEN
|
||||
begin
|
||||
if not (str2array(data,"<>")[0]=str2array(data,"<>")[1]) then
|
||||
return 1;
|
||||
return data;
|
||||
end
|
||||
end
|
||||
end
|
||||
if data like "ifThen" then
|
||||
begin
|
||||
try
|
||||
paramList := ansireplaceText(ansireplaceText(data, "ifThen(", ""), ")", "");
|
||||
paramList := str2array(paramList, ",");
|
||||
for paramNum:=0 to length(paramList)-1 do
|
||||
begin
|
||||
if ParseRegExpr("^([\\d\\.+\\-\\*\\/\\)\\(]+)([=<>]{1,2})([\\d\\.+\\-\\*\\/\\)\\(]+)$",trim(paramList[paramNum]),"",res,MPos,Mlen)=1 then
|
||||
begin
|
||||
leftS := eval(&res[0][1]);
|
||||
mark := res[0][2];
|
||||
rightS := eval(&res[0][3]);
|
||||
replaceS := leftS$mark$rightS;
|
||||
data := replaceText(data, paramList[paramNum] ,replaceS);
|
||||
end
|
||||
else
|
||||
continue;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
if data like "without" then //用于处理集合1不存在于集合2 ex-wanzl
|
||||
begin
|
||||
data := replaceText(data, "array", "");
|
||||
tmp := replaceText(replaceText(data, ")", ""), "(", "");
|
||||
tmp := str2array(tmp, " without ");
|
||||
|
||||
if length(tmp)=2 then
|
||||
begin
|
||||
tmp1 := str2array(tmp[0], ",");
|
||||
tmp2 := str2array(tmp[1], ",");
|
||||
arr := array();
|
||||
for i := 0 to length(tmp1) do
|
||||
begin
|
||||
if tmp1[i] in tmp2 then
|
||||
arr[length(arr)] := tmp1[i] ;
|
||||
end
|
||||
if istable(arr) then
|
||||
begin
|
||||
tmp3 := "【不符合项:"$array2str(DistinctStr(arr), ",")$"】" ;
|
||||
return replaceText(data, "array", "")$tmp3;
|
||||
end
|
||||
else return 1;
|
||||
end
|
||||
else
|
||||
tmp2 := "";
|
||||
return replaceText(data, "array", "")$tmp2;
|
||||
end
|
||||
else if eval(&data)=1 then
|
||||
return 1;
|
||||
else if data like " in " then //用于处理集合函数公式
|
||||
begin
|
||||
data := replaceText(data, "array", "");
|
||||
tmp2 := "以下项目存在差异,请检查。【";
|
||||
dataRe := str2array(data, " and ");
|
||||
for j:=0 to length(dataRe)-1 do
|
||||
begin
|
||||
tmp := replaceText(replaceText(dataRe[j], ")", ""), "(", "");
|
||||
tmp := str2array(tmp, " in ");
|
||||
if length(tmp)=2 then
|
||||
begin
|
||||
chayi := str2array(tmp[0], ",") minus str2array(tmp[1], ",");
|
||||
if istable(chayi) then
|
||||
tmp2 += (j=0?"":";")$array2str(chayi, ",");
|
||||
end else
|
||||
tmp2 += "";
|
||||
end;
|
||||
tmp2 += "】";
|
||||
data := replaceText(data, "in", "与");
|
||||
return tmp2;
|
||||
end
|
||||
else if data like "nil" and not (data like "\\) and \\(") then
|
||||
begin
|
||||
if (data like '<>' or data like '=') and (str2array(data,"<>")[0]='nil' or str2array(data,"<>")[0]=nil or str2array(data,"<>")[1]=nil or str2array(data,"<>")[1]='nil') then
|
||||
return data$"【nil】";
|
||||
return data$"【"$FormatFloat(fStr,setPrecision(eval(&str2array(data,"=")[1]),precision))$"】";
|
||||
end
|
||||
else
|
||||
return data$"【"$eval(&data)$"】";
|
||||
|
||||
end;
|
||||
ParseRegExpr("([<|>|=])+",data, "" , ret, MPos, Mlen);
|
||||
if istable(ret) then
|
||||
flag := ret[0][0];
|
||||
|
||||
tmp := str2array(data, flag);
|
||||
|
||||
for i:=0 to length(tmp)-1 do
|
||||
tmp[i] := replaceText(tmp[i], "--", "+");
|
||||
try
|
||||
Rresult := eval(&tmp[1]);
|
||||
except
|
||||
//dolog("zhang1021",tmp[1]);//记录报错公式
|
||||
end;
|
||||
{if length(tmp)>2 then
|
||||
return "公式错误."; }
|
||||
|
||||
try
|
||||
LResult := eval(&tmp[0]);
|
||||
if WCZ then
|
||||
begin
|
||||
WCZ += 0.000000001;
|
||||
if samevalue(setPrecision(LResult,precision),setPrecision(Rresult,precision),WCZ) then
|
||||
return 1;
|
||||
end;
|
||||
LResult := isNan(LResult)?0:Lresult;
|
||||
Rresult := isNan(Rresult)?0:Rresult;
|
||||
//if eval(&floattostr(setPrecision(LResult,precision))$flag$floattostr(setPrecision(Rresult,precision))) then
|
||||
|
||||
// 获取勾稽的左边结果/右边结果/差额,并给予入库
|
||||
sysparams["LResult"] := FormatFloat(fStr, Lresult);
|
||||
sysparams["RResult"] := FormatFloat(fStr, Rresult);
|
||||
sysparams["chaE"] := strtofloat(FormatFloat(fStr, Lresult))-strtofloat(FormatFloat(fStr, Rresult));
|
||||
|
||||
if eval(&FormatFloat(fStr, LResult)$flag$FormatFloat(fStr,Rresult)) then
|
||||
return 1;
|
||||
return tmp[0]$(tmp[0] like "[\\+\\-\\*\\/]"?"【"$FormatFloat(fStr, Lresult)$"】":"")$flag$tmp[1]$
|
||||
(tmp[1] like "[\\+\\-\\*\\/]"?"【"$FormatFloat(fStr, Rresult)$"】":"");
|
||||
except
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
//将公式的数值转化为千分位
|
||||
class function IDS_AuditExpr.FormulaeConvert(v);
|
||||
begin
|
||||
if not v then
|
||||
return v;
|
||||
ParseRegExpr("\\d+\\.\\d+|\\d+",v,"",ret,MPos,Mlen);
|
||||
|
||||
tmp := v;
|
||||
ret := select distinct * from ret order by length([0]) desc end;
|
||||
for i:=0 to length(ret)-1 do
|
||||
begin
|
||||
if length(ret[i][0])>3 then
|
||||
begin
|
||||
//转化为千分位后根据原值小数位数保留小数位
|
||||
if ret[i][0] like "\\." then
|
||||
p := length(str2array(ret[i][0], ".")[1]);
|
||||
|
||||
tmpvalue := FormatFloat("#,##0"$(p?"."$DupeString('0', p):""), strtofloat(ret[i][0]));
|
||||
end else
|
||||
continue;
|
||||
|
||||
tmp := replaceText(tmp, ret[i][0], tmpvalue);
|
||||
end;
|
||||
|
||||
return tmp;
|
||||
end;
|
||||
|
||||
//获取报告讯息
|
||||
class function IDS_AuditExpr.GetReportInfo(data);
|
||||
begin
|
||||
//针对提交勾稽去取报告id
|
||||
if istable(data) then
|
||||
begin
|
||||
did:=data[0];
|
||||
sql:="select a.ID,
|
||||
a.fundid,
|
||||
a.reportdate,
|
||||
a.begindate,
|
||||
"$ids_tdbc("td_ifnull", array("g.ORG_ESTABLISH_DATE", ids_tdbc("td_strtofloat", array(ids_tdbc("td_formatDateTime", array("p.establishdate", "yyyymmdd"))))))$" Fdate,
|
||||
a.CLASSIFY
|
||||
from ts_rformaldata c
|
||||
left join ts_reportinfo a
|
||||
on a.fundid = c.tip2
|
||||
and a.classify = c.classify
|
||||
and ((a.change_date is null and a.publishdate = c.enddate and
|
||||
a.begindate = c.begindate) or
|
||||
(a.change_date is not null and
|
||||
((c.enddate = a.publishdate and
|
||||
c.begindate = "$ids_tdbc("td_strtofloat", array(ids_tdbc("td_formatDateTime", array("a.change_date", "yyyymmdd"))))$") or
|
||||
(c.enddate = "$ids_tdbc("td_incDay", array("a.change_date", -1))$" and
|
||||
c.begindate = a.begindate))))
|
||||
left join ts_productinfo p
|
||||
on a.fundid = p.productid
|
||||
and p.isvalid = 1
|
||||
left join TS_FUNDCHANGELOG g
|
||||
on p.productid = g.fundid
|
||||
and g.isvalid = 1
|
||||
where c.id = '"$did$"' and p.isvalid = 1
|
||||
and c.status <> 0 order by a.isvalid desc";
|
||||
|
||||
ret:=ids_execsql(sql,r);
|
||||
return r;
|
||||
|
||||
end else
|
||||
rid := data;
|
||||
|
||||
sql :="select ID,r.fundid,reportdate,begindate,"$ids_TDBC("td_ifnull", array("ORG_ESTABLISH_DATE", ids_TDBC("td_strtofloat",array(ids_TDBC("td_formatDateTime", array("p.establishdate", "yyyymmdd"))))))$" Fdate, CLASSIFY, r.CHANGE_DATE
|
||||
from ts_reportinfo r join ts_productinfo p on r.fundid = p.productid
|
||||
left join TS_FUNDCHANGELOG g on p.productid =g.fundid
|
||||
where r.isvalid=1 and id = '"$rid$"' and p.isvalid = 1 order by Fdate";
|
||||
ids_execsql(sql,r);
|
||||
|
||||
return r;
|
||||
end;
|
||||
|
||||
//解析勾稽表达式,传入一个字符串类型的勾稽表达式,去掉运算符,返回一个数组。
|
||||
class function IDS_AuditExpr.analysisFormulae(Formulae);
|
||||
Begin
|
||||
//去除空格
|
||||
sysparams["StrReplace"] := array();
|
||||
Formulae := specialStrReplace(Formulae, 0);
|
||||
if Pos('or', Formulae) or Pos('and', Formulae) then
|
||||
ReplaceStr := ReplaceText(Formulae, ' ', '');
|
||||
else
|
||||
ReplaceStr := Formulae;
|
||||
// 勾稽公式页面获取章节公式指标额外增加的文本需替换掉
|
||||
addReplace := array("(总和)","整表","(上期末)","上期年报","一季报","二季报","三季报","四季报",
|
||||
"中报","上期报告","前年报告","(期初)","(期末)","(集合)","(份额总和)","TXT","#");
|
||||
//替换字符串中的运算符
|
||||
wantReplace := Array('GetMaxValue', 'GetMinValue', '>=', '<=', '+', '-', '*', '/', '>', '<', '=', 'and', 'or', 'Min', 'Max', 'abs', 'AnsiContainsText', 'in',
|
||||
'without', '?', ':ture', ';;;', ';;', ':true',',','(买入)','(卖出)','(下属数据总和)','funcOfIf'{, "'"}, "funcOfRoundTo", "funcOfRoundDown",
|
||||
"funcOfIsNull", "not", "SameText", "ifThen", "isNull", "≠", "公募基金代码", "公募基金全称", "公募基金简称", "textMatch", "getMonthSpan", "fundInfo", "基金存续起始日");
|
||||
if SYSPARAMS["addChapterRow"] then
|
||||
wantReplace &= addReplace;
|
||||
|
||||
for i:=0 to length(wantReplace)-1 do
|
||||
Begin
|
||||
if Pos(wantReplace[i], ReplaceStr) then
|
||||
ReplaceStr := ReplaceStr(ReplaceStr, wantReplace[i], ';');
|
||||
End;
|
||||
|
||||
//正则替换掉and or min等情况的字符
|
||||
reAry := array(';\\d+;', ';\\d+$', ';Min\\\(', ';\\d+;', ';\\d+\\\);\\\(', ';\\d+\\\)', ';\\\)\\\);', ';\\\(\\\(;', ';Max\\\(',';\\d+\\.\\d+',';abs\\\(');
|
||||
for k := 0 to length(reAry) - 1 do
|
||||
begin
|
||||
ParseRegExpr(reAry[k], ReplaceStr, "", matchResult, MPos, Mlen);
|
||||
if matchResult<>0 then
|
||||
Begin
|
||||
for j:=0 to length(matchResult)-1 do
|
||||
ReplaceStr := ReplaceText(ReplaceStr, matchResult[j][0], ';');
|
||||
End;
|
||||
end;
|
||||
|
||||
if ReplaceStr like ';$' then ReplaceStr := ReplaceStr[1:length(ReplaceStr)-1];
|
||||
if ReplaceStr like '^;' then ReplaceStr := ReplaceStr[2:length(ReplaceStr)];
|
||||
|
||||
//将字符串转化为数组
|
||||
tAry := Str2Array(ReplaceStr,';');
|
||||
//去除每个元素首尾的空格
|
||||
sAry := array();
|
||||
for h := 0 to length(tAry) - 1 do
|
||||
begin
|
||||
sAry[h] := Trim(tAry[h]);
|
||||
end;
|
||||
|
||||
if not (Pos('(', ReplaceStr) or Pos(')', ReplaceStr)) then
|
||||
begin
|
||||
sAry := sselect distinct specialStrReplace(thisrow, 1) from sAry where not (thisrow like "^\\d+$") order by lengthW(specialStrReplace(thisrow, 1)) desc end;
|
||||
return sAry;
|
||||
//return array2str(sAry);
|
||||
end;
|
||||
|
||||
//去掉每个元素中多余的括号
|
||||
nAry := array();
|
||||
|
||||
for m := 0 to length(sAry) - 1 do
|
||||
begin
|
||||
s := sAry[m];
|
||||
|
||||
//查找"("与")"的位置
|
||||
sLen := length(s);
|
||||
brackets := array('(',')');
|
||||
markAry := array(array(),array());
|
||||
|
||||
for idx := 0 to length(brackets)-1 do
|
||||
begin
|
||||
t:=s;
|
||||
i:=1;
|
||||
j:=0;
|
||||
k:=0;
|
||||
|
||||
while AnsiContainsText(t,brackets[idx]) do
|
||||
begin
|
||||
i := pos(brackets[idx], t);
|
||||
k := k + i;
|
||||
markAry[idx][j]:=k;
|
||||
j:=j+1;
|
||||
if k+1>sLen then break;
|
||||
t:=s[k+1:sLen];
|
||||
end;
|
||||
end;
|
||||
|
||||
if not markAry[0] then
|
||||
begin
|
||||
if not markAry[1] then
|
||||
begin
|
||||
nAry[m] := s;
|
||||
continue;
|
||||
end
|
||||
else
|
||||
begin
|
||||
s := ReplaceText(s, ')', '');
|
||||
nAry[m] := s;
|
||||
continue;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if not markAry[1] then
|
||||
begin
|
||||
s := ReplaceText(s, '(', '');
|
||||
nAry[m] := s;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
//就近原则匹配相近的左右括号
|
||||
leftPair := array();
|
||||
rightPair := array();
|
||||
for i := 0 to length(markAry[1]) - 1 do
|
||||
begin
|
||||
for j := 0 to length(markAry[0]) - 1 do
|
||||
begin
|
||||
if markAry[0][j] in leftPair then continue;
|
||||
if markAry[0][j] < markAry[1][i] then
|
||||
begin
|
||||
k := 1;
|
||||
while markAry[0][j+k] do
|
||||
begin
|
||||
if not (markAry[0][j+k] in leftPair) then break;
|
||||
k := k + 1;
|
||||
end;
|
||||
if markAry[0][j+k] then
|
||||
begin
|
||||
if markAry[0][j+k] > markAry[1][i] then
|
||||
begin
|
||||
leftPair[length(leftPair)] := markAry[0][j];
|
||||
rightPair[length(rightPair)] := markAry[1][i];
|
||||
end
|
||||
else continue;
|
||||
end
|
||||
else
|
||||
begin
|
||||
leftPair[length(leftPair)] := markAry[0][j];
|
||||
rightPair[length(rightPair)] := markAry[1][i];
|
||||
end;
|
||||
end
|
||||
else break;
|
||||
end;
|
||||
end;
|
||||
|
||||
//删除多余的括号
|
||||
for l := 0 to length(markAry[0]) - 1 do
|
||||
begin
|
||||
if not (markAry[0][l] in leftPair) then s[markAry[0][l]:markAry[0][l]] := '';
|
||||
end;
|
||||
|
||||
for n := 0 to length(markAry[1]) -1 do
|
||||
begin
|
||||
if not (markAry[1][n] in rightPair) then s[markAry[1][n]:markAry[1][n]] := '';
|
||||
end;
|
||||
|
||||
//删除占位符
|
||||
//s := replaceStr(trim(s), '\0', '');
|
||||
|
||||
//删除头尾能够配对的括号,针对不规范的公式,需要加try包裹防止公式列表页面查询时报错
|
||||
try
|
||||
if rightPair[length(rightPair)-1] - leftPair[length(leftPair)-1] + 1 = length(s) then s := s[2:length(s)-1];
|
||||
except
|
||||
end;
|
||||
|
||||
nAry[m] := trim(s);
|
||||
end;
|
||||
|
||||
t := sselect distinct trim(specialStrReplace(thisrow, 1)) from nAry where not (trim(thisrow) like "^\\d+$" or thisrow='' or thisrow like "'[\\s\\S]+'" or specialStrReplace(thisrow, 1) like "^'[\\s\\S]+'$") order by lengthW(specialStrReplace(thisrow, 1)) desc end;
|
||||
|
||||
//t := sselect distinct thisrow from nAry where not (thisrow like "^\\d+$") order by lengthW(thisrow) desc end;
|
||||
//t := array2str(t);
|
||||
return t;
|
||||
End;
|
||||
|
||||
class function IDS_AuditExpr.encryptFormulae(s);
|
||||
begin
|
||||
result := Base64Encode(tostring(s));
|
||||
return result;
|
||||
end;
|
||||
|
||||
class function IDS_AuditExpr.decryptFormulae(s);
|
||||
begin
|
||||
result := Base64Decode(tostring(s));
|
||||
return result;
|
||||
end;
|
||||
|
||||
class function IDS_AuditExpr.XBRLInsert(Formulae, FundType, Classify, isencrypt);
|
||||
Begin
|
||||
//新勾稽条目插入,接收四个参数,Formulae勾稽表达式,FundType基金类型,Classify报告类型,isencrypt是否需要加密
|
||||
|
||||
table := "XBRL_DataAuditConf";
|
||||
|
||||
eFormulae := class(IDS_AuditExpr).encryptFormulae(Formulae);
|
||||
sql := "select * from "$table$"
|
||||
where formulae in ('"$Formulae$"','"$eFormulae$"')
|
||||
and classify='"$Classify$"'";
|
||||
ids_execsql(sql, r1);
|
||||
if istable(r1) then return '该勾稽关系式已存在';
|
||||
|
||||
if isencrypt then Formulae := eFormulae;
|
||||
|
||||
sql:="INSERT INTO "$table$"
|
||||
(
|
||||
Formulae,
|
||||
FundType,
|
||||
Classify
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
"
|
||||
$ "'" $ Formulae $ "'" $ ","
|
||||
$ (FundType?("'" $ FundType $ "'"):"null") $ ","
|
||||
$ "'" $ Classify $ "'" $
|
||||
")";
|
||||
|
||||
ret1 := ids_execsql(sql,r);
|
||||
if ret1=0 then
|
||||
errorMsg := SQLErrorMsg();
|
||||
else
|
||||
return 'success';
|
||||
if errorMsg then
|
||||
return errorMsg;
|
||||
|
||||
End;
|
||||
|
||||
class function IDS_AuditExpr.specialStrReplace(str, r_type); //针对部分特殊字符进行临时转换 r_type: 0-转化为特殊串 1-转化为原字符串
|
||||
begin
|
||||
if not str then
|
||||
return '';
|
||||
arr := specialStrConf();
|
||||
StrList := array();
|
||||
SNum := 0;
|
||||
if r_type then
|
||||
begin
|
||||
StrList := sysparams["StrReplace"];
|
||||
if istable(StrList) then
|
||||
begin
|
||||
for StrNum:=length(StrList)-1 downto 0 do
|
||||
str := replaceStr(str, StrList[StrNum][1], StrList[StrNum][0]);
|
||||
end;
|
||||
for StrNum:=0 to length(arr)-1 do
|
||||
str := replaceStr(str, arr[StrNum][1], arr[StrNum][0]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
for StrNum:=0 to length(arr)-1 do
|
||||
str := replaceStr(str, arr[StrNum][0], arr[StrNum][1]);
|
||||
|
||||
ParseRegExpr("'+[^']+'+",str,"",StrArr,MPos,Mlen);
|
||||
for StrArrNum:=0 to length(StrArr)-1 do
|
||||
begin
|
||||
str := replaceStr(str, StrArr[StrArrNum][0], "@STR"$SNum$"@");
|
||||
sysparams["StrReplace"][SNum] := array(StrArr[StrArrNum][0], "@STR"$SNum$"@");
|
||||
SNum += 1;
|
||||
end;
|
||||
ParseRegExpr("[^+\\-\\*/<> =]+",str,"",result,MPos,Mlen);
|
||||
result := select * from result order by length([0]) desc end;
|
||||
for StrNum:=0 to length(result)-1 do
|
||||
begin
|
||||
if ansipos("#", result[StrNum][0]) and ansipos("getLastYear", result[StrNum][0])=0
|
||||
and ansipos("AnsiContainsText", result[StrNum][0])=0 and ansipos("TXT", result[StrNum][0])=0
|
||||
and ansipos("funcOfRowCount", result[StrNum][0])=0 and ansipos("isNull", result[StrNum][0])=0 then
|
||||
begin
|
||||
filterStr := result[StrNum][0];
|
||||
if filterStr like "^\\([\\s\\S]+\\)$" and ansipos("fundInfo", filterStr)=0 then
|
||||
filterStr := filterStr[2:length(filterStr)-1]; // 如果条件替换串的首位都是括号,则需要去掉
|
||||
str := replaceStr(str, filterStr, "@FILTER"$StrNum$"@");
|
||||
|
||||
sysparams["StrReplace"][SNum] := array(filterStr, "@FILTER"$StrNum$"@");
|
||||
SNum += 1;
|
||||
end
|
||||
end;
|
||||
end;
|
||||
return str;
|
||||
end;
|
||||
|
||||
function specialStrConf();
|
||||
begin
|
||||
return array(
|
||||
("“-”", "@SP1@"),
|
||||
("定期存款/协议存款", "@SP2@"),
|
||||
("报告期末基金资产组合情况-注", "@SP3@"),
|
||||
("资产负债表-注", "@SP4@"),
|
||||
("银行间市场债券正回购-文", "@SP5@"),
|
||||
("管理人对报告期内基金利润分配情况的说明-FA", "@SP6@"),
|
||||
("(利率风险的敏感性分析)对资产负债表日基金资产净值的影响金额", "@SP7@"),
|
||||
("积极投资前五名股票明细(指数基金)", "@SP8@"),
|
||||
("(基金中基金)报告期末按公允价值占基金资产净值比例大小排序的基金投资明细", "@SP9@"),
|
||||
("#like ", "@SP10@")
|
||||
);
|
||||
end;
|
||||
|
||||
function replace_FH(str);
|
||||
begin
|
||||
FHconf := array(
|
||||
("@横杠@", "-")
|
||||
);
|
||||
|
||||
for r_i:=0 to length(FHconf)-1 do
|
||||
begin
|
||||
if str like FHconf[r_i][0] then
|
||||
str := replaceStr(str, FHconf[r_i][0], FHconf[r_i][1]);
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
// 以下为公募勾稽构筑新增函数
|
||||
function funcOfIf(a, b, c); // if判断函数
|
||||
begin
|
||||
if eval(&a) then
|
||||
return eval(&b);
|
||||
else
|
||||
return eval(&c);
|
||||
end;
|
||||
|
||||
function funcOfRoundTo(n, p); // 精度进位函数
|
||||
begin
|
||||
return SimpleRoundTo(n, -p);
|
||||
end;
|
||||
|
||||
function funcOfRoundDown(n, p); // 精度舍位函数
|
||||
begin
|
||||
ns := tostring(n);
|
||||
if ansipos(".", ns) then
|
||||
begin
|
||||
tmp := str2array(ns, ".");
|
||||
return strtofloat(tmp[0]$"."$leftStr(tmp[1],p));
|
||||
end
|
||||
else
|
||||
return strtofloat(ns);
|
||||
end;
|
||||
|
||||
function isNull(value); // 空判断, 原函数只能处理数值类型,与系统函数重名,但只生效于勾稽公式中的变量
|
||||
begin
|
||||
if tostring(value)<>"" and not ifnil(value) then
|
||||
return 0;
|
||||
return 1;
|
||||
end;
|
||||
|
||||
function 公募基金代码(fundid);
|
||||
begin
|
||||
pinfo := sysparams["productInfo"];
|
||||
if not istable(pinfo) then
|
||||
pinfo := getProductInfoByGM();
|
||||
pinfo := select ["PRODUCTID"] from pinfo where ["PRODUCTID"]=fundid end;
|
||||
|
||||
if istable(pinfo) then
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
end;
|
||||
|
||||
function 公募基金简称(shortname);
|
||||
begin
|
||||
pinfo := sysparams["productInfo"];
|
||||
if not istable(pinfo) then
|
||||
pinfo := getProductInfoByGM();
|
||||
pinfo := select ["SHORTNAME"], ["SUB_SHORTNAME"] from pinfo where ["SUB_SHORTNAME"]=trim(shortname) or ["SHORTNAME"]=trim(shortname) end;
|
||||
if istable(pinfo) then
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
end;
|
||||
|
||||
function 公募基金全称(fullname);
|
||||
begin
|
||||
pinfo := sysparams["productInfo"];
|
||||
if not istable(pinfo) then
|
||||
pinfo := getProductInfoByGM();
|
||||
pinfo := select ["FULLNAME"] from pinfo where ["FULLNAME"]=trim(fullname) end;
|
||||
|
||||
if istable(pinfo) then
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
end;
|
||||
|
||||
function 基金存续起始日(fundid);
|
||||
begin
|
||||
pinfo := sysparams["productInfo"];
|
||||
if not istable(pinfo) then
|
||||
pinfo := getProductInfoByGM();
|
||||
pinfo := select ["EXISTENCEDATE"], ["ESTABLISHDATE"] from pinfo where ["PRODUCTID"]=fundid end;
|
||||
if istable(pinfo) then
|
||||
return pinfo[0]["EXISTENCEDATE"]?:pinfo[0]["ESTABLISHDATE"];
|
||||
else
|
||||
return 0;
|
||||
end;
|
||||
|
||||
|
||||
function getProductInfoByGM();
|
||||
begin
|
||||
sql := "select PRODUCTID, SHORTNAME, FULLNAME, SUB_SHORTNAME, MANAGER, CUSTODIAN, ESTABLISHDATE, NOTICEDATE, EXISTENCEDATE, LISTING_DATE from ts_productinfo where isvalid = 1 and (FULLNAME like '%证券投资基金' or FUNDPRODUCTTYPE = '公募基金')";
|
||||
ret := ids_execsql(sql, r);
|
||||
if not (ret and istable(r)) then
|
||||
r := array();
|
||||
sysparams["productInfo"] := r;
|
||||
return r;
|
||||
end;
|
||||
|
||||
function GetMaxValue();
|
||||
begin
|
||||
tmpParams := params;
|
||||
valArr := array();
|
||||
if istable(tmpParams) then
|
||||
begin
|
||||
for i:=0 to length(tmpParams)-1 do
|
||||
begin
|
||||
if istable(tmpParams[i]) then
|
||||
valArr &= tmpParams[i];
|
||||
else if ifstring(tmpParams[i]) or ifnumber(tmpParams[i]) then
|
||||
valArr[length(valArr)] := tmpParams[i];
|
||||
end;
|
||||
end;
|
||||
if istable(valArr) then
|
||||
v := MaxValue(valArr);
|
||||
else
|
||||
v := 0;
|
||||
return v;
|
||||
end;
|
||||
|
||||
function GetMinValue();
|
||||
begin
|
||||
tmpParams := params;
|
||||
valArr := array();
|
||||
if istable(tmpParams) then
|
||||
begin
|
||||
for i:=0 to length(tmpParams)-1 do
|
||||
begin
|
||||
if istable(tmpParams[i]) then
|
||||
valArr &= tmpParams[i];
|
||||
else if ifstring(tmpParams[i]) or ifnumber(tmpParams[i]) then
|
||||
valArr[length(valArr)] := tmpParams[i];
|
||||
end;
|
||||
end;
|
||||
if istable(valArr) then
|
||||
v := MinValue(valArr);
|
||||
else
|
||||
v := 0;
|
||||
return v;
|
||||
end;
|
||||
@@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
递归读取文件,提取 SQL 语句:
|
||||
- select/vselect/sselect ... end; (不匹配字符串中的关键字,select和end之间不能有分号)
|
||||
- update ... end; (update和end之间不能有分号)
|
||||
- delete ... ; (delete到分号)
|
||||
- insert ... ; (insert到分号)
|
||||
- 按文件分组输出
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def extract_sql_statements(content):
|
||||
"""
|
||||
从文本内容中提取 SQL 语句:
|
||||
- select/vselect/sselect ... end; (select和end之间不能有分号)
|
||||
- update ... end; (update和end之间不能有分号)
|
||||
- delete ... ; (delete到分号)
|
||||
- insert ... ; (insert到分号)
|
||||
不会匹配字符串中的关键字
|
||||
|
||||
Args:
|
||||
content: 文件内容字符串
|
||||
|
||||
Returns:
|
||||
按类型分类的SQL语句字典
|
||||
"""
|
||||
# 将所有字符串替换为占位符(保持长度不变)
|
||||
def replace_string_content(match):
|
||||
quote = match.group(0)[0]
|
||||
length = len(match.group(0))
|
||||
return quote + ' ' * (length - 2) + quote
|
||||
|
||||
# 将注释替换为空格(保持长度不变)
|
||||
def replace_comment(match):
|
||||
return ' ' * len(match.group(0))
|
||||
|
||||
# 替换单引号字符串
|
||||
content_cleaned = re.sub(r"'(?:[^'\\]|\\.)*?'", replace_string_content, content)
|
||||
# 替换双引号字符串
|
||||
content_cleaned = re.sub(r'"(?:[^"\\]|\\.)*?"', replace_string_content, content_cleaned)
|
||||
# 替换单行注释 //
|
||||
content_cleaned = re.sub(r'//.*?$', replace_comment, content_cleaned, flags=re.MULTILINE)
|
||||
# 替换多行注释 /* */
|
||||
content_cleaned = re.sub(r'/\*.*?\*/', replace_comment, content_cleaned, flags=re.DOTALL)
|
||||
|
||||
results = {
|
||||
'select': [],
|
||||
'sselect': [],
|
||||
'vselect': [],
|
||||
'update': [],
|
||||
'delete': [],
|
||||
'insert': []
|
||||
}
|
||||
|
||||
# 在清理后的内容中匹配,但从原始内容中提取
|
||||
|
||||
# 匹配 vselect ... end; (中间不能有分号)
|
||||
vselect_pattern = r'(?i)\bvselect\b(?!\s*\()[^;]*?end\s*;'
|
||||
for match in re.finditer(vselect_pattern, content_cleaned, re.DOTALL):
|
||||
original_text = content[match.start():match.end()].strip()
|
||||
results['vselect'].append(original_text)
|
||||
|
||||
# 匹配 sselect ... end; (中间不能有分号)
|
||||
sselect_pattern = r'(?i)\bsselect\b(?!\s*\()[^;]*?end\s*;'
|
||||
for match in re.finditer(sselect_pattern, content_cleaned, re.DOTALL):
|
||||
original_text = content[match.start():match.end()].strip()
|
||||
results['sselect'].append(original_text)
|
||||
|
||||
# 匹配 select ... end; (但不包括 vselect 和 sselect,中间不能有分号)
|
||||
select_pattern = r'(?i)(?<![vs])\bselect\b(?!\s*\()[^;]*?end\s*;'
|
||||
for match in re.finditer(select_pattern, content_cleaned, re.DOTALL):
|
||||
original_text = content[match.start():match.end()].strip()
|
||||
results['select'].append(original_text)
|
||||
|
||||
# 匹配 update ... end; (中间不能有分号)
|
||||
update_pattern = r'(?i)\bupdate\b(?!\s*\()[^;]*?end\s*;'
|
||||
for match in re.finditer(update_pattern, content_cleaned, re.DOTALL):
|
||||
original_text = content[match.start():match.end()].strip()
|
||||
results['update'].append(original_text)
|
||||
|
||||
# 匹配 delete ... ; (到第一个分号为止)
|
||||
delete_pattern = r'(?i)\bdelete\b(?!\s*\()(?:\s+from\b)[^;]*?;'
|
||||
for match in re.finditer(delete_pattern, content_cleaned, re.DOTALL):
|
||||
original_text = content[match.start():match.end()].strip()
|
||||
results['delete'].append(original_text)
|
||||
|
||||
# 匹配 insert ... ; (到第一个分号为止)
|
||||
insert_pattern = r'(?i)\binsert\b(?!\s*\()[^;]*?;'
|
||||
for match in re.finditer(insert_pattern, content_cleaned, re.DOTALL):
|
||||
original_text = content[match.start():match.end()].strip()
|
||||
results['insert'].append(original_text)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def read_files_recursively(directory, output_file, file_extensions=None):
|
||||
"""
|
||||
递归读取目录下的所有文件,提取SQL语句并按文件分组输出
|
||||
|
||||
Args:
|
||||
directory: 要扫描的目录路径
|
||||
output_file: 输出文件路径
|
||||
file_extensions: 要处理的文件扩展名列表,如 ['.sql', '.txt'],None表示所有文件
|
||||
"""
|
||||
# 按文件存储SQL语句
|
||||
# 结构: {file_path: {'select': [...], 'sselect': [...], 'vselect': [...]}}
|
||||
files_statements = {}
|
||||
|
||||
processed_files = 0
|
||||
error_files = []
|
||||
|
||||
# 递归遍历目录
|
||||
for root, dirs, files in os.walk(directory, followlinks=True):
|
||||
for filename in files:
|
||||
file_path = os.path.join(root, filename)
|
||||
|
||||
# 跳过输出文件本身
|
||||
if os.path.abspath(file_path) == os.path.abspath(output_file):
|
||||
continue
|
||||
|
||||
# 如果指定了文件扩展名,只处理匹配的文件
|
||||
if file_extensions:
|
||||
if not any(filename.lower().endswith(ext.lower()) for ext in file_extensions):
|
||||
continue
|
||||
|
||||
try:
|
||||
# 尝试多种编码读取文件
|
||||
encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1']
|
||||
content = None
|
||||
|
||||
for encoding in encodings:
|
||||
try:
|
||||
with open(file_path, 'r', encoding=encoding) as f:
|
||||
content = f.read()
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
|
||||
if content is None:
|
||||
print(f"警告: 无法读取文件 {file_path} (编码问题)")
|
||||
error_files.append(file_path)
|
||||
continue
|
||||
|
||||
# 提取SQL语句(按类型分类)
|
||||
matches = extract_sql_statements(content)
|
||||
|
||||
# 统计该文件中的语句数量
|
||||
total_matches = sum(len(stmts) for stmts in matches.values())
|
||||
|
||||
if total_matches > 0:
|
||||
files_statements[file_path] = matches
|
||||
print(f"✓ {file_path}: 找到 {total_matches} 条语句 "
|
||||
f"(select: {len(matches['select'])}, "
|
||||
f"sselect: {len(matches['sselect'])}, "
|
||||
f"vselect: {len(matches['vselect'])}, "
|
||||
f"update: {len(matches['update'])}, "
|
||||
f"delete: {len(matches['delete'])}, "
|
||||
f"insert: {len(matches['insert'])})")
|
||||
|
||||
processed_files += 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"错误: 处理文件 {file_path} 时出错: {str(e)}")
|
||||
error_files.append(file_path)
|
||||
|
||||
# 计算总数
|
||||
total_select = sum(len(stmts['select']) for stmts in files_statements.values())
|
||||
total_sselect = sum(len(stmts['sselect']) for stmts in files_statements.values())
|
||||
total_vselect = sum(len(stmts['vselect']) for stmts in files_statements.values())
|
||||
total_update = sum(len(stmts['update']) for stmts in files_statements.values())
|
||||
total_delete = sum(len(stmts['delete']) for stmts in files_statements.values())
|
||||
total_insert = sum(len(stmts['insert']) for stmts in files_statements.values())
|
||||
total_statements = total_select + total_sselect + total_vselect + total_update + total_delete + total_insert
|
||||
|
||||
# 写入输出文件(按文件分组输出)
|
||||
if total_statements > 0:
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(f"// 共提取到 {total_statements} 条SQL语句\n")
|
||||
f.write(f"// 处理了 {processed_files} 个文件\n")
|
||||
f.write(f"// SELECT: {total_select} 条\n")
|
||||
f.write(f"// SSELECT: {total_sselect} 条\n")
|
||||
f.write(f"// VSELECT: {total_vselect} 条\n")
|
||||
f.write(f"// UPDATE: {total_update} 条\n")
|
||||
f.write(f"// DELETE: {total_delete} 条\n")
|
||||
f.write(f"// INSERT: {total_insert} 条\n")
|
||||
f.write("//" + "=" * 80 + "\n")
|
||||
|
||||
# 按文件输出
|
||||
for file_path, statements in sorted(files_statements.items()):
|
||||
file_total = sum(len(stmts) for stmts in statements.values())
|
||||
|
||||
f.write("\n")
|
||||
f.write("//" + "=" * 80 + "\n")
|
||||
f.write(f"// 文件: {file_path}\n")
|
||||
f.write(f"// 共 {file_total} 条语句 "
|
||||
f"(SELECT: {len(statements['select'])}, "
|
||||
f"SSELECT: {len(statements['sselect'])}, "
|
||||
f"VSELECT: {len(statements['vselect'])}, "
|
||||
f"UPDATE: {len(statements['update'])}, "
|
||||
f"DELETE: {len(statements['delete'])}, "
|
||||
f"INSERT: {len(statements['insert'])})\n")
|
||||
f.write("//" + "=" * 80 + "\n")
|
||||
|
||||
# 按顺序输出:select -> sselect -> vselect -> update -> delete -> insert
|
||||
for stmt_type in ['select', 'sselect', 'vselect', 'update', 'delete', 'insert']:
|
||||
stmts = statements[stmt_type]
|
||||
|
||||
if stmts:
|
||||
for idx, stmt in enumerate(stmts, 1):
|
||||
f.write(stmt)
|
||||
f.write("\n")
|
||||
|
||||
print(f"\n✓ 成功提取 {total_statements} 条SQL语句")
|
||||
print(f" - SELECT: {total_select} 条")
|
||||
print(f" - SSELECT: {total_sselect} 条")
|
||||
print(f" - VSELECT: {total_vselect} 条")
|
||||
print(f" - UPDATE: {total_update} 条")
|
||||
print(f" - DELETE: {total_delete} 条")
|
||||
print(f" - INSERT: {total_insert} 条")
|
||||
print(f"✓ 结果已保存到: {output_file}")
|
||||
else:
|
||||
print(f"\n! 没有找到匹配的SQL语句")
|
||||
|
||||
if error_files:
|
||||
print(f"\n! 有 {len(error_files)} 个文件处理失败")
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 配置参数
|
||||
source_directory = "/mnt/c/Programs/Tinysoft/TSLGen2/funcext" # 当前目录,可以修改为你的目标目录
|
||||
output_file = "test_sql_statements.tsf"
|
||||
|
||||
# 可以指定只处理特定扩展名的文件,如 ['.sql', '.txt']
|
||||
# 设为 None 则处理所有文件
|
||||
file_extensions = ['.tsf']
|
||||
|
||||
print(f"开始扫描目录: {os.path.abspath(source_directory)}")
|
||||
print(f"输出文件: {output_file}")
|
||||
print(f"文件类型: {file_extensions if file_extensions else '所有文件'}")
|
||||
print("-" * 80)
|
||||
|
||||
# 检查目录是否存在
|
||||
if not os.path.exists(source_directory):
|
||||
print(f"错误: 目录不存在: {source_directory}")
|
||||
return
|
||||
|
||||
# 执行提取
|
||||
read_files_recursively(source_directory, output_file, file_extensions)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+2
-1
@@ -43,7 +43,8 @@ for root_dir in "${ROOT_DIRS[@]}"; do
|
||||
# 遍历当前目录下的所有 .tsf 文件
|
||||
while IFS= read -r -d '' file; do
|
||||
echo "--- 正在解析: $file"
|
||||
output=$(tree-sitter parse "$file" 2>&1)
|
||||
# output=$(tree-sitter parse "$file" 2>&1)
|
||||
output=$(tree-sitter parse "$file" 2>&1 | tr -d '\0')
|
||||
if echo "$output" | grep -q "ERROR\|MISSING"; then
|
||||
echo "❌ 语法错误在文件: $file"
|
||||
echo "$output"
|
||||
@@ -0,0 +1,12 @@
|
||||
<?tslx>
|
||||
<?tsl echo "123"; ?>
|
||||
aaaa
|
||||
<?= echo "123" ?>
|
||||
<?tsl
|
||||
|
||||
a := 1;
|
||||
|
||||
function abc();
|
||||
begin
|
||||
a := 1;
|
||||
end
|
||||
@@ -0,0 +1,606 @@
|
||||
// ============================================
|
||||
// TSF 语法单元测试
|
||||
// ============================================
|
||||
|
||||
// ============================================
|
||||
// 1. 字面量测试
|
||||
// ============================================
|
||||
|
||||
// 数字字面量
|
||||
123;
|
||||
+456;
|
||||
-789;
|
||||
123.456;
|
||||
.456;
|
||||
123.;
|
||||
123e10;
|
||||
123e-5;
|
||||
+123.456e+10;
|
||||
0xFF;
|
||||
0xABCD;
|
||||
0b1010;
|
||||
0o777;
|
||||
|
||||
// 字符串字面量
|
||||
"hello world";
|
||||
'single quote';
|
||||
"escape \n \r \t \\ \" \'";
|
||||
"unicode \u4E2D \U00004E2D";
|
||||
"hex \x41 \x42";
|
||||
L"wide string";
|
||||
L'wide char';
|
||||
|
||||
// 字符字面量
|
||||
#65;
|
||||
#$41;
|
||||
#$FF;
|
||||
|
||||
// 布尔值
|
||||
true;
|
||||
false;
|
||||
TRUE;
|
||||
FALSE;
|
||||
True;
|
||||
False;
|
||||
|
||||
// 特殊值
|
||||
nil;
|
||||
nan;
|
||||
+inf;
|
||||
-inf;
|
||||
...;
|
||||
|
||||
// ============================================
|
||||
// 2. 标识符测试
|
||||
// ============================================
|
||||
|
||||
identifier;
|
||||
_underscore;
|
||||
camelCase;
|
||||
PascalCase;
|
||||
snake_case;
|
||||
with123numbers;
|
||||
中文标识符;
|
||||
混合Chinese123标识符;
|
||||
|
||||
// ============================================
|
||||
// 3. 一元表达式测试
|
||||
// ============================================
|
||||
|
||||
// 前缀一元运算符
|
||||
+x;
|
||||
-x;
|
||||
not x;
|
||||
.!x;
|
||||
.!!x;
|
||||
##x();
|
||||
|
||||
// 表达式运算符
|
||||
@expr;
|
||||
&expr;
|
||||
|
||||
// 前缀自增自减
|
||||
++x;
|
||||
--x;
|
||||
|
||||
// 后缀自增自减
|
||||
x++;
|
||||
x--;
|
||||
|
||||
// ============================================
|
||||
// 4. 二元表达式测试
|
||||
// ============================================
|
||||
|
||||
// 算术运算
|
||||
a + b;
|
||||
a - b;
|
||||
a * b;
|
||||
a / b;
|
||||
a \ b;
|
||||
a % b;
|
||||
a mod b;
|
||||
a div b;
|
||||
|
||||
// 幂运算(右结合)
|
||||
a ^ b;
|
||||
a :^ b;
|
||||
a ^ b ^ c;
|
||||
|
||||
// 矩阵运算
|
||||
a :* b;
|
||||
a :/ b;
|
||||
a :\ b;
|
||||
a | b;
|
||||
a :| b;
|
||||
|
||||
// 位运算
|
||||
a .| b;
|
||||
a .& b;
|
||||
a .^ b;
|
||||
|
||||
// 移位运算
|
||||
a shl b;
|
||||
a shr b;
|
||||
a rol b;
|
||||
a ror b;
|
||||
|
||||
// 比较运算
|
||||
a = b;
|
||||
a .= b;
|
||||
a <> b;
|
||||
a .<> b;
|
||||
a > b;
|
||||
a .> b;
|
||||
a < b;
|
||||
a .< b;
|
||||
a >= b;
|
||||
a .>= b;
|
||||
a <= b;
|
||||
a .<= b;
|
||||
a like b;
|
||||
a in b;
|
||||
a is b;
|
||||
|
||||
// 逻辑运算
|
||||
a or b;
|
||||
a and b;
|
||||
a .|| b;
|
||||
a .&& b;
|
||||
a || b;
|
||||
a && b;
|
||||
|
||||
// 集合运算
|
||||
a union b;
|
||||
a union2 b;
|
||||
a intersect b;
|
||||
a outersect b;
|
||||
a minus b;
|
||||
|
||||
// 范围
|
||||
a -> b;
|
||||
|
||||
// 连接运算
|
||||
a $ b;
|
||||
|
||||
// 对数运算
|
||||
a ~ b;
|
||||
|
||||
// ============================================
|
||||
// 5. 三元表达式测试
|
||||
// ============================================
|
||||
|
||||
condition ? consequence : alternative;
|
||||
a > b ? a : b;
|
||||
nested ? (inner ? x : y) : z;
|
||||
condition ? : default_value;
|
||||
|
||||
// ============================================
|
||||
// 6. 赋值表达式测试
|
||||
// ============================================
|
||||
|
||||
// 基本赋值
|
||||
x := 10;
|
||||
|
||||
// 复合赋值
|
||||
x += 1;
|
||||
x -= 1;
|
||||
x *= 2;
|
||||
x /= 2;
|
||||
x \= 2;
|
||||
x ^= 2;
|
||||
x ~= 2;
|
||||
x %= 2;
|
||||
x div= 2;
|
||||
x |= 1;
|
||||
x :|= 1;
|
||||
x &= 1;
|
||||
x :*= 1;
|
||||
x :/= 1;
|
||||
x :\= 1;
|
||||
x :^= 1;
|
||||
x ::= 1;
|
||||
x .|= 1;
|
||||
x .&= 1;
|
||||
x .||= 1;
|
||||
x .&&= 1;
|
||||
x .^= 1;
|
||||
x union= set1;
|
||||
x union2= set1;
|
||||
x intersect= set1;
|
||||
x outersect= set1;
|
||||
x minus= set1;
|
||||
|
||||
// 下标赋值
|
||||
arr[0] := 10;
|
||||
matrix[i, j] := 20;
|
||||
|
||||
// 属性赋值
|
||||
obj.property := value;
|
||||
|
||||
// 解包赋值
|
||||
[a, b, c] := array(1, 2, 3);
|
||||
[x, y] := tuple;
|
||||
|
||||
// ============================================
|
||||
// 7. 数组测试(重点)
|
||||
// ============================================
|
||||
|
||||
// 空数组
|
||||
array();
|
||||
|
||||
// 简单数组
|
||||
array(1, 2, 3);
|
||||
array(1, 2, 3,);
|
||||
|
||||
// 多种类型混合
|
||||
array(1, "string", true, nil, 3.14);
|
||||
|
||||
// 键值对数组
|
||||
array(a: 1, b: 2, c: 3);
|
||||
array("key1": "value1", "key2": "value2");
|
||||
array(1: "one", 2: "two", 3: "three");
|
||||
|
||||
// 隐式数组(嵌套括号)
|
||||
array((1, 2, 3));
|
||||
array((a, b), (c, d));
|
||||
|
||||
// 键值对带隐式数组
|
||||
array(
|
||||
point1: (x, y, z),
|
||||
point2: (1, 2, 3)
|
||||
);
|
||||
|
||||
// 混合数组元素
|
||||
array(
|
||||
1,
|
||||
key: value,
|
||||
(a, b, c),
|
||||
nested: (1, 2, 3),
|
||||
"string"
|
||||
);
|
||||
|
||||
// 嵌套数组
|
||||
array(
|
||||
array(1, 2, 3),
|
||||
array(4, 5, 6),
|
||||
array(7, 8, 9)
|
||||
);
|
||||
|
||||
// 多层嵌套
|
||||
array(
|
||||
array(
|
||||
array(1, 2),
|
||||
array(3, 4)
|
||||
),
|
||||
array(
|
||||
array(5, 6),
|
||||
array(7, 8)
|
||||
)
|
||||
);
|
||||
|
||||
// 复杂键值对嵌套
|
||||
array(
|
||||
matrix: array(
|
||||
row1: array(1, 2, 3),
|
||||
row2: array(4, 5, 6)
|
||||
),
|
||||
vector: array(x: 1, y: 2, z: 3),
|
||||
nested: (
|
||||
(1, 2),
|
||||
(3, 4)
|
||||
)
|
||||
);
|
||||
|
||||
// 数组带表达式
|
||||
array(1 + 2, 3 * 4, 5 ^ 6);
|
||||
array(func(), obj.method(), arr[0]);
|
||||
|
||||
// 数组带条件表达式
|
||||
array(
|
||||
a > b ? a : b,
|
||||
condition ? x : y
|
||||
);
|
||||
|
||||
|
||||
// 尾随逗号测试
|
||||
array(1, 2, 3,);
|
||||
array(a: 1, b: 2,);
|
||||
array((1, 2, 3,));
|
||||
|
||||
// ============================================
|
||||
// 8. 下标访问测试
|
||||
// ============================================
|
||||
|
||||
// 基本下标
|
||||
arr[0];
|
||||
arr[i];
|
||||
matrix[x, y];
|
||||
|
||||
// 切片
|
||||
arr[:];
|
||||
arr[1:];
|
||||
arr[:10];
|
||||
arr[1:10];
|
||||
|
||||
// 矩阵切片
|
||||
matrix[:, :];
|
||||
matrix[1:5, 2:8];
|
||||
matrix[:, 0];
|
||||
matrix[0, :];
|
||||
matrix[1:, :5];
|
||||
|
||||
// 多维切片
|
||||
tensor[1:5, 2:8, 3:9];
|
||||
tensor[:, :, 0];
|
||||
|
||||
// 嵌套下标
|
||||
arr[0][1];
|
||||
matrix[i][j];
|
||||
arr[func()][obj.attr];
|
||||
|
||||
// ============================================
|
||||
// 9. 属性访问测试
|
||||
// ============================================
|
||||
|
||||
obj.property;
|
||||
obj.method;
|
||||
nested.obj.property;
|
||||
arr[0].attribute;
|
||||
func().result;
|
||||
(expr).attr;
|
||||
|
||||
// ============================================
|
||||
// 9.5. 链式调用测试(属性和方法混合)
|
||||
// ============================================
|
||||
|
||||
// 方法后访问属性
|
||||
obj.method().property;
|
||||
func().result.value;
|
||||
|
||||
// 属性后调用方法
|
||||
obj.property.method();
|
||||
data.field.toString();
|
||||
|
||||
// 混合链式调用
|
||||
obj.Abc().def.FGH();
|
||||
obj.method1().property.method2();
|
||||
obj.a().b().c().d();
|
||||
obj.a.b().c.d();
|
||||
|
||||
// 复杂链式
|
||||
obj.getData().results[0].format();
|
||||
obj.query().filter().map().reduce();
|
||||
api.connect().auth().request().parse();
|
||||
|
||||
// 链式调用带参数
|
||||
obj.method(arg).property.next(param);
|
||||
builder.setX(1).setY(2).setZ(3).build();
|
||||
|
||||
// 链式调用带下标
|
||||
obj.method()[0].property;
|
||||
arr.filter()[0].name;
|
||||
data.get("key").items[0].process();
|
||||
|
||||
// 超长链式
|
||||
obj.a.b.c.d.e.f.g.h.i.j.k();
|
||||
func1().func2().func3().func4().func5();
|
||||
|
||||
// 混合运算符的链式
|
||||
obj.fetch().result := value;
|
||||
|
||||
// 链式调用在表达式中
|
||||
obj.calculate().result + other.getValue().data;
|
||||
arr.first().value * matrix.last().coefficient;
|
||||
|
||||
// ============================================
|
||||
// 10. 函数调用测试
|
||||
// ============================================
|
||||
|
||||
// 无参数调用
|
||||
func();
|
||||
|
||||
// 单参数
|
||||
func(arg);
|
||||
|
||||
// 多参数
|
||||
func(a, b, c);
|
||||
|
||||
// 命名参数
|
||||
func(name: value);
|
||||
func(x: 1, y: 2, z: 3);
|
||||
|
||||
// 混合参数
|
||||
func(1, 2, name: value, 3, key: data);
|
||||
|
||||
// const 参数
|
||||
func(const arg);
|
||||
func(const x, const y);
|
||||
|
||||
// 星号参数
|
||||
// func(*);
|
||||
// func(a, *, b);
|
||||
|
||||
// 嵌套调用
|
||||
func1(func2(func3()));
|
||||
|
||||
// 链式调用
|
||||
obj.method1().method2().method3();
|
||||
|
||||
// ============================================
|
||||
// 11. 括号表达式测试
|
||||
// ============================================
|
||||
|
||||
(expr);
|
||||
((nested));
|
||||
(a + b) * (c + d);
|
||||
(condition ? x : y);
|
||||
|
||||
// ============================================
|
||||
// 12. 内置表达式测试
|
||||
// ============================================
|
||||
|
||||
// new 表达式
|
||||
new ClassName;
|
||||
new MyClass();
|
||||
|
||||
// echo 表达式
|
||||
echo "message";
|
||||
echo x, y, z;
|
||||
echo "value:", value, "result:", result;
|
||||
|
||||
// raise 表达式
|
||||
raise Exception;
|
||||
raise CustomError("message");
|
||||
|
||||
// inherited 表达式
|
||||
inherited;
|
||||
inherited method();
|
||||
inherited ParentClass.method();
|
||||
|
||||
// ============================================
|
||||
// 13. 复杂组合测试
|
||||
// ============================================
|
||||
|
||||
// 运算符优先级混合
|
||||
a + b * c;
|
||||
(a + b) * c;
|
||||
a ^ b * c;
|
||||
a + b ^ c;
|
||||
a and b or c;
|
||||
(a and b) or c;
|
||||
|
||||
// 链式运算
|
||||
a.b.c.d;
|
||||
arr[0][1][2];
|
||||
obj.method().property[0];
|
||||
|
||||
// 复杂赋值
|
||||
obj.arr[i].prop := value;
|
||||
matrix[x, y] += delta;
|
||||
obj.counter++;
|
||||
|
||||
// 复杂数组初始化
|
||||
array(
|
||||
id: 1,
|
||||
name: "test",
|
||||
values: array(1, 2, 3),
|
||||
matrix: array(
|
||||
array(1, 2),
|
||||
array(3, 4)
|
||||
),
|
||||
computed: func(),
|
||||
conditional: x > 0 ? pos : neg,
|
||||
nested: (
|
||||
(a, b),
|
||||
(c, d)
|
||||
)
|
||||
);
|
||||
|
||||
// 复杂表达式
|
||||
((a + b) * c - d) / (e ^ f);
|
||||
func(x: a + b, y: c * d, z: array(1, 2, 3));
|
||||
obj.method(arr[0], key: value).property++;
|
||||
|
||||
// 多层嵌套结构
|
||||
array(
|
||||
level1: array(
|
||||
level2: array(
|
||||
level3: array(
|
||||
data: (1, 2, 3)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// ============================================
|
||||
// 14. 边界情况测试
|
||||
// ============================================
|
||||
|
||||
// 空切片
|
||||
arr[];
|
||||
|
||||
// 单元素数组
|
||||
array(1);
|
||||
array(1,);
|
||||
|
||||
// 单键值对
|
||||
array(key: value);
|
||||
|
||||
// 空隐式数组(语法上可能无效,但测试边界)
|
||||
array(());
|
||||
|
||||
// 连续运算符
|
||||
a+-b;
|
||||
a-+b;
|
||||
|
||||
// 长标识符链
|
||||
very.long.chain.of.attributes.and.calls().more[0].data;
|
||||
|
||||
// 深层嵌套表达式
|
||||
((((((expr))))));
|
||||
|
||||
// 多行数组格式
|
||||
array(
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
);
|
||||
|
||||
// ============================================
|
||||
// 15. 解包模式测试
|
||||
// ============================================
|
||||
|
||||
[a] := array(1);
|
||||
[a, b] := array(1, 2);
|
||||
[x, y, z] := tuple;
|
||||
[first, second, third] := values;
|
||||
|
||||
// ============================================
|
||||
// 16. 组合运算测试
|
||||
// ============================================
|
||||
|
||||
// 矩阵和标量混合
|
||||
matrix :* scalar + vector;
|
||||
(matrix :| vector) :^ 2;
|
||||
|
||||
// 位运算和逻辑运算
|
||||
(a .& b) .|| (c .^ d);
|
||||
a and (b .| c);
|
||||
|
||||
// 集合运算链
|
||||
set1 union set2 intersect set3;
|
||||
(set1 union set2) minus set3;
|
||||
|
||||
// 范围和运算
|
||||
(1 -> 10) union (20 -> 30);
|
||||
array(0 -> 9);
|
||||
|
||||
// 字符串连接
|
||||
"hello" $ " " $ "world";
|
||||
str1 $ str2 $ str3;
|
||||
|
||||
// ============================================
|
||||
// 17. 特殊语法组合
|
||||
// ============================================
|
||||
|
||||
// 三元嵌套
|
||||
a ? b ? c : d : e ? f : g;
|
||||
|
||||
// 赋值链(如果支持)
|
||||
a := b := c := 0;
|
||||
|
||||
// 调用后自增
|
||||
arr[0]++;
|
||||
|
||||
// 属性链式赋值
|
||||
obj.a.b.c := value;
|
||||
|
||||
// 复杂下标表达式
|
||||
arr[i + 1][j * 2];
|
||||
matrix[func(x), obj.y];
|
||||
|
||||
// // ============================================
|
||||
// // 测试完成
|
||||
// // ============================================
|
||||
@@ -0,0 +1,87 @@
|
||||
class(test).test1(); // 允许这样调用class function
|
||||
// class(); // 不允许这么调用函数
|
||||
// in();
|
||||
// do();
|
||||
// select();
|
||||
// sselect();
|
||||
// vselect();
|
||||
// update();
|
||||
// delete();
|
||||
// insert();
|
||||
type(); // 仅有type允许函数调用
|
||||
|
||||
// var global static const
|
||||
var type := 1; // 仅var允许
|
||||
// global type: string := "123";
|
||||
// static type: integer := 123;
|
||||
// const type = 123;
|
||||
|
||||
// 赋值
|
||||
type := 1; // 允许左值,也要允许右值
|
||||
// class := 1; // 不允许
|
||||
// do := 1; // 不允许
|
||||
// select := 1; // 不允许
|
||||
// sselect := 1; // 不允许
|
||||
// vselect := 1; // 不允许
|
||||
// update := 1; // 不允许
|
||||
// delete := 1; // 不允许
|
||||
// insert := 1; // 不允许
|
||||
// in := 1; // 不允许
|
||||
|
||||
// 对象调用 除了class都允许
|
||||
o := new test();
|
||||
o.In();
|
||||
o.type();
|
||||
o.Do();
|
||||
o.Select();
|
||||
o.SSelect();
|
||||
o.VSelect();
|
||||
o.Delete();
|
||||
o.Update();
|
||||
o.Insert();
|
||||
|
||||
// function class(); // 不允许函数名
|
||||
// begin
|
||||
// end;
|
||||
// function In(); // 不允许
|
||||
// begin
|
||||
// end;
|
||||
// function Do();
|
||||
// begin
|
||||
// end;
|
||||
// function Select();
|
||||
// begin
|
||||
// end;
|
||||
// function SSelect();
|
||||
// begin
|
||||
// end;
|
||||
// function VSelect();
|
||||
// begin
|
||||
// end;
|
||||
// function Delete();
|
||||
// begin
|
||||
// end;
|
||||
// function Update();
|
||||
// begin
|
||||
// end;
|
||||
// function Insert();
|
||||
// begin
|
||||
// end;
|
||||
function type();
|
||||
begin
|
||||
end;
|
||||
|
||||
type test = class
|
||||
class function test1();
|
||||
|
||||
// function class(); //不允许
|
||||
function In();
|
||||
function type();
|
||||
function Do();
|
||||
function Select();
|
||||
function SSelect();
|
||||
function VSelect();
|
||||
function Delete();
|
||||
function Update();
|
||||
function Insert();
|
||||
end;
|
||||
@@ -0,0 +1,15 @@
|
||||
function(arr, i);
|
||||
begin
|
||||
end
|
||||
function(arr, i);
|
||||
begin
|
||||
echo "123";
|
||||
end;
|
||||
pf := function(arr, i);
|
||||
begin
|
||||
echo "123";
|
||||
end
|
||||
pf := function(arr, i);
|
||||
begin
|
||||
echo "123";
|
||||
end;;
|
||||
@@ -0,0 +1,242 @@
|
||||
// 共提取到 127 条SQL语句
|
||||
// 处理了 115 个文件
|
||||
// SELECT: 64 条
|
||||
// SSELECT: 23 条
|
||||
// VSELECT: 11 条
|
||||
// UPDATE: 24 条
|
||||
// DELETE: 3 条
|
||||
// INSERT: 2 条
|
||||
//================================================================================
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/OfficeXml-dev/funcext/OfficeXml/docx/vba/DocxVba.tsf
|
||||
// 共 1 条语句 (SELECT: 0, SSELECT: 1, VSELECT: 0, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
sselect ['FileName'] from zip.Files() where AnsiStartsText('word/media/image', ['FileName']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/OfficeXml-dev/generator/CreateAdapter.tsf
|
||||
// 共 3 条语句 (SELECT: 2, SSELECT: 0, VSELECT: 0, UPDATE: 1, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select * from children where not ifnil(['adapter_key']) end;
|
||||
select * from children where not ifnil(['adapter_child_key']) end;
|
||||
update children set ['adapter_key'] = array(['adapter_key']) where ifString(['adapter_key']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/OfficeXml-dev/generator/CreateDecorator.tsf
|
||||
// 共 6 条语句 (SELECT: 1, SSELECT: 1, VSELECT: 0, UPDATE: 4, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select ['field'], select * from thisgroup end as 'detail' from children group by ['field'] having countof(['field']) > 1 end;
|
||||
sselect["field"] from ml_children end;
|
||||
update attrs set ['new_field'] = format('XmlAttr%s', ['field']) end;
|
||||
update children set ['origin_field'] = ['field'] end;
|
||||
update children set ['field'] = uppercase(['prefix']) + ['field'] where not ifnil(['ml']) and ['field'] in fields end;
|
||||
update children set ['new_field'] = format('XmlChild%s', ['field']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/OfficeXml-dev/generator/CreateTslUnit.tsf
|
||||
// 共 16 条语句 (SELECT: 5, SSELECT: 3, VSELECT: 0, UPDATE: 8, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select ['field'], select * from thisgroup end as 'detail' from attrs group by ['field'] having countof(['field']) > 1 end;
|
||||
select ['field'], select * from thisgroup end as 'detail' from children group by ['field'] having countof(['field']) > 1 end;
|
||||
select ['origin_field'], select * from thisgroup end as 'detail' from attrs group by ['origin_field'] having countof(['origin_field']) > 1 end;
|
||||
select ['origin_field'], select * from thisgroup end as 'detail' from children group by ['origin_field'] having countof(['origin_field']) > 1 end;
|
||||
select * from children where ['multi'] <> 1 end;
|
||||
sselect ['ml'] from children where ifString(['ml']) end;
|
||||
sselect ['field'] from mu_attrs end;
|
||||
sselect ['field'] from mu_children end;
|
||||
update attrs set ['origin_field'] = ['field'] end;
|
||||
update attrs set ['field'] = uppercase(['prefix']) + ['field'] where ifstring(['prefix']) and ['field'] in fields end;
|
||||
update attrs set ['field'] = ['field'] + 'N' where ifnil(['prefix']) and ['field'] in fields end;
|
||||
update attrs set ['new_field'] = format('XmlAttr%s', ['field']) end;
|
||||
update children set ['origin_field'] = ['field'] end;
|
||||
update children set ['field'] = uppercase(['prefix']) + ['field'] where ifstring(['prefix']) and ['field'] in fields end;
|
||||
update children set ['field'] = ['field'] + 'N' where ifnil(['prefix']) and ['field'] in fields end;
|
||||
update children set ['new_field'] = format('XmlChild%s', ['field']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/TSOffice/funcext/TSOffice/TOfficeObj.tsf
|
||||
// 共 10 条语句 (SELECT: 3, SSELECT: 5, VSELECT: 1, UPDATE: 1, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select thisrowindex as 'Index' from commentsArray_ where ['ID'] = id end;
|
||||
select * from commentsArray_ where thisrowindex <= r[1]['Index'] and thisrowindex >= r[0]['Index'] end;
|
||||
select * from Tabs where thisrowindex <> ind end;
|
||||
sselect distinct ['ID'] from commentsArray_ where ['ID'] >= 0 end;
|
||||
sselect ['obj'] from Tabs end;
|
||||
sselect ['FileName'] from zipfile.Files() where AnsiStartsText('word/media/image', ['FileName']) end;
|
||||
sselect ['FileName'] from zipfile_.Files() where AnsiStartsText('word/media/image', ['FileName']) end;
|
||||
sselect ['FileName'] from zipfile_.Files() where AnsiStartsText('word/' $ headerFooter, ['FileName']) end;
|
||||
vselect countof( ['FileName'] ) from docx.Zip().Files() where AnsiStartsText('word/embeddings/Workbook', ['FileName']) end;
|
||||
update pArr set ['pIndex'] = i end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/TSOffice/funcext/TSOffice/TSDocxFile.tsf
|
||||
// 共 1 条语句 (SELECT: 0, SSELECT: 0, VSELECT: 1, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
vselect thisrowindex from files where ['FileName']=file end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/TSOffice/funcext/TSOffice/TSUtils/NodeInfo.tsf
|
||||
// 共 4 条语句 (SELECT: 2, SSELECT: 2, VSELECT: 0, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select * from children where lName = lowerCase(['field']) end;
|
||||
select * from children where lName = lowerCase(['field']) end;
|
||||
sselect * from attrs where lName = lowerCase([0]) end;
|
||||
sselect * from attrs where lName = lowerCase([0]) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/TSOffice/funcext/TSOffice/document/TDocxChart.tsf
|
||||
// 共 1 条语句 (SELECT: 0, SSELECT: 0, VSELECT: 1, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
vselect countof( ['FileName'] ) from docx.Zip().Files() where AnsiStartsText('word/charts/chart', ['FileName']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/TSOffice/funcext/TSOffice/document/TDocxCopy.tsf
|
||||
// 共 3 条语句 (SELECT: 0, SSELECT: 3, VSELECT: 0, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
sselect ['FileName'] from zip.Files() where AnsiStartsText('word/' $ tar_prefix, ['FileName']) end;
|
||||
sselect ['FileName'] from zip.Files() where AnsiStartsText('word/media/image', ['FileName']) end;
|
||||
sselect ['FileName'] from zip.Files() where AnsiStartsText('word/charts/chart', ['FileName']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/TSOffice/funcext/TSOffice/worksheet/xlsxImage.tsf
|
||||
// 共 1 条语句 (SELECT: 0, SSELECT: 1, VSELECT: 0, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
sselect ['FileName'] from zipfile_.Files() where AnsiStartsText('xl/media/image', ['FileName']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/TSOffice/funcext/TSOffice/worksheet/xlsxWorkBook.tsf
|
||||
// 共 6 条语句 (SELECT: 1, SSELECT: 2, VSELECT: 3, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select * from sheetNames_ where thisrowindex <> ind end;
|
||||
sselect ['FileName'] from files where AnsiContainsStr(['FileName'], 'tables/table') end;
|
||||
sselect ['name'] from sheetNames_ end;
|
||||
vselect maxof(['sheetId']) from sheetNames_ end;
|
||||
vselect thisrowindex from files where ['FileName'] = oldname end;
|
||||
vselect maxof(['sheetId']) from sheetNames_ end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/other/TS_Excel.tsf
|
||||
// 共 1 条语句 (SELECT: 0, SSELECT: 1, VSELECT: 0, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
sselect length(str2array(thisrow, "@"))-1 from arr order by length(str2array(thisrow, "@")) desc end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/other/sysconfdb.tsf
|
||||
// 共 17 条语句 (SELECT: 12, SSELECT: 1, VSELECT: 0, UPDATE: 2, DELETE: 1, INSERT: 1)
|
||||
//================================================================================
|
||||
select ['TSID'],['CID'],['CNAME'],['KEY_NAME'] FROM sqltable 'ts_sys_config' of GetDBAlias() where ["PID"] = arr['pid'] and (['CNAME'] = arr['cname'] or ['KEY_NAME'] = arr['key_name']) end;
|
||||
select ['cid'],['pid'],['cname'],['c_type'],['key_name'],['c_remarks'],['created_name'],['created_time'],setEncodeRSA(['c_type'], ['value_s']) AS 'value_s',['value_list'] from arr end;
|
||||
select * from data where ['PID'] = '0' AND ['KEY_NAME'] = RootKey END;
|
||||
Select * from data where ['PID'] = d1[0]['CID'] END;
|
||||
Select * from d2 where ['KEY_NAME'] = NodeKeyArr[i] END;
|
||||
select * from data where ['PID'] = '0' AND ['KEY_NAME'] = RootKey END;
|
||||
Select * from data where ['PID'] = d1[0]['CID'] END;
|
||||
Select * from d2 where ['KEY_NAME'] = NodeKeyArr[i] END;
|
||||
select * from data where ['CID'] = cid end;
|
||||
select * from data where ['PID'] = cid end;
|
||||
select ['CNAME'] as "配置名称",
|
||||
['KEY_NAME'] as "配置KEY",
|
||||
GetConfigurationKey(['C_TYPE'],['VALUE_S'],['VALUE_LIST']) as "配置值",
|
||||
['C_TYPE'] as "配置类型",
|
||||
['C_REMARKS'] as "备注",
|
||||
GetConfigurationValueList(['C_TYPE'],['VALUE_LIST']) as "配置可选值" from data where ['CID'] = cid end;
|
||||
select * from data where ['PID'] = cid end;
|
||||
sselect ['VALUE'] from d2 where ['KEY'] in t1 end;
|
||||
Update sqltable 'ts_sys_config' of GetDBAlias() set ['PID'] = arr['pid'],
|
||||
['CNAME'] = arr['cname'],
|
||||
['KEY_NAME'] = arr['key_name'],
|
||||
['VALUE_S'] = arr['value_s'],
|
||||
['C_TYPE'] = arr['c_type'],
|
||||
['C_REMARKS'] = arr['c_remarks'],
|
||||
['UPDATED_BY'] = arr['updated_by'],
|
||||
['VALUE_LIST'] = arr['value_list'],
|
||||
['UPDATED_TIME'] = arr['updated_time'] where ['CID'] = arr['cid'] end;
|
||||
Update sqltable 'ts_sys_config' of GetDBAlias() set ['VALUE_S'] = arr['value_s'],
|
||||
['UPDATED_BY'] = arr['updated_by'],
|
||||
['UPDATED_TIME'] = arr['updated_time'] where ['CID'] = arr['cid'] end;
|
||||
DELETE FROM sqltable 'SELECT * FROM ts_sys_config' of GetDBAlias() where ["CID"] IN arr ;
|
||||
Insert INTO sqltable 'ts_sys_config' of GetDBAlias() arr;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/other/tgenreport.tsf
|
||||
// 共 21 条语句 (SELECT: 10, SSELECT: 2, VSELECT: 3, UPDATE: 6, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select * from t order by ["名称"] end;
|
||||
select * from r where not (['did'] in (sselect ['ID'] from existsDidArr end)) end;
|
||||
select * from preData where ['EID']= r[i]['EID'] end;
|
||||
select * from preData where ['EID']= r[i]['EID'] end;
|
||||
select * from wordConf where ['Value']=reportInfo['TType'] end;
|
||||
select [xName] from data end;
|
||||
select * from xData join data on [1].[xName] = [2].[xName] end;
|
||||
select [1],[3] from mgConf where [1]=num_row and [1]<>[3] and ([1]= num_colunm or [3]= num_colunm) end;
|
||||
select ['doc_order_no'],trim(['org_content']) as 'org_content' from reportData where ['type'] = 'title' end;
|
||||
select * from fzhTable where ['doc_order_no'] like '^'$ZXCWBB end;
|
||||
select * from r where not (['did'] in (sselect ['ID'] from existsDidArr end)) end;
|
||||
sselect distinct ['DATA_ID'] from EArr where ['type']='pdf' end;
|
||||
vselect ['PRE_DATA'] from rpt_latestData where ['EID']= EArr[j]['EID'] and ['PRE_TYPE']= EArr[j]['type'] end;
|
||||
vselect countof( * ) from fuZhuHaoTable where ['org_content'] like '转型前' end;
|
||||
vselect ['doc_order_no'] from fzhTable where ['org_content'] = title end;
|
||||
update r set ['did']= GenDataId(['EID'],productionID,pubDate,init_begindate,classify) end;
|
||||
update r set ['DATASOURCE']= class(Element).dataSource_autoInherit() where not (['EID'] in array('20150512171332212_95089541912828646461640993495')) end;
|
||||
update r set ['DATA_INIT_STATE']= 4 where not (['EID'] in array('20150512171332212_95089541912828646461640993495','20150304151252139_31808466412173073041697290538')) end;
|
||||
update EArr set ['content'] = ['doc_order_no']$' '$['content'] where ['doc_order_no'] and pos('、',['doc_order_no'])=0 end;
|
||||
update EArr set ['content'] = ['doc_order_no']$['content'] where ['doc_order_no'] and pos('、',['doc_order_no'])<>0 end;
|
||||
update reportConf set ['content'] = updateFuZhuHaoSub(fuzhuhaoHash,['content']) ,['Data'] = updateFuZhuHaoSub(fuzhuhaoHash,['Data'])
|
||||
where ['ename'] in array('资产负债表','利润表') and istable(['Data']) end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/tsword/ts_word.tsf
|
||||
// 共 1 条语句 (SELECT: 0, SSELECT: 1, VSELECT: 0, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
sselect thisrow from rules where thisrow <> "" end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/tsword/tsword_report.tsf
|
||||
// 共 2 条语句 (SELECT: 1, SSELECT: 0, VSELECT: 0, UPDATE: 1, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select [1],[3] from mgConf where [1]=num_row and [1]<>[3] and ([1]= num_colunm or [3]= num_colunm) end;
|
||||
update cellAlignConf set ["horizAlign"] = "left" end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/word2arr/helpdoctools.tsf
|
||||
// 共 29 条语句 (SELECT: 27, SSELECT: 0, VSELECT: 2, UPDATE: 0, DELETE: 0, INSERT: 0)
|
||||
//================================================================================
|
||||
select ["node_id"],["parent_id"],["node_name"],"sys" as "created_by","sys" as "updated_by",["node_order"],["node_type"],["bus_key"],1 as "is_valid" from data end;
|
||||
select ["node_id"],(["content"] + ".md") as "content","sys" as "created_by",["describe"] from data where ["describe"] <> "" and ["describe"] <> nil end;
|
||||
select ["node_id"],["content"],["created_by"] from tmp_contentdata end;
|
||||
select ["node_id"],["title"] from data where ["node_id"] = id end;
|
||||
select ["node_id"],["title"] from data where ["node_id"] = id or ["title"] = name end;
|
||||
select ["node_id"], ["parent_id"], ["node_order"], ["node_type"], ["bus_key"], ["node_name"] AS "title" from MenuData ORDER BY ["node_order"] end;
|
||||
select * from MenuData where ["node_id"] = id end;
|
||||
select ["node_id"], ["parent_id"], ["node_order"], ["node_type"], ["bus_key"], ["node_name"] AS "title" from MenuData ORDER BY ["node_order"] end;
|
||||
select * from MenuData where ["node_id"] = id end;
|
||||
select ["node_id"] AS "value", ["parent_id"], ["node_name"] AS "label", ["node_order"] from MenuData end;
|
||||
select ["value"], ["label"] from MenuData where ["parent_id"] = id end;
|
||||
select ["node_id"], ["parent_id"], ["node_order"], ["node_type"], ["bus_key"], ["node_name"] AS "title" from MenuData ORDER BY ["node_order"] end;
|
||||
select *, 1 as "expand" from MenuData where ["parent_id"] = id end;
|
||||
select * from MenuData where ["parent_id"] = nodeData[i]["value"] ORDER BY ["node_order"] end;
|
||||
select * from MenuData where ["parent_id"] = nodeData[i]["node_id"] ORDER BY ["node_order"] end;
|
||||
select * from MenuData where ["parent_id"] = nodeData[i]["node_id"] ORDER BY ["node_order"] end;
|
||||
select ["node_id"], ["parent_id"], ["node_name"] AS "title" from MenuData where ["node_id"] = id end;
|
||||
select ["node_id"], ["parent_id"], ["node_name"] AS "title", ["bus_key"] from MenuData where ["parent_id"] = id end;
|
||||
select ["node_id"],["node_name"] AS "title" from res["data"] end;
|
||||
select ["node_id"], (["node_order"] + 1) AS "node_order" from MenuList where ["node_order"] >= index ORDER BY ["node_order"] end;
|
||||
select ["node_id"] from oldMenuData where ["parent_id"] = pid end;
|
||||
select ["node_id"] from oldMenuData where ["parent_id"] = pid and ["title"] = newMenuData[i]["title"] and IsEmpty(["bus_key"]) end;
|
||||
select ["node_id"], ["parent_id"], ["node_order"], ["node_type"], ["bus_key"], ["node_name"] AS "title" from res["data"] ORDER BY ["node_order"] end;
|
||||
select ["node_id"], ["parent_id"], ["title"] from MenuData where ["node_id"] = nodeId end;
|
||||
select ["node_id"], ["parent_id"], ["node_order"] from MenuData where ["parent_id"] = nodeData[0]["node_id"] ORDER BY ["node_order"] end;
|
||||
select ["node_id"],["node_name"] AS "title" from res["data"] end;
|
||||
select ["parent_id"],["node_id"],["node_order"] from res["data"] where ["node_id"] <> param["bid"] end;
|
||||
vselect ["content"] from menuList where ["node_id"] = pid end;
|
||||
vselect ["node_order"] from res["data"] ORDER BY ["node_order"] desc end;
|
||||
|
||||
//================================================================================
|
||||
// 文件: /mnt/c/Programs/Tinysoft/TSLGen2/funcext/word2arr/sethelptreedocdb.tsf
|
||||
// 共 4 条语句 (SELECT: 0, SSELECT: 0, VSELECT: 0, UPDATE: 1, DELETE: 2, INSERT: 1)
|
||||
//================================================================================
|
||||
update sqltable "ts_helpDocMenu" of FDBAlias set ["is_valid"] = 0 where ["node_id"] in data end;
|
||||
delete from sqltable "ts_helpDocContent" of FDBAlias where ["node_id"] in data;
|
||||
delete from sqltable "ts_helpDocMenu" of FDBAlias where ["node_id"] in data;
|
||||
insert into sqltable tableName of FDBAlias data[i:i+999-1];
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -3,11 +3,11 @@
|
||||
echo "=== TSF 基础语法验证 ==="
|
||||
|
||||
echo "步骤1: 生成解析器"
|
||||
tree-sitter generate
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ 生成解析器失败"
|
||||
exit 1
|
||||
fi
|
||||
# tree-sitter generate
|
||||
# if [ $? -ne 0 ]; then
|
||||
# echo "❌ 生成解析器失败"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
echo -e "\n步骤2: 测试最简单的完整结构"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?tslx>
|
||||
aa<?=ids_version()?>"
|
||||
src='js?v=<?=ids_version()?>'
|
||||
style="display: none;">
|
||||
@@ -0,0 +1,201 @@
|
||||
// TSF 变量声明测试代码示例
|
||||
// 用于测试 var, static, global, const 语法
|
||||
|
||||
//================================================================================
|
||||
// 1. var 声明测试
|
||||
//================================================================================
|
||||
// 保留关键字
|
||||
do := 13;
|
||||
type := "1234";
|
||||
in := f2();
|
||||
class := defff;
|
||||
delete := +inf;
|
||||
|
||||
// 基本声明
|
||||
var simple;
|
||||
var withType: integer;
|
||||
var withInit := 42;
|
||||
var complete: real := 3.14;
|
||||
|
||||
// 多变量声明
|
||||
var a, b, c;
|
||||
var x, y, z: integer;
|
||||
var m, n := 100;
|
||||
var p, q, r: string := "default";
|
||||
|
||||
// 数组类型
|
||||
var intArray: array of integer;
|
||||
var stringArray: array of string := null;
|
||||
var matrix: array of real;
|
||||
var tensor: array of float;
|
||||
|
||||
// 复杂类型名
|
||||
var list: System.Collections.List;
|
||||
var dict: System.Collections.Generic.Dictionary_string_int;
|
||||
var custom: MyNamespace.MyClass.NestedType;
|
||||
|
||||
// 复杂初始化器
|
||||
var fromFunc := getValue();
|
||||
var fromExpr := (a + b) * c;
|
||||
var fromArray := array(1, 2, 3, 4, 5);
|
||||
var fromCall := createObject("param1", 123, true);
|
||||
|
||||
//================================================================================
|
||||
// 2. static 声明测试
|
||||
//================================================================================
|
||||
|
||||
// 基本声明
|
||||
static counter;
|
||||
static typed: integer;
|
||||
static initialized := 0;
|
||||
static full: string := "static";
|
||||
|
||||
// 多变量声明
|
||||
static s1, s2, s3;
|
||||
static sx, sy: real;
|
||||
static sa, sb := 999;
|
||||
static sp, sq, sr: boolean := false;
|
||||
|
||||
// 静态数组
|
||||
static cache: array of object;
|
||||
static buffer: array of byte := null;
|
||||
static lookupTable: array of integer := createTable();
|
||||
|
||||
// 复杂类型和初始化
|
||||
static singleton: MyClass := MyClass.getInstance();
|
||||
static config: dictionary := loadConfig("app.config");
|
||||
static handler: EventHandler := lambda(e) { handleEvent(e); };
|
||||
|
||||
//================================================================================
|
||||
// 3. global 声明测试
|
||||
//================================================================================
|
||||
|
||||
// 基本声明
|
||||
global appConfig;
|
||||
global settings: object;
|
||||
global database := null;
|
||||
global connection: DBConnection := connect();
|
||||
|
||||
// 多变量声明
|
||||
global g1, g2;
|
||||
global gx, gy, gz: any;
|
||||
global ga, gb := "global";
|
||||
global gp, gq: integer := 0;
|
||||
|
||||
// 全局数组和集合
|
||||
global users: array of User;
|
||||
global cache: dictionary := createDictionary();
|
||||
global eventQueue: array of Event := array();
|
||||
|
||||
// 复杂全局变量
|
||||
global logger: ILogger := createLogger("app.log");
|
||||
global threadPool: ThreadPool := ThreadPool(4);
|
||||
global serviceLocator: ServiceLocator := ServiceLocator.default;
|
||||
|
||||
//================================================================================
|
||||
// 4. const 声明测试
|
||||
//================================================================================
|
||||
|
||||
// 数值常量
|
||||
const PI = 3.14159265359;
|
||||
const E = 2.71828;
|
||||
const MAX_INT: integer = 2147483647;
|
||||
const MIN_INT: integer = -2147483648;
|
||||
|
||||
// 字符串常量
|
||||
const VERSION = "1.0.0";
|
||||
const APP_NAME: string = "MyApplication";
|
||||
const PATH_SEPARATOR = "/";
|
||||
const EMPTY = "";
|
||||
|
||||
// 布尔常量
|
||||
const DEBUG = true;
|
||||
const RELEASE: boolean = false;
|
||||
const ENABLED = true;
|
||||
|
||||
// 表达式常量
|
||||
const BUFFER_SIZE = 1024 * 8;
|
||||
const TIMEOUT = 60 * 1000;
|
||||
const MASK = 0xFF;
|
||||
const COMBINED = "Hello" $ " " $ "World";
|
||||
|
||||
// 特殊值常量
|
||||
const NULL_VALUE = null;
|
||||
const DEFAULT_PORT = 8080;
|
||||
const MAX_RETRIES: integer = 3;
|
||||
|
||||
//================================================================================
|
||||
// 5. 混合声明测试
|
||||
//================================================================================
|
||||
|
||||
// 同一作用域内的多种声明
|
||||
var localVar: integer;
|
||||
static sharedStatic := 0;
|
||||
global globalResource: Resource;
|
||||
const CONFIG_FILE = "config.json";
|
||||
|
||||
// 连续声明
|
||||
var v1; var v2; var v3;
|
||||
static s1; static s2;
|
||||
global g1; global g2;
|
||||
const C1 = 1; const C2 = 2;
|
||||
|
||||
//================================================================================
|
||||
// 6. 特殊字符和命名测试
|
||||
//================================================================================
|
||||
|
||||
// 下划线开头
|
||||
var _private;
|
||||
static __internal: integer;
|
||||
const _CONSTANT = 100;
|
||||
|
||||
// 数字结尾
|
||||
var var1, var2, var3;
|
||||
static counter_2024;
|
||||
global data_123: array of integer;
|
||||
const VERSION_2 = "2.0";
|
||||
|
||||
// Unicode标识符(如果支持)
|
||||
var 变量: string;
|
||||
static 静态变量 := 0;
|
||||
global 全局设置: dictionary;
|
||||
const 常量值 = "中文";
|
||||
|
||||
//================================================================================
|
||||
// 7. 边界和错误情况(这些应该导致解析错误)
|
||||
//================================================================================
|
||||
|
||||
// 以下是故意的错误示例,用于测试错误处理
|
||||
|
||||
// var x = 10; // 错误:应该使用 :=
|
||||
// const C := 5; // 错误:const应该使用 =
|
||||
// const EMPTY_CONST; // 错误:const必须有值
|
||||
// var ; // 错误:缺少标识符
|
||||
// var x: integer // 错误:缺少分号
|
||||
|
||||
//================================================================================
|
||||
// 8. 格式化和空白测试
|
||||
//================================================================================
|
||||
|
||||
// 紧凑格式
|
||||
var a,b,c:integer:=0;
|
||||
static x,y:real;
|
||||
global m:string:="test";
|
||||
const K=999;
|
||||
|
||||
// 宽松格式
|
||||
var spaced , names : type := value ;
|
||||
static wide : integer ;
|
||||
global lots , of , spaces ;
|
||||
const SPACEY = "value" ;
|
||||
|
||||
// 多行格式
|
||||
var
|
||||
multiline,
|
||||
declaration,
|
||||
test: integer
|
||||
:= 0;
|
||||
|
||||
//================================================================================
|
||||
// 测试结束
|
||||
//================================================================================
|
||||
@@ -0,0 +1,607 @@
|
||||
uid := OnlineUserId();
|
||||
if not uid then
|
||||
begin
|
||||
rqUrl := createObject("TWebRequest").url;
|
||||
return CreateObject('TWebResponse').SendRedirect('/website/security/login.tsl?url='$base64encode(rqUrl)$'&e=base64');
|
||||
end;
|
||||
|
||||
isAdmin := class(IDS_ResponseRightDB).isAdmin(uid);
|
||||
// 公式操作权限
|
||||
opRight := 0;
|
||||
uinfo := class(IDS_ResponseRightDB).getUserInfoByRoleName("勾稽公式操作权限");
|
||||
if isAdmin or (istable(uinfo) and uid in (sselect ["MEMBERID"] from uinfo end)) then
|
||||
begin
|
||||
opRight := 1;
|
||||
end;
|
||||
|
||||
classify := Q("classify") ?: ''; //业务类型
|
||||
tid := Q("tid") ?:''; // 模板id
|
||||
key := Q("key") ?:''; // 公式id
|
||||
onlyFormula := Q('onlyFormula')?:''; //仅显示当前公式相关
|
||||
zhiBiaoJson := ''; // 指标json串
|
||||
zhiBiaoArr := array(); // 指标数据
|
||||
GJGongShi := ''; // 勾稽公式
|
||||
onlyFormulaCheck := ''; // 仅显示当前公式相关选择
|
||||
GJWuChaZhi := ""; // 容差范围:默认万分之一
|
||||
GJBeiZhu := "";
|
||||
checkedClassifyArr := array();
|
||||
|
||||
elements := Q("elements") ?: '';
|
||||
|
||||
xbrlFormulaSign := class(xbrl_formula).getAllFormulaSign();
|
||||
xbrlFormulaOperatorSign := class(xbrl_formula).operatorSign();
|
||||
xbrlFormulaFunctionSign := class(xbrl_formula).functionSign();
|
||||
xbrlFormulaAttributeSign := class(xbrl_formula).attributeSign();
|
||||
xbrlFormulaCondition := class(xbrl_formula).formulaCondition();
|
||||
ele := createobject("ids_element");
|
||||
// 获取报告参数属性标签集合
|
||||
DictionaryByReport := ele.DictionaryByReport();
|
||||
xbrlFormulaReportAttrSign := select distinct ["标签中文名称"] as "key",["标签中文名称"] as "title",["标签ID"] as "e_id" from DictionaryByReport where ["标签英文名称"]<>"GongGaoXinXi_#_ZTGG" end;
|
||||
|
||||
formulaAttrs := array(
|
||||
"is_sanxing": -1,
|
||||
"is_fenji": -1,
|
||||
"is_shangshi": -1,
|
||||
"is_etf": -1,
|
||||
"is_etf_lianjie": -1,
|
||||
"is_zhishu": -1,
|
||||
"is_jiji": -1,
|
||||
"is_fof": -1,
|
||||
"is_mom": -1,
|
||||
"is_xinjijin": -1,
|
||||
"is_faqishi": -1,
|
||||
"fundtype": array2str(xbrlFormulaCondition["基金类别"]["default"], ";"),
|
||||
"guzhifangshi": array2str(xbrlFormulaCondition["估值方式"]["default"], ";"),
|
||||
"yunzuofangshi": array2str(xbrlFormulaCondition["运作方式"]["default"], ";"),
|
||||
"adaptType":"limit",
|
||||
"fundid": "",
|
||||
);
|
||||
errorMsg := '';
|
||||
|
||||
//修改公式
|
||||
if key then
|
||||
begin
|
||||
obj := createObject("ids_xbrl_expr");
|
||||
obj.exprAttr(key);
|
||||
GJWuChaZhi := obj.GJWuChaZhi ?: "";
|
||||
(*
|
||||
if istable(obj.GJZhiBiao) then
|
||||
begin
|
||||
GJGongShi := obj.GJZhiBiao;
|
||||
if istable(obj.GJXiangMu) then
|
||||
begin
|
||||
for i,v in obj.GJXiangMu do
|
||||
update GJGongShi set thisrow = v[1] where thisrow = v[0] end;
|
||||
end;
|
||||
GJGongShi := sselect "[[" $ thisrow $ "]]" as thisrow from GJGongShi end;
|
||||
GJGongShi := array2str(GJGongShi, "");
|
||||
end;
|
||||
*)
|
||||
gongShi := obj.GJGongShi;
|
||||
if gongShi then
|
||||
begin
|
||||
GJGongShi := _getSplitFormula(gongShi);
|
||||
GJBeiZhu := obj.GJBeiZhu ?: "";
|
||||
formulaAttrs := array(
|
||||
"is_sanxing": obj.isSanXing,
|
||||
"is_fenji": obj.isFenJi,
|
||||
"is_shangshi": obj.isShangShi,
|
||||
"is_etf": obj.isETF,
|
||||
"is_etf_lianjie": obj.isETFLianJie,
|
||||
"is_zhishu": obj.isZhiShu,
|
||||
"is_jiji": obj.isJianJuJiJi,
|
||||
"is_fof": obj.isFOF,
|
||||
"is_mom": obj.isMOM,
|
||||
"is_xinjijin": obj.isXinJiJin,
|
||||
"is_faqishi": obj.isFaQiShi,
|
||||
"fundtype": obj.GJFanWei,
|
||||
"guzhifangshi": obj.GuZhiFangShi,
|
||||
"yunzuofangshi": obj.YunZuoFangShi,
|
||||
"adaptType":obj.adaptType,
|
||||
"fundid": obj.fundid,
|
||||
);
|
||||
zhiBiaoArr := obj.GJZhiBiao;
|
||||
if istable(zhiBiaoArr) then
|
||||
zhiBiaoJson := class(TSTool).Arr2Json(zhiBiaoArr);
|
||||
// json 串内有单引号需转义
|
||||
if ansipos("'", zhiBiaoJson) then
|
||||
zhiBiaoJson := ansireplacetext(zhiBiaoJson,"'","\\'");
|
||||
if ansipos("'", GJGongShi) then
|
||||
GJGongShi := ansireplacetext(GJGongShi,"'","\\'");
|
||||
if obj.classify then
|
||||
classifyArr := str2array(obj.classify, ";");
|
||||
|
||||
if not classify and classifyArr then
|
||||
begin
|
||||
classify := classifyArr[0];
|
||||
checkedClassifyArr &= classifyArr;
|
||||
end else
|
||||
begin
|
||||
if classify then
|
||||
checkedClassifyArr &= str2array(classify, ";");
|
||||
if classifyArr then
|
||||
checkedClassifyArr &= classifyArr;
|
||||
end;
|
||||
onlyFormulaCheck := '<div class="filter-tool">'
|
||||
$ '<label class="ivu-checkbox-wrapper ivu-checkbox-small ivu-checkbox-border">'
|
||||
$ '<span class="ivu-checkbox '$(onlyFormula?'ivu-checkbox-checked':'')$'">'
|
||||
$ '<span class="ivu-checkbox-inner"></span>'
|
||||
$ '<input type="checkbox" class="js-onlyFormula ivu-checkbox-input" '$(onlyFormula?'checked':'')$'>'
|
||||
$ '</span> 仅显示当前公式相关</label>'
|
||||
$ '</div>';
|
||||
end else
|
||||
begin
|
||||
errorMsg := '<div class="alert alert-danger">无效公式,请确认该公式是否删除!</div>';
|
||||
end;
|
||||
end else
|
||||
begin // 新增公式
|
||||
if classify then
|
||||
begin
|
||||
if classify = "SEMIYEAR_REP" or classify = "YEAR_REP" then
|
||||
checkedClassifyArr := array("SEMIYEAR_REP", "YEAR_REP");
|
||||
else
|
||||
checkedClassifyArr &= str2array(classify, ";");
|
||||
end;
|
||||
end;
|
||||
checkedClassifyJson := '';
|
||||
if istable(checkedClassifyArr) then
|
||||
checkedClassifyJson := class(TStool).Arr2Json(distinctstr(checkedClassifyArr)); // 默认选中的业务
|
||||
|
||||
businessOfUser := class(IDS_BusinessDB).getKeyByUID(uid);
|
||||
classifyList := class(ts_switch).getSwitchApplyClassify("report_audit_view");
|
||||
classifyData := select ["BUSINESS_KEY"], ["BUSINESS_NAME"] from businessOfUser where ["BUSINESS_KEY"] in classifyList order by ["BUSINESS_NAME"] end;
|
||||
classifyList := array(("BUSINESS_KEY": "", "BUSINESS_NAME": "-")) union classifyData;
|
||||
|
||||
if not tid then
|
||||
begin
|
||||
templateList := select ["TID"], ["TNAME"] from class(IDS_TemplateDB).getTemplateByClassify(classify) end;
|
||||
tid := _getTemplateID(templateList);
|
||||
end else
|
||||
begin
|
||||
templateList := select ["TID"], ["TNAME"] from class(IDS_TemplateDB).getTemplateByClassify(classify) end;
|
||||
end;
|
||||
|
||||
templateList := array(("TID": "", "TNAME": "-")) union templateList;
|
||||
|
||||
temptList := '';
|
||||
dataContent := '';
|
||||
emListHtml := '';
|
||||
if tid then
|
||||
begin
|
||||
// 元素标签相关信息
|
||||
r := class(xbrl_formula).getElementTagInfo(tid); // 根据模板获取指标标签信息
|
||||
// 根据业务获取业务相关标签
|
||||
baseData := class(xbrl_formula).getBasicIndexByClassify(classify);
|
||||
// 模板相关元素
|
||||
emList := class(IDS_RformalDB).getTempleteElementList(tid);
|
||||
// 标签数据字典
|
||||
Dictionary := ele.Dictionary();
|
||||
Dictionary := select ["标签ID"] as "E_ID",["标签中文名称"] as "E_CN_NAME" from Dictionary end;
|
||||
|
||||
emArr := array();
|
||||
cnArr := array();
|
||||
rt := select distinct ["E_ID"], ["E_CN_NAME"] from r end;
|
||||
if istable(baseData) then
|
||||
rt := rt union2 baseData union2 Dictionary;
|
||||
|
||||
for i := 0 to length(rt) - 1 do
|
||||
begin
|
||||
emArr[rt[i]["E_ID"]] := rt[i]["E_CN_NAME"];
|
||||
cnArr[rt[i]["E_CN_NAME"]] := rt[i]["E_ID"];
|
||||
end;
|
||||
// 元素标签
|
||||
(*elementArr := class(IDS_ElementDB).getElementNameAndXbTag();
|
||||
elementTagArr := array();
|
||||
vv := 0;
|
||||
for i := 0 to length(elementArr) - 1 do
|
||||
begin
|
||||
if not elementArr[i]["XBRL_TAG"] then continue;
|
||||
elementTagArr[elementArr[i]["NAME"]] := elementArr[i]["NAME"];
|
||||
end;
|
||||
*)
|
||||
|
||||
// xbElementJson := class(TStool).Arr2Json(elementTagArr); // 含xbtag标签的元素,用来匹配元素()这个函数
|
||||
xbElementJson := "";
|
||||
elementJson := class(TStool).Arr2Json(emArr); // 元素id标签对照 {"1702":"本报告期基金份额总额", ...}
|
||||
cn_nameJson := class(TStool).Arr2Json(cnArr); // 中文标签对照 {"本报告期基金份额总额":"1702", ...}
|
||||
// \转义
|
||||
if ansipos("\\", elementJson) then
|
||||
elementJson := AnsiReplaceText(elementJson, "\\", "\\\\");
|
||||
//文本类的e_id
|
||||
eTxt := select ["E_ID"],["EID"],["E_CN_NAME"],["ISEM"] from r where ["ISEM"] = 1 end;
|
||||
rela_eid := array();
|
||||
if istable(zhiBiaoArr) and istable(r) then
|
||||
begin
|
||||
// 获取仅在公式指标中的相关元素
|
||||
rela_eid := sselect distinct ["EID"] from r where ["E_ID"] in zhiBiaoArr end;
|
||||
end;
|
||||
|
||||
if istable(emList) then
|
||||
begin
|
||||
filterList := array(("title": "元素筛选", "key": "ELEMENT-NAME", "option": emList, "mulitList": "mulitEm"));
|
||||
emListHtml := '<div class="filter-tool">';
|
||||
emListHtml += checkFilter(filterList, 'formulae-filter', '');
|
||||
emListHtml += '</div>';
|
||||
end;
|
||||
|
||||
// 模板元素数据
|
||||
data := class(xbrl_formula).getTemplateData(tid);
|
||||
if istable(data) then
|
||||
begin
|
||||
elementArr := array();
|
||||
if elements then
|
||||
elementArr := str2array(elements, ";") ;
|
||||
|
||||
if istable(rela_eid) and onlyFormula then
|
||||
begin
|
||||
if istable(elementArr) then
|
||||
rela_eid &= elementArr;
|
||||
data := select * from data where ["EID"] in rela_eid or ["TYPE"] = "title" end;
|
||||
data := class(ReportData).deleteEmptyChapter(data); // 去除空章节
|
||||
end
|
||||
else if istable(elementArr) then
|
||||
begin
|
||||
data := select * from data where ["EID"] in elementArr or ["TYPE"] = "title" end;
|
||||
data := class(ReportData).deleteEmptyChapter(data); // 去除空章节
|
||||
end;
|
||||
temptList := class(xbrl_formula).getTemplateHtml(data);
|
||||
end;
|
||||
|
||||
end else
|
||||
begin
|
||||
data := array();
|
||||
temptList := '';
|
||||
end;
|
||||
|
||||
<?tslx>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>勾稽公式构建</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=gb2312" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<link rel="stylesheet" type="text/css" href="/resource/iview/iview.css?v=<?=ids_version()?>" />
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/jquery-ui/jquery.ui.all.css">
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/bootstrap/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/bootstrap/button.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/font-awesome.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/style.css?v=<?=ids_version()?>" />
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/report.css?v=<?=ids_version()?>" />
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/live_report.css?v=<?=ids_version()?>" />
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/xbrl_data_audit_view.css?v=<?=ids_version()?>" />
|
||||
<link rel="stylesheet" type="text/css" href="/resource/fundids/css/formula.css?v=<?=ids_version()?>" />
|
||||
<link rel="stylesheet" type="text/css" href="/resource/codemirror/lib/codemirror.css" />
|
||||
<script type="text/javascript" src="/resource/js/jquery-1.8.3.min.js" ></script>
|
||||
<script type="text/javascript" src="/resource/js/jquery-migrate-1.8.3.min.js" ></script>
|
||||
<script type="text/javascript" src="/resource/js/jquery-ui-1.10.2.custom.min.js"></script>
|
||||
<script type="text/javascript" src="/resource/vue/vue.min.js" charset="UTF-8"></script>
|
||||
<script type="text/javascript" src="/resource/iview/iview.min.js" charset="UTF-8"></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/tsalert.js"></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/edittable.js"></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/global.js?v=<?=ids_version()?>"></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/autoTextarea.js?v=<?=ids_version()?>"></script>
|
||||
<script type="text/javascript" src="/resource/js/dropdown-button.js"></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/dm.ext.js?v=<?=ids_version()?>"></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/live_report.js?v=<?=ids_version()?>"></script>
|
||||
<script type='text/javascript' src='/resource/fundids/js/xbrl_formula_page.js?v=<?=ids_version()?>'></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/xbrl_formula_view.js?v=<?=ids_version()?>"></script>
|
||||
<script type="text/javascript" src="/resource/fundids/js/check_xbrldata.js?v=<?=ids_version()?>"></script>
|
||||
<script type="text/javascript" src="/resource/codemirror/lib/codemirror.umd.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="xbrl-formula-view-wrapper">
|
||||
<div class="top-banner">
|
||||
<div class="title-wrapper"></div>
|
||||
<div class="tools-wrapper">
|
||||
<div class="left-tools">
|
||||
<div class="filter-tool">
|
||||
<span>业务类型:</span>
|
||||
<?=class(html).makeSelect(classifyList, ' class="formula-classify-select" ', classify, 'BUSINESS_NAME', 'BUSINESS_KEY')?>
|
||||
</div>
|
||||
<div class="filter-tool">
|
||||
<span>模板:</span>
|
||||
<?=class(html).makeSelect(templateList, ' class="formula-model-select" ', tid, 'TNAME', 'TID')?>
|
||||
</div>
|
||||
<?=emListHtml?>
|
||||
<?=onlyFormulaCheck?>
|
||||
<div id="page-params" class="filter-tool">
|
||||
<input type="hidden" name="elements" value="<?=elements?>">
|
||||
<input type="hidden" name="classify" value="<?=classify?>">
|
||||
<input type="hidden" name="tid" value="<?=tid?>">
|
||||
<input type="hidden" name="key" value="<?=key?>">
|
||||
<input type="hidden" name="onlyFormula" value="<?=onlyFormula?>">
|
||||
</div>
|
||||
<div class="filter-tool">
|
||||
<button class="btn btn-primary" @click="clickQueryBtn"> 查 询 </button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-tools">
|
||||
<div class="filter-tool">
|
||||
<?=key and opRight?'<button class="btn btn-primary btn-add-formulae" data-classify="'$classify$'"> + 新增 </button>':''?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aui-page-panel-inner">
|
||||
<!--目录-->
|
||||
<div class="aui-page-panel-nav">
|
||||
<div class="report_navigator">
|
||||
<div class="filter-panel">导航栏</div>
|
||||
<?=temptList?>
|
||||
<div class="bottomth"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aui-page-panel-content row-fluid">
|
||||
<!--数据-->
|
||||
<div class="model-data-area js-rpt-content">
|
||||
<div class="report_page data_page">
|
||||
<?tsl
|
||||
if errorMsg then
|
||||
echo errorMsg;
|
||||
sysparams["xbrl_formula_view"] := true;
|
||||
for i := 0 to length(data) - 1 do
|
||||
begin
|
||||
textClass := '';
|
||||
zhibiaoSpan := '';
|
||||
echo '<div class="element-data-container">';
|
||||
if data[i]['EID'] then
|
||||
begin
|
||||
editBtn := '';
|
||||
zhibiaoid := '';
|
||||
if istable(eTxt) then
|
||||
begin
|
||||
try
|
||||
zhibiaoid := sselect ["E_ID"] from eTxt where ["EID"] = data[i]["EID"] and ["ISEM"] = 1 end[0] ?:'';
|
||||
if zhibiaoid then
|
||||
zhibiaoSpan := '<span class="zhibiaoid" data-zhibiaoid="'$zhibiaoid$'"> ['$zhibiaoid$']</span>';
|
||||
except
|
||||
zhibiaoSpan := '';
|
||||
end;
|
||||
end;
|
||||
(*
|
||||
if data[i]["TYPE"] = 'txt' then
|
||||
begin
|
||||
textClass := 'hasTextSample';
|
||||
if zhibiaoid then
|
||||
editBtn := '<div class="text-right element-data-actions">'
|
||||
$ '<button class="btn btn-mini edit-txt-index" data-zhibiaoid="'$zhibiaoid$'" title="设置文本变量指标">指标</button>'
|
||||
$ '<button class="btn btn-mini edit-template-txt" title="修改文本样例">样例</button>'
|
||||
$ '<button class="btn btn-mini btn-formula-list" title="相关公式">公式</button>'
|
||||
$ '</div>';
|
||||
end else
|
||||
begin
|
||||
editBtn := '<div class="text-right element-data-actions">'
|
||||
$ '<button class="btn btn-mini btn-formula-list" title="相关公式">公式</button>'
|
||||
$ '</div>';
|
||||
end;
|
||||
*)
|
||||
editBtn := '<div class="text-right element-data-actions">'
|
||||
$ '<button class="btn btn-mini btn-formula-list" data-eid="'$data[i]['EID']$'" title="相关公式">公式</button>'
|
||||
$ '</div>';
|
||||
echo '<div class="element-bar"><span class="element-name" data-eid="'$data[i]["EID"]$'"><i class="'$getTypetag(data[i]["TYPE"])$'"></i> '$data[i]["NAME"]$zhibiaoSpan$'</span>'$editBtn$'</div>';
|
||||
end;
|
||||
echo '<div class="row">
|
||||
<div class="element-data-content '$textClass$'">';
|
||||
class(xbrldataauditreport).rpt_show_data(data[i], true);
|
||||
echo '</div></div>';
|
||||
|
||||
echo '</div>';
|
||||
end;
|
||||
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<!--公式区-->
|
||||
<div class="formula-edit-area" v-cloak>
|
||||
<tabs :animated="true" size="small">
|
||||
<tab-pane label="公式编辑">
|
||||
<div class="formula-tools">
|
||||
<div class="formula-tools-list">
|
||||
<div v-for="(item, index) of toolListData" :key="index" class="formula-tools-list-item">
|
||||
<i-button type="small" class="formula-tools-item" @click="insertSign(item)" :title="item.info">{{ item.label }}</i-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formula-tools-list" style="display: none;">
|
||||
<div v-for="(item, index) of reportAttrListData" :key="index" class="formula-tools-list-item">
|
||||
<i-button type="small" class="formula-tools-item" @click="insertSign(item)" :title="item.info">{{ item.label }}</i-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formula-editor">
|
||||
<editor-component ref="editor" :editor-data.sync="formula" :completion-options="formulaRule" :vaild-params="vaildParams" :invalid-param-msg="invalidParamMsg" symbol-sets="()" />
|
||||
</div>
|
||||
</tab-pane>
|
||||
<tab-pane label="公式属性">
|
||||
<div class="formula-tools">
|
||||
<div class="formula-attrs">
|
||||
<div class="formula-attrs-list">
|
||||
<p>适用业务:</p>
|
||||
<checkbox-group v-model="formulaClassify" class="formula-classify" size="small">
|
||||
<?tsl
|
||||
for i,v in classifyData do
|
||||
echo '<div class="formula-classify-item"><checkbox label="'$v["BUSINESS_KEY"]$'">'$v["BUSINESS_NAME"]$'</checkbox></div>';
|
||||
?>
|
||||
</checkbox-group>
|
||||
</div>
|
||||
<?tsl
|
||||
for i,v in xbrlFormulaCondition do
|
||||
begin
|
||||
if not pos("IS_", v["name"]) then
|
||||
begin
|
||||
echo '<div class="formula-attrs-list"><p>'$i$':</p> <checkbox-group v-model="'$lowerCase(v["name"])$'" class="formula-prod-attr" size="small">';
|
||||
for si,sv in v["value"] do
|
||||
echo '<div class="formula-prod-attr-item"><checkbox label="'$sv$'">'$sv$'</checkbox></div>';
|
||||
echo '</checkbox-group></div>';
|
||||
end;
|
||||
end;
|
||||
?>
|
||||
<div class="formula-attrs-list">
|
||||
<p>其它属性:</p>
|
||||
<div class="formula-prod-attr ">
|
||||
<?tsl
|
||||
otherAttrs := select * from xbrlFormulaCondition where pos("IS_", thisrow["name"]) end;
|
||||
for i,v in otherAttrs do
|
||||
begin
|
||||
//echo '<div class="formula-prod-attr-item"><checkbox v-model="'$lowerCase(v["name"])$'" size="small">'$i$'</checkbox></div>';
|
||||
echo
|
||||
'<div class="formula-prod-attr-item">
|
||||
<label>'$i$'</label>
|
||||
<i-select placeholder="" v-model="'$lowerCase(v["name"])$'" style="width:70px; margin-left:4px;">
|
||||
<i-option value=-1 key=""> </i-option>
|
||||
<i-option value=1 key="1">是</i-option>
|
||||
<i-option value=0 key="0">否</i-option>
|
||||
</i-select>
|
||||
</div>';
|
||||
end;
|
||||
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formula-attrs-list">
|
||||
<p>基 金:</p>
|
||||
<div class="formula-prod-attr">
|
||||
<i-select placeholder="" v-model="adaptType" style="width:100px">
|
||||
<i-option value="limit" key="1">仅适用</i-option>
|
||||
<i-option value="defy" key="0">不适用</i-option>
|
||||
<i-option value="extend" key="2">额外适用</i-option>
|
||||
</i-select>
|
||||
<input value="<?=formulaAttrs["fundid"]?>" type="text" class="form-control mul_produnct ui-autocomplete-input" autocomplete="off" placeholder="请输入主基金代码"> <button type="button" title="基金选择" class="btn CheckfundList">...</button></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formula-attrs-list">
|
||||
<p>容差范围:</p>
|
||||
<input-number class="formula-wucha" :max="1" :min="0" :step="0.0001" v-model="formulaWucha" size="small" style="height:30px;"></input-number>
|
||||
</div>
|
||||
<div class="formula-attrs-list">
|
||||
<p>备 注:</p>
|
||||
<i-input class="formula-beizhu" v-model="beizhu" type="textarea" :autosize="{minRows: 2,maxRows: 3}" size="small" ></i-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tab-pane>
|
||||
<tab-pane label="数据字典"></tab-pane>
|
||||
<?tsl
|
||||
if opRight then
|
||||
echo '<template #extra>
|
||||
<i-button size="small" type="primary" :disabled="!formula" @click="saveFormula(\'save\')"> 保存 </i-button>
|
||||
<i-button size="small" :disabled="!formula" @click="saveFormula(\'saveAS\')" title="另存为新的公式"> 另存 </i-button>
|
||||
<i-button size="small" :disabled="!formula" @click="saveFormula(\'test\')" title="测试勾稽校验"> 校验 </i-button>
|
||||
<i-button size="small" type="error" :disabled="!formula" @click="clearFormula"> 清空 </i-button>
|
||||
</template>';
|
||||
?>
|
||||
</tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var XBRL_FORMULA_SIGN = <?=class(TSTool).Arr2Json(xbrlFormulaSign)?>;
|
||||
var XBRL_FORMULA_OPERATOR_SIGN = <?=class(TSTool).Arr2Json(xbrlFormulaOperatorSign)?>;
|
||||
var XBRL_FORMULA_FUNCTION_SIGN = <?=class(TSTool).Arr2Json(xbrlFormulaFunctionSign)?>;
|
||||
var XBRL_FORMULA_ATTRIBUTE_SIGN = <?=class(TSTool).Arr2Json(xbrlFormulaAttributeSign)?>;
|
||||
var XBRL_FORMULA_CONDITION = <?=class(TSTool).Arr2Json(xbrlFormulaCondition)?>;
|
||||
var XBRL_FORMULA_REPORTATTR_SIGN = <?=class(TSTool).Arr2Json(xbrlFormulaReportAttrSign)?>;
|
||||
var elementJson = '<?=elementJson?>';
|
||||
if(elementJson && !Array.isArray(elementJson)){
|
||||
elementJson = JSON.parse(elementJson);
|
||||
}
|
||||
var xbElementJson = '<?=xbElementJson?>';
|
||||
if(xbElementJson && !Array.isArray(xbElementJson)){
|
||||
xbElementJson = JSON.parse(xbElementJson);
|
||||
}
|
||||
var cn_nameJson = '<?=cn_nameJson?>';
|
||||
if(cn_nameJson && !Array.isArray(cn_nameJson)){
|
||||
cn_nameJson = JSON.parse(cn_nameJson);
|
||||
}
|
||||
var zhiBiaoJson = '<?=zhiBiaoJson?>';
|
||||
if(zhiBiaoJson && !Array.isArray(zhiBiaoJson)){
|
||||
zhiBiaoJson = JSON.parse(zhiBiaoJson);
|
||||
}
|
||||
var GOUJIGONGSHI = '<?=GJGongShi?:""?>';
|
||||
var FORMULAID = '<?=key?:""?>';
|
||||
var formulaWucha = '<?=GJWuChaZhi?:""?>';
|
||||
var formulaClassify = '<?=checkedClassifyJson?:""?>';
|
||||
var formulaBeizhu = '<?=GJBeiZhu?:""?>';
|
||||
<?tsl
|
||||
for i,v in formulaAttrs do
|
||||
Begin
|
||||
// echo "var "$i$" = "$(v <> "" ? '"'$v$'"' : "false")$";";
|
||||
echo "var "$i$" = '"$v$"';";
|
||||
|
||||
end;
|
||||
|
||||
?>
|
||||
$(function(){
|
||||
// 基金代码选择器
|
||||
AddAutoComplete_mul(".mul_produnct","product","");
|
||||
// 添加文本指标标签
|
||||
addTextTag(cn_nameJson);
|
||||
// 指标标签
|
||||
addElementTag(elementJson, zhiBiaoJson);
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?tsl
|
||||
|
||||
function getTypetag(types);
|
||||
begin
|
||||
case types of
|
||||
'txt': typetag := 'icon-text-width';
|
||||
'table': typetag := 'icon-table';
|
||||
'pic':typetag := 'icon-picture';
|
||||
'complex': typetag := 'icon-list';
|
||||
'mix':typetag := 'icon-th-large';
|
||||
'radio': typetag := 'icon-ok-circle';
|
||||
else
|
||||
typetag := '';
|
||||
end;
|
||||
return typetag;
|
||||
end;
|
||||
|
||||
function _getTemplateID(t);
|
||||
begin
|
||||
if not istable(t) then
|
||||
return '';
|
||||
t1 := sselect ["TID"] from t where LeftStr(["TNAME"], 2) = "普通" order by ["TNAME"],["IS_BASIC"] desc end;
|
||||
if istable(t1) then
|
||||
return t1[0];
|
||||
t2 := sselect ["TID"] from t order by ["IS_BASIC"] desc end;
|
||||
if istable(t1) then
|
||||
return t2[0];
|
||||
return '';
|
||||
end;
|
||||
|
||||
function _getSplitFormula(f);
|
||||
begin
|
||||
f1 := f;
|
||||
t := class(IDS_AuditExpr).analysisFormulae(f1);
|
||||
|
||||
item := array();
|
||||
for i := 0 to length(t) - 1 do
|
||||
begin
|
||||
k := "[[REP_"$i$"]]";
|
||||
item[i]:= array("v": "[["$t[i]$"]]", "k": k );
|
||||
f := replaceStr(f, t[i], k );
|
||||
end;
|
||||
|
||||
for i := 0 to length(item) - 1 do
|
||||
begin
|
||||
f := replaceStr(f, item[i]["k"], item[i]["v"]);
|
||||
end;
|
||||
|
||||
attrArr := class(xbrl_formula).attributeSign();
|
||||
for i := 0 to length(attrArr) - 1 do
|
||||
begin
|
||||
attr := attrArr[i]["key"];
|
||||
if pos(attr, f) then
|
||||
f := replaceStr(f, "("$attr$")", "]][[("$attr$")");
|
||||
end;
|
||||
|
||||
f := replaceStr(f, "#", "]]#[[" );
|
||||
return f;
|
||||
end;
|
||||
@@ -0,0 +1,7 @@
|
||||
// function 公募基金简称(shortname);
|
||||
function abc(shortname);
|
||||
begin
|
||||
中文 := 123;
|
||||
pinfo := sysparams["productInfo"];
|
||||
end;
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
|
||||
[*.{json,toml,yml,gyp}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.scm]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{c,cc,h}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.rs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{py,pyi}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.swift]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[parser.c]
|
||||
indent_size = 2
|
||||
|
||||
[{alloc,array,parser}.h]
|
||||
indent_size = 2
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
# Generated source files
|
||||
src/*.json linguist-generated
|
||||
src/parser.c linguist-generated
|
||||
src/tree_sitter/* linguist-generated
|
||||
|
||||
# C bindings
|
||||
bindings/c/** linguist-generated
|
||||
CMakeLists.txt linguist-generated
|
||||
Makefile linguist-generated
|
||||
|
||||
# Rust bindings
|
||||
bindings/rust/* linguist-generated
|
||||
Cargo.toml linguist-generated
|
||||
Cargo.lock linguist-generated
|
||||
|
||||
# Node.js bindings
|
||||
bindings/node/* linguist-generated
|
||||
binding.gyp linguist-generated
|
||||
package.json linguist-generated
|
||||
package-lock.json linguist-generated
|
||||
|
||||
# Python bindings
|
||||
bindings/python/** linguist-generated
|
||||
setup.py linguist-generated
|
||||
pyproject.toml linguist-generated
|
||||
|
||||
# Go bindings
|
||||
bindings/go/* linguist-generated
|
||||
go.mod linguist-generated
|
||||
go.sum linguist-generated
|
||||
|
||||
# Swift bindings
|
||||
bindings/swift/** linguist-generated
|
||||
Package.swift linguist-generated
|
||||
Package.resolved linguist-generated
|
||||
|
||||
# Zig bindings
|
||||
build.zig linguist-generated
|
||||
build.zig.zon linguist-generated
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
# Rust artifacts
|
||||
target/
|
||||
Cargo.lock
|
||||
|
||||
# Node artifacts
|
||||
build/
|
||||
prebuilds/
|
||||
node_modules/
|
||||
package-lock.json
|
||||
|
||||
# Swift artifacts
|
||||
.build/
|
||||
Package.resolved
|
||||
|
||||
# Go artifacts
|
||||
_obj/
|
||||
|
||||
# Python artifacts
|
||||
.venv/
|
||||
dist/
|
||||
*.egg-info
|
||||
*.whl
|
||||
|
||||
# C artifacts
|
||||
*.a
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
*.dll
|
||||
*.pc
|
||||
*.exp
|
||||
*.lib
|
||||
|
||||
# Zig artifacts
|
||||
.zig-cache/
|
||||
zig-cache/
|
||||
zig-out/
|
||||
|
||||
# Example dirs
|
||||
/examples/*/
|
||||
|
||||
# Grammar volatiles
|
||||
*.wasm
|
||||
*.obj
|
||||
*.o
|
||||
|
||||
# Archives
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
*.zip
|
||||
-1
@@ -1 +0,0 @@
|
||||
ret := insert into sqltable tableName of FDBAlias data[i:i+999-1];
|
||||
-1644
File diff suppressed because it is too large
Load Diff
-364
@@ -1,364 +0,0 @@
|
||||
// Example TSF program demonstrating various language features
|
||||
|
||||
// Variable declarations
|
||||
var x, y, z: int;
|
||||
var name: string;
|
||||
var matrix: array of real;
|
||||
|
||||
// Constants
|
||||
const PI = 3.14159;
|
||||
const MAX_SIZE: int = 100;
|
||||
const GREETING = "Hello, World!";
|
||||
|
||||
// Global and static variables
|
||||
global config: object;
|
||||
static counter := 0;
|
||||
|
||||
// Basic arithmetic
|
||||
x := 10;
|
||||
y := 20;
|
||||
z := x + y * 2; // z = 50
|
||||
|
||||
// String operations
|
||||
name := "John" $ " " $ "Doe";
|
||||
|
||||
// Boolean operations
|
||||
var isValid := x > 0 and y < 100;
|
||||
var isReady := not (z = 0) or name <> "";
|
||||
|
||||
// Bitwise operations
|
||||
var flags := 0b1010;
|
||||
flags := flags .| 0b0101; // flags = 0b1111
|
||||
flags := flags shl 2; // flags = 0b111100
|
||||
|
||||
// Matrix operations
|
||||
var A, B, C: matrix;
|
||||
C := A :* B; // Matrix multiplication
|
||||
C := A :^ 2; // Matrix power
|
||||
|
||||
// Set operations
|
||||
var set1, set2, result: set;
|
||||
result := set1 union set2;
|
||||
result := set1 intersect set2;
|
||||
|
||||
// Ternary operator
|
||||
var max := x > y ? x : y;
|
||||
var sign := x > 0 ? 1 : x < 0 ? -1 : 0;
|
||||
|
||||
// Prefix and postfix operators
|
||||
++counter;
|
||||
var oldValue := counter++;
|
||||
|
||||
// Augmented assignments
|
||||
x += 10;
|
||||
y *= 2;
|
||||
flags .&= 0xFF;
|
||||
set1 union= set2;
|
||||
obj.a := 123;
|
||||
obj["a"] := 456;
|
||||
|
||||
// Special values
|
||||
var nothing := nil;
|
||||
var infinity := +inf;
|
||||
var negInfinity := -inf;
|
||||
|
||||
// array
|
||||
arr := array();
|
||||
arr := array(1, 2, 3);
|
||||
arr := array(1, "abc", true, nil);
|
||||
arr := array("key1": "value1", "key2": "value2");
|
||||
arr := array((1, "a"), array(2, "b"));
|
||||
arr := array(array(1, 2), array(3, 4));
|
||||
arr := array(array(array(1, 2), array(3, 4)), array(array(5, 6), array(7, 8)));
|
||||
arr := array(("key1": array(1, 2, 3)), ("key2": (4, 5, 6)));
|
||||
arr := array("outer": array("inner1": 1, "inner2": 2), "data": array(1, 2, 3));
|
||||
arr := array((array(1, 2), array("a", "b")), (array(3, 4), array("c", "d")));
|
||||
arr := array("data": array((1, "first"), (2, "second")), "meta": array("count": 2, "type": "test"));
|
||||
arr := array(var1, var2, array(var3, var4));
|
||||
arr := array(func1(), func2(arg), array(func3(), func4(arg1, arg2)));
|
||||
arr := array(func(), (a + b));
|
||||
arr := array((x + y), z, (a * b));
|
||||
arr := array(func(), (a + b), var1, (c * d));
|
||||
arr := array((a, b, c), (x + y), ("key": "value"));
|
||||
arr := array(1, func(), (expr), (a, b), "key": (value));
|
||||
|
||||
data := array(
|
||||
"users": array(
|
||||
("id": 1, "name": "Alice", "scores": array(85, 92, 78)),
|
||||
("id": 2, "name": "Bob", "scores": array(91, 87, 95))
|
||||
),
|
||||
"metadata": array(
|
||||
"total": 2,
|
||||
"average": array(88.0, 89.5, 86.5),
|
||||
"nested": array(
|
||||
"level1": array(
|
||||
"level2": array(1, 2, 3),
|
||||
"level2b": (true, false, nil)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// 访问嵌套数据
|
||||
first_user := data["users"][0];
|
||||
first_score := first_user["scores"][0];
|
||||
nested_value := data["metadata"]["nested"]["level1"]["level2"][1];
|
||||
|
||||
echo "First user score:", first_score;
|
||||
echo "Nested value:", nested_value;
|
||||
|
||||
// Function calls (hypothetical functions)
|
||||
process(data);
|
||||
calculate(x: 10, y: 20, mode: "fast");
|
||||
##process(data);
|
||||
|
||||
// Attribute access (hypothetical objects)
|
||||
// var length := myString.length;
|
||||
// config.settings.timeout := 3000;
|
||||
|
||||
// Array subscripting and slicing
|
||||
// var first := array[0];
|
||||
// var subArray := array[1:10];
|
||||
// var tail := array[5:];
|
||||
|
||||
// Complex expressions with precedence
|
||||
var result1 := 2 + 3 * 4 ^ 2; // 2 + 3 * 16 = 50
|
||||
var result2 := (2 + 3) * 4 ^ 2; // 5 * 16 = 80
|
||||
var result3 := not a > b and c <= d or e = f;
|
||||
|
||||
// Derivative operator (mathematical)
|
||||
// var derivative := !f;
|
||||
|
||||
// Expression operators
|
||||
// var reference := @value;
|
||||
// var address := &variable;
|
||||
|
||||
{ This is a block comment
|
||||
It can span multiple lines
|
||||
and contain any text }
|
||||
|
||||
(* This is a nested comment
|
||||
It can also span multiple lines
|
||||
and is Pascal-style *)
|
||||
|
||||
// Chained comparisons
|
||||
var inRange := 0 <= x <= 100;
|
||||
var ordered := a < b < c;
|
||||
|
||||
// Nested assignments
|
||||
var a := var b := var c := 0;
|
||||
|
||||
// Complex type specifications
|
||||
var complexType: array of array of real;
|
||||
var functionType: procedure of integer;
|
||||
|
||||
// const
|
||||
const a: real = 10;
|
||||
const b = "123";
|
||||
|
||||
// augmented_assignment
|
||||
a += 10;
|
||||
b += func();
|
||||
c /= ma[1];
|
||||
|
||||
// return
|
||||
return;
|
||||
return 10;
|
||||
return f(10);
|
||||
|
||||
// break
|
||||
break;
|
||||
|
||||
// continue
|
||||
continue;
|
||||
|
||||
// echo
|
||||
echo abc $ def $ "123" $ 456, funcstr(), "\n";
|
||||
|
||||
// raise
|
||||
raise abc() $ "123";
|
||||
|
||||
// inherited
|
||||
inherited abc();
|
||||
|
||||
// new
|
||||
obj := new abc();
|
||||
|
||||
// if
|
||||
if condition then
|
||||
f1();
|
||||
else
|
||||
raise "abc";
|
||||
|
||||
if condition1 then
|
||||
begin
|
||||
if f1() then echo 1;
|
||||
else echo 2;
|
||||
end
|
||||
else if condition2 then
|
||||
begin
|
||||
echo 3;
|
||||
end
|
||||
else begin
|
||||
echo 4;
|
||||
end
|
||||
|
||||
// for
|
||||
for i:=0 to 10 do
|
||||
echo i, "\n";
|
||||
|
||||
for k,v in arr do
|
||||
begin
|
||||
echo "k = 0", "\n";
|
||||
echo "v = 1", "\n";
|
||||
end
|
||||
|
||||
// while
|
||||
while true do
|
||||
echo 123;
|
||||
|
||||
// repeat
|
||||
repeat
|
||||
echo 1;
|
||||
a++;
|
||||
until a > 10;
|
||||
|
||||
// case
|
||||
case x of
|
||||
1,2: return abc;
|
||||
"acde": begin
|
||||
return def;
|
||||
end
|
||||
else begin
|
||||
a := 1;
|
||||
return a;
|
||||
end
|
||||
end;
|
||||
|
||||
// try
|
||||
try
|
||||
a := 1;
|
||||
except
|
||||
a := 2;
|
||||
end
|
||||
|
||||
// function
|
||||
function foo(a, b, c): real
|
||||
begin
|
||||
end
|
||||
|
||||
function foo(a, b: integer; c: string);
|
||||
begin
|
||||
end;
|
||||
|
||||
function foo(a: boolean; b: integer; c: string): real;
|
||||
begin
|
||||
end
|
||||
|
||||
function foo(a: boolean = true; b: integer = 123);
|
||||
begin
|
||||
end;
|
||||
|
||||
// function pointer
|
||||
pf := function(a, b)
|
||||
begin
|
||||
echo a;
|
||||
end;
|
||||
|
||||
// type
|
||||
type A = class
|
||||
public
|
||||
function create()
|
||||
begin
|
||||
end
|
||||
function foo1(a: real; b: real);virtual;
|
||||
function foo2(a: real; b: real);virtual;
|
||||
begin
|
||||
end
|
||||
function operator[](index);
|
||||
|
||||
property row read readrow;
|
||||
property col read readcol write wirtecol;
|
||||
|
||||
private
|
||||
[weakref]a1: real;
|
||||
static a2: real;
|
||||
a3: tslobj;
|
||||
end;
|
||||
|
||||
function A.create();
|
||||
begin
|
||||
pf := aa;
|
||||
end;
|
||||
|
||||
function operator A.[](index);
|
||||
begin
|
||||
a := 1;
|
||||
end;
|
||||
|
||||
function A.foo1(a: real; b: real);virtual;
|
||||
begin
|
||||
pf := function();
|
||||
begin
|
||||
end
|
||||
end
|
||||
|
||||
// select
|
||||
select * from abc end;
|
||||
select *, ["abc"] from abc end;
|
||||
select *, ["abc"] as "def" from abc end;
|
||||
select * from abc where func(["abc"]) end;
|
||||
select * from abc where ["abc"] > 1 end;
|
||||
R1 := select *,RoundTo((["英语成绩"]+["语文成绩"]+["历史成绩"]+["地理成绩"])/4,2) as "文科成绩" from ScoreList end;
|
||||
return select ['stockid'],['date'],['close']*['vol'] as nil from markettable end;
|
||||
A := select *,ThisOrder as "Order" from A order by ["AAA"] end;
|
||||
B := select * from EnglishScore where ["英语成绩"] > 85 order by ["英语成绩"] end;
|
||||
B := select drange(0 to 9) * from EnglishScore order by ["英语成绩"] desc end;
|
||||
B := select drange(1 of 10) from EnglishScore order by ["英语成绩"] desc end;
|
||||
a := select * from abc where ["abc"] > 1 end;
|
||||
b := select * from abc group by ["abc"] end;
|
||||
c := select * from abc group by func(["acbb"]) end;
|
||||
b := select * from abc group by ["abc"], ["def"] end;
|
||||
e := select * from abc where func(["abc"]) order by ["A"] desc end;
|
||||
select AvgOf(["英语成绩"]) from EnglishScore where ["英语成绩"]>85 end;
|
||||
return select ["性别"],AvgOf(["英语成绩"]),CountOf( * ),groupfunc(["英语成绩"]) from EnglishScore group by ["性别"],groupfunc(["英语成绩"]) end;
|
||||
return select AvgOf(["英语成绩"]), CountOf( * ), groupfunc(["英语成绩"]) from EnglishScore group by groupfunc(["英语成绩"]) having CountOf( * ) >1 end;
|
||||
R := select [1].*,[2].["英语成绩"] from A join B on [1].["学号"]=[2].["学号"] end;
|
||||
R := select [1].*,[2].["英语成绩"] from A cross join B where [1].["学号"]=[2].["学号"] end;
|
||||
R := select [1].*,[2].["英语成绩"] from A, B where [1].["学号"]=[2].["学号"] end;
|
||||
R := select [1].*,[2].["英语成绩"] from A join B with ([1].["学号"] on [2].["学号"]) end;
|
||||
R := select [1].*,[2].["英语成绩"] from A join B with ([1].["学号"],[1].["班级"] on [2].["学号"],[2].["班级"]) end;
|
||||
R := select [1].*,[2].["英语成绩"],[3].["语文成绩"] from A join B on [1].["学号"]=[2].["学号"] join C on [1].["学号"]=[3].["学号"] end;
|
||||
R := select [1].*,[2].["英语成绩"],[3].["俄语成绩"] from A left join B on [1].["学号"]=[2].["学号"] left join C on [1].["学号"]=[3].["学号"] end;
|
||||
R := select [1].["学号"]?:[2].["学号"] as "学号",[1].["英语成绩"],[2].["俄语成绩"] from B full join C on [1].["学号"]=[2].["学号"] end;
|
||||
R1 := select ThisRow from R where ThisRow>5 end;
|
||||
R2 := sselect ThisRow from R where ThisRow>5 end;
|
||||
R2 := vselect SumOf( ["英语成绩"] ) from B end;
|
||||
R1 := select ["性别"],["年龄"], AvgOf(["身高"]), select * from ThisGroup end as "详细信息" from R group by ["性别"],["年龄"] end;
|
||||
|
||||
// update
|
||||
update B set ["英语成绩"] = 79 where ["学号"] = "03" end;
|
||||
update B set ["英语成绩"]=79,["语文成绩"]=80 where ["学号"]="03" end;
|
||||
update children set ['origin_field'] = ['field'] end;
|
||||
update children set ['field'] = uppercase(['prefix']) + ['field'] where not ifnil(['ml']) and ['field'] in fields end;
|
||||
update children set ['new_field'] = format('XmlChild%s', ['field']) end;
|
||||
|
||||
// delete
|
||||
delete from A where ["学号"] = "01";
|
||||
delete from A;
|
||||
|
||||
// insert
|
||||
insert into a values("06","路人甲");
|
||||
insert into a insertfields(["学号"],["姓名"],["英语成绩"]) values("06","路人甲",80);
|
||||
|
||||
// []
|
||||
A[2,3];
|
||||
A[2:5,3:6];
|
||||
A[:,3:6];
|
||||
A[3,:];
|
||||
A[:,"columnName"];
|
||||
A[array(2,4,6)];
|
||||
A[array(2,3),array(1,2)];
|
||||
[a,b,c] := arr;
|
||||
|
||||
// End of example
|
||||
-1548
File diff suppressed because it is too large
Load Diff
-22
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "tree-sitter-tsf",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "bingings/node",
|
||||
"scripts": {
|
||||
"test": "tree-sitter test"
|
||||
},
|
||||
"tree-sitter":
|
||||
[
|
||||
{
|
||||
"scope": "source.tsf",
|
||||
"file-types": ["tsf"]
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"nan": "^2.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tree-sitter-cli": "^0.25.6"
|
||||
}
|
||||
}
|
||||
-364225
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user