♻️ 重构`tree-sitter-tsf`
This commit is contained in:
parent
5eba41429d
commit
7e0b69c354
|
|
@ -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.
File diff suppressed because it is too large
Load Diff
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()
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 +0,0 @@
|
|||
ret := insert into sqltable tableName of FDBAlias data[i:i+999-1];
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue