lihkgcode

TOON (Token-Oriented Object Notation) to indexed array code in Nodejs/python/C/golang.

Nov 8th, 2025
108
0
Never
5
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.04 KB | None | 0 0
  1. TOON (Token-Oriented Object Notation) to indexed array code in Nodejs/python/C/golang.
  2.  
  3. Usage:
  4.  
  5. node toIndexedArray.js "employees[3]{id,name,department}: abc,John Doe,Engineering cdf,Jane Smith,Marketing fgz,Amy Zheng,IT"
  6.  
  7. Output:
  8. [
  9. {
  10. "id": "abc",
  11. "name": "John Doe",
  12. "department": "Engineering"
  13. },
  14. {
  15. "id": "cdf",
  16. "name": "Jane Smith",
  17. "department": "Marketing"
  18. },
  19. {
  20. "id": "fgz",
  21. "name": "Amy Zheng",
  22. "department": "IT"
  23. }
  24. ]
  25.  
  26. Nodejs:
  27.  
  28. // toIndexedArray.js
  29. /**
  30. * Usage:
  31. * node toIndexedArray.js "employees[2]{id,name,dept}: 1,John,IT 2,Jane,HR"
  32. * node toIndexedArray.js "products[3]{code,title,price}: A001,Notebook,59.9 A002,Pen,129 A003,Eraser,15"
  33. *
  34. * Output: pure JSON array (indexed)
  35. */
  36.  
  37. function convertToIndexedArray(input) {
  38. const inputTrim = input.trim();
  39. const colonPos = inputTrim.indexOf(':');
  40. if (colonPos === -1) {
  41. throw new Error('No colon found in input');
  42. }
  43.  
  44. const header = inputTrim.substring(0, colonPos).trim();
  45. let dataString = inputTrim.substring(colonPos + 1).trim();
  46.  
  47. const headerRegex = /^(\w+)\[\d+\]\{([^}]+)\}[::]?$/;
  48. const match = header.match(headerRegex);
  49. if (!match) {
  50. throw new Error('Invalid header format. Use: name[N]{field1,field2,...}');
  51. }
  52.  
  53. const arrayName = match[1]; // Not used, but parsed for completeness
  54. const fields = match[2].split(',').map(f => f.trim());
  55.  
  56. // Parse expected count from [N]
  57. const countMatch = header.match(/\[(\d+)\]/);
  58. const expectedCount = countMatch ? parseInt(countMatch[1], 10) : null;
  59.  
  60. const firstFieldIsId = fields[0].toLowerCase() === 'id' || fields[0].toLowerCase().endsWith('id');
  61.  
  62. let dataLines = [];
  63.  
  64. if (dataString.includes('\n')) {
  65. // Multi-line mode
  66. dataLines = dataString.split('\n').map(l => l.trim()).filter(Boolean);
  67. } else {
  68. // Single-line mode
  69. const tokens = dataString.split(/\s+/).filter(t => t);
  70. dataLines = [];
  71. let i = 0;
  72. const numCommasNeeded = fields.length - 1;
  73. while (i < tokens.length) {
  74. let current = [tokens[i]];
  75. let currentStr = current[0];
  76. let commaCount = (currentStr.match(/,/g) || []).length;
  77. i++;
  78. while (commaCount < numCommasNeeded && i < tokens.length) {
  79. const nextToken = tokens[i];
  80. const tempStr = currentStr + ' ' + nextToken;
  81. const tempCount = (tempStr.match(/,/g) || []).length;
  82. if (tempCount > numCommasNeeded) {
  83. throw new Error(`Too many commas in row starting at ${current[0]}`);
  84. }
  85. current.push(nextToken);
  86. currentStr = tempStr;
  87. commaCount = tempCount;
  88. i++;
  89. }
  90. if (commaCount < numCommasNeeded) {
  91. throw new Error('Incomplete row');
  92. }
  93. // Add extra parts for last field if no comma in them
  94. while (i < tokens.length && !tokens[i].includes(',')) {
  95. const nextToken = tokens[i];
  96. current.push(nextToken);
  97. currentStr = currentStr + ' ' + nextToken;
  98. i++;
  99. }
  100. dataLines.push(currentStr);
  101. }
  102. }
  103.  
  104. if (dataLines.length === 0) {
  105. throw new Error('No data rows found');
  106. }
  107.  
  108. if (expectedCount !== null && dataLines.length !== expectedCount) {
  109. throw new Error(`Expected ${expectedCount} rows, but found ${dataLines.length}`);
  110. }
  111.  
  112. const result = [];
  113.  
  114. for (let i = 0; i < dataLines.length; i++) {
  115. const line = dataLines[i];
  116. const values = line.split(',').map(v => v.trim());
  117. if (values.length !== fields.length) {
  118. throw new Error(`Row ${i + 1} has ${values.length} values, but ${fields.length} fields are expected.`);
  119. }
  120.  
  121. const obj = {};
  122. fields.forEach((field, idx) => {
  123. let value = values[idx];
  124. // Auto-convert "id" or fields ending with "Id" to number
  125. if (field.toLowerCase() === 'id' || field.toLowerCase().endsWith('id')) {
  126. const num = parseInt(value, 10);
  127. if (!isNaN(num)) value = num;
  128. }
  129. // Add more conversions if needed (e.g., parseFloat for 'price')
  130. obj[field] = value;
  131. });
  132. result.push(obj);
  133. }
  134.  
  135. return result;
  136. }
  137.  
  138. // Main
  139. if (process.argv.length < 3) {
  140. console.error('Usage: node toIndexedArray.js "your-text-here"');
  141. console.error('Example:');
  142. console.error(' node toIndexedArray.js "employees[2]{id,name,dept}: 1,Alice,IT 2,Bob,HR"');
  143. process.exit(1);
  144. }
  145.  
  146. const inputText = process.argv.slice(2).join(' ');
  147. try {
  148. const array = convertToIndexedArray(inputText);
  149. console.log(JSON.stringify(array, null, 2));
  150. } catch (err) {
  151. console.error('Error:', err.message);
  152. process.exit(1);
  153. }
  154.  
  155. Python:
  156.  
  157. # to_indexed_array.py
  158. import sys
  159. import re
  160. import json
  161.  
  162. def convert_to_indexed_array(input_str):
  163. input_trim = input_str.strip()
  164. colon_pos = input_trim.find(':')
  165. if colon_pos == -1:
  166. raise ValueError('No colon found in input')
  167.  
  168. header = input_trim[:colon_pos].strip()
  169. data_string = input_trim[colon_pos + 1:].strip()
  170.  
  171. header_regex = r'^(\w+)\[\d+\]\{([^}]+)\}[::]?$'
  172. match = re.match(header_regex, header)
  173. if not match:
  174. raise ValueError('Invalid header format. Use: name[N]{field1,field2,...}')
  175.  
  176. array_name = match.group(1) # Not used
  177. fields = [f.strip() for f in match.group(2).split(',')]
  178.  
  179. count_match = re.search(r'\[(\d+)\]', header)
  180. expected_count = int(count_match.group(1)) if count_match else None
  181.  
  182. first_field_is_id = fields[0].lower() == 'id' or fields[0].lower().endswith('id')
  183.  
  184. data_lines = []
  185.  
  186. if '\n' in data_string:
  187. # Multi-line mode
  188. data_lines = [l.strip() for l in data_string.split('\n') if l.strip()]
  189. else:
  190. # Single-line mode
  191. tokens = re.split(r'\s+', data_string)
  192. tokens = [t for t in tokens if t]
  193. i = 0
  194. num_commas_needed = len(fields) - 1
  195. while i < len(tokens):
  196. current = [tokens[i]]
  197. current_str = current[0]
  198. comma_count = current_str.count(',')
  199. i += 1
  200. while comma_count < num_commas_needed and i < len(tokens):
  201. next_token = tokens[i]
  202. temp_str = current_str + ' ' + next_token
  203. temp_count = temp_str.count(',')
  204. if temp_count > num_commas_needed:
  205. raise ValueError(f'Too many commas in row starting at {current[0]}')
  206. current.append(next_token)
  207. current_str = temp_str
  208. comma_count = temp_count
  209. i += 1
  210. if comma_count < num_commas_needed:
  211. raise ValueError('Incomplete row')
  212. # Add extra parts for last field if no comma in them
  213. while i < len(tokens) and ',' not in tokens[i]:
  214. next_token = tokens[i]
  215. current.append(next_token)
  216. current_str += ' ' + next_token
  217. i += 1
  218. data_lines.append(current_str)
  219.  
  220. if not data_lines:
  221. raise ValueError('No data rows found')
  222.  
  223. if expected_count is not None and len(data_lines) != expected_count:
  224. raise ValueError(f'Expected {expected_count} rows, but found {len(data_lines)}')
  225.  
  226. result = []
  227.  
  228. for idx, line in enumerate(data_lines):
  229. values = [v.strip() for v in line.split(',')]
  230. if len(values) != len(fields):
  231. raise ValueError(f'Row {idx + 1} has {len(values)} values, but {len(fields)} fields are expected.')
  232.  
  233. obj = {}
  234. for field, value in zip(fields, values):
  235. if field.lower() == 'id' or field.lower().endswith('id'):
  236. try:
  237. obj[field] = int(value)
  238. except ValueError:
  239. obj[field] = value
  240. else:
  241. obj[field] = value
  242. result.append(obj)
  243.  
  244. return result
  245.  
  246. if __name__ == "__main__":
  247. if len(sys.argv) < 2:
  248. print('Usage: python to_indexed_array.py "your-text-here"')
  249. print('Example:')
  250. print(' python to_indexed_array.py "employees[2]{id,name,dept}: 1,Alice,IT 2,Bob,HR"')
  251. sys.exit(1)
  252.  
  253. input_text = ' '.join(sys.argv[1:])
  254. try:
  255. array = convert_to_indexed_array(input_text)
  256. print(json.dumps(array, indent=2, ensure_ascii=False))
  257. except ValueError as err:
  258. print('Error:', err)
  259. sys.exit(1)
  260.  
  261. C:
  262.  
  263. // to_indexed_array.c
  264. #include <stdio.h>
  265. #include <stdlib.h>
  266. #include <string.h>
  267. #include <ctype.h>
  268. #include <regex.h>
  269.  
  270. // Function to trim whitespace
  271. char* trim(char* str) {
  272. char* end;
  273. while (isspace((unsigned char)*str)) str++;
  274. if (*str == 0) return str;
  275. end = str + strlen(str) - 1;
  276. while (end > str && isspace((unsigned char)*end)) end--;
  277. end[1] = '\0';
  278. return str;
  279. }
  280.  
  281. // Function to split string by delimiter
  282. int split(const char* str, char delim, char*** tokens) {
  283. int count = 0;
  284. char* temp = strdup(str);
  285. char* token = strtok(temp, &delim);
  286. while (token) {
  287. count++;
  288. token = strtok(NULL, &delim);
  289. }
  290. free(temp);
  291.  
  292. *tokens = malloc(sizeof(char*) * count);
  293. temp = strdup(str);
  294. token = strtok(temp, &delim);
  295. int i = 0;
  296. while (token) {
  297. (*tokens)[i] = strdup(trim(token));
  298. token = strtok(NULL, &delim);
  299. i++;
  300. }
  301. free(temp);
  302. return count;
  303. }
  304.  
  305. int main(int argc, char* argv[]) {
  306. if (argc < 2) {
  307. fprintf(stderr, "Usage: %s \"your-text-here\"\n", argv[0]);
  308. fprintf(stderr, "Example:\n");
  309. fprintf(stderr, " %s \"employees[2]{id,name,dept}: 1,Alice,IT 2,Bob,HR\"\n", argv[0]);
  310. return 1;
  311. }
  312.  
  313. // Join all arguments into one string
  314. size_t len = 0;
  315. for (int i = 1; i < argc; i++) len += strlen(argv[i]) + 1;
  316. char* input_text = malloc(len);
  317. input_text[0] = '\0';
  318. for (int i = 1; i < argc; i++) {
  319. strcat(input_text, argv[i]);
  320. if (i < argc - 1) strcat(input_text, " ");
  321. }
  322.  
  323. char* input_trim = trim(input_text);
  324. char* colon_pos = strchr(input_trim, ':');
  325. if (!colon_pos) {
  326. fprintf(stderr, "Error: No colon found in input\n");
  327. free(input_text);
  328. return 1;
  329. }
  330.  
  331. *colon_pos = '\0';
  332. char* header = trim(input_trim);
  333. char* data_string = trim(colon_pos + 1);
  334.  
  335. regex_t regex;
  336. regmatch_t matches[3];
  337. int reti = regcomp(&regex, "^(\\w+)\\[(\\d+)\\]\\{([^}]+)\\}[::]?$", REG_EXTENDED);
  338. if (reti) {
  339. fprintf(stderr, "Could not compile regex\n");
  340. free(input_text);
  341. return 1;
  342. }
  343.  
  344. reti = regexec(&regex, header, 3, matches, 0);
  345. if (reti) {
  346. fprintf(stderr, "Error: Invalid header format. Use: name[N]{field1,field2,...}\n");
  347. regfree(&regex);
  348. free(input_text);
  349. return 1;
  350. }
  351.  
  352. char* array_name = strndup(header + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
  353. char count_str[10];
  354. strncpy(count_str, header + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
  355. count_str[matches[2].rm_eo - matches[2].rm_so] = '\0';
  356. int expected_count = atoi(count_str);
  357.  
  358. char* fields_str = strndup(header + matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so);
  359. char** fields;
  360. int num_fields = split(fields_str, ',', &fields);
  361. regfree(&regex);
  362. free(fields_str);
  363. free(array_name);
  364.  
  365. int first_field_is_id = (strcasecmp(fields[0], "id") == 0 || strncasecmp(fields[0] + strlen(fields[0]) - 2, "id", 2) == 0);
  366.  
  367. char** data_lines = NULL;
  368. int num_lines = 0;
  369.  
  370. char* newline_pos = strchr(data_string, '\n');
  371. if (newline_pos) {
  372. // Multi-line
  373. char** lines;
  374. num_lines = split(data_string, '\n', &lines);
  375. data_lines = malloc(sizeof(char*) * num_lines);
  376. for (int i = 0; i < num_lines; i++) {
  377. char* trimmed = trim(lines[i]);
  378. if (strlen(trimmed) > 0) {
  379. data_lines[num_lines++] = strdup(trimmed);
  380. }
  381. free(lines[i]);
  382. }
  383. free(lines);
  384. } else {
  385. // Single-line
  386. char** tokens;
  387. int num_tokens = split(data_string, ' ', &tokens);
  388. int i = 0;
  389. int num_commas_needed = num_fields - 1;
  390. while (i < num_tokens) {
  391. char* current = strdup(tokens[i]);
  392. int comma_count = 0;
  393. for (char* p = current; *p; p++) if (*p == ',') comma_count++;
  394. i++;
  395. while (comma_count < num_commas_needed && i < num_tokens) {
  396. char* temp = malloc(strlen(current) + strlen(tokens[i]) + 2);
  397. sprintf(temp, "%s %s", current, tokens[i]);
  398. free(current);
  399. current = temp;
  400. comma_count = 0;
  401. for (char* p = current; *p; p++) if (*p == ',') comma_count++;
  402. i++;
  403. }
  404. if (comma_count < num_commas_needed) {
  405. fprintf(stderr, "Error: Incomplete row\n");
  406. // Free memory
  407. for (int j = 0; j < num_tokens; j++) free(tokens[j]);
  408. free(tokens);
  409. for (int j = 0; j < num_fields; j++) free(fields[j]);
  410. free(fields);
  411. free(input_text);
  412. return 1;
  413. }
  414. while (i < num_tokens && strchr(tokens[i], ',') == NULL) {
  415. char* temp = malloc(strlen(current) + strlen(tokens[i]) + 2);
  416. sprintf(temp, "%s %s", current, tokens[i]);
  417. free(current);
  418. current = temp;
  419. i++;
  420. }
  421. data_lines = realloc(data_lines, sizeof(char*) * (num_lines + 1));
  422. data_lines[num_lines++] = current;
  423. }
  424. for (int j = 0; j < num_tokens; j++) free(tokens[j]);
  425. free(tokens);
  426. }
  427.  
  428. if (num_lines == 0) {
  429. fprintf(stderr, "Error: No data rows found\n");
  430. // Free memory
  431. for (int j = 0; j < num_fields; j++) free(fields[j]);
  432. free(fields);
  433. free(input_text);
  434. return 1;
  435. }
  436.  
  437. if (expected_count && num_lines != expected_count) {
  438. fprintf(stderr, "Error: Expected %d rows, but found %d\n", expected_count, num_lines);
  439. // Free memory
  440. for (int j = 0; j < num_lines; j++) free(data_lines[j]);
  441. free(data_lines);
  442. for (int j = 0; j < num_fields; j++) free(fields[j]);
  443. free(fields);
  444. free(input_text);
  445. return 1;
  446. }
  447.  
  448. // Output JSON
  449. printf("[\n");
  450. for (int i = 0; i < num_lines; i++) {
  451. char** values;
  452. int num_values = split(data_lines[i], ',', &values);
  453. if (num_values != num_fields) {
  454. fprintf(stderr, "Error: Row %d has %d values, but %d fields are expected.\n", i + 1, num_values, num_fields);
  455. // Free memory
  456. for (int j = 0; j < num_values; j++) free(values[j]);
  457. free(values);
  458. for (int j = 0; j < num_lines; j++) free(data_lines[j]);
  459. free(data_lines);
  460. for (int j = 0; j < num_fields; j++) free(fields[j]);
  461. free(fields);
  462. free(input_text);
  463. return 1;
  464. }
  465.  
  466. printf(" {\n");
  467. for (int j = 0; j < num_fields; j++) {
  468. char* value = values[j];
  469. int is_number = 0;
  470. if (strcasecmp(fields[j], "id") == 0 || strncasecmp(fields[j] + strlen(fields[j]) - 2, "id", 2) == 0) {
  471. char* endptr;
  472. strtol(value, &endptr, 10);
  473. if (*endptr == '\0') is_number = 1;
  474. }
  475. printf(" \"%s\": ", fields[j]);
  476. if (is_number) {
  477. printf("%s", value);
  478. } else {
  479. printf("\"%s\"", value);
  480. }
  481. if (j < num_fields - 1) printf(",");
  482. printf("\n");
  483. free(values[j]);
  484. }
  485. free(values);
  486. printf(" }");
  487. if (i < num_lines - 1) printf(",");
  488. printf("\n");
  489. free(data_lines[i]);
  490. }
  491. printf("]\n");
  492.  
  493. free(data_lines);
  494. for (int j = 0; j < num_fields; j++) free(fields[j]);
  495. free(fields);
  496. free(input_text);
  497. return 0;
  498. }
  499.  
  500. Golang:
  501.  
  502. // to_indexed_array.go
  503. package main
  504.  
  505. import (
  506. "fmt"
  507. "os"
  508. "regexp"
  509. "strconv"
  510. "strings"
  511. )
  512.  
  513. func convertToIndexedArray(input string) ([]map[string]interface{}, error) {
  514. inputTrim := strings.TrimSpace(input)
  515. colonPos := strings.Index(inputTrim, ":")
  516. if colonPos == -1 {
  517. return nil, fmt.Errorf("no colon found in input")
  518. }
  519.  
  520. header := strings.TrimSpace(inputTrim[:colonPos])
  521. dataString := strings.TrimSpace(inputTrim[colonPos+1:])
  522.  
  523. headerRegex := regexp.MustCompile(`^(\w+)\[\d+\]\{([^}]+)\}[::]?$`)
  524. match := headerRegex.FindStringSubmatch(header)
  525. if match == nil {
  526. return nil, fmt.Errorf("invalid header format. Use: name[N]{field1,field2,...}")
  527. }
  528.  
  529. // arrayName := match[1] // Not used
  530. fields := strings.Split(match[2], ",")
  531. for i := range fields {
  532. fields[i] = strings.TrimSpace(fields[i])
  533. }
  534.  
  535. countRegex := regexp.MustCompile(`\[(\d+)\]`)
  536. countMatch := countRegex.FindStringSubmatch(header)
  537. var expectedCount *int
  538. if countMatch != nil {
  539. count, _ := strconv.Atoi(countMatch[1])
  540. expectedCount = &count
  541. }
  542.  
  543. firstFieldIsID := strings.ToLower(fields[0]) == "id" || strings.HasSuffix(strings.ToLower(fields[0]), "id")
  544.  
  545. var dataLines []string
  546.  
  547. if strings.Contains(dataString, "\n") {
  548. // Multi-line mode
  549. lines := strings.Split(dataString, "\n")
  550. for _, l := range lines {
  551. trimmed := strings.TrimSpace(l)
  552. if trimmed != "" {
  553. dataLines = append(dataLines, trimmed)
  554. }
  555. }
  556. } else {
  557. // Single-line mode
  558. tokens := strings.Fields(dataString)
  559. i := 0
  560. numCommasNeeded := len(fields) - 1
  561. for i < len(tokens) {
  562. current := []string{tokens[i]}
  563. currentStr := current[0]
  564. commaCount := strings.Count(currentStr, ",")
  565. i++
  566. for commaCount < numCommasNeeded && i < len(tokens) {
  567. nextToken := tokens[i]
  568. tempStr := currentStr + " " + nextToken
  569. tempCount := strings.Count(tempStr, ",")
  570. if tempCount > numCommasNeeded {
  571. return nil, fmt.Errorf("too many commas in row starting at %s", current[0])
  572. }
  573. current = append(current, nextToken)
  574. currentStr = tempStr
  575. commaCount = tempCount
  576. i++
  577. }
  578. if commaCount < numCommasNeeded {
  579. return nil, fmt.Errorf("incomplete row")
  580. }
  581. // Add extra parts for last field if no comma in them
  582. for i < len(tokens) && !strings.Contains(tokens[i], ",") {
  583. nextToken := tokens[i]
  584. current = append(current, nextToken)
  585. currentStr += " " + nextToken
  586. i++
  587. }
  588. dataLines = append(dataLines, currentStr)
  589. }
  590. }
  591.  
  592. if len(dataLines) == 0 {
  593. return nil, fmt.Errorf("no data rows found")
  594. }
  595.  
  596. if expectedCount != nil && len(dataLines) != *expectedCount {
  597. return nil, fmt.Errorf("expected %d rows, but found %d", *expectedCount, len(dataLines))
  598. }
  599.  
  600. result := []map[string]interface{}{}
  601.  
  602. for idx, line := range dataLines {
  603. values := strings.Split(line, ",")
  604. for j := range values {
  605. values[j] = strings.TrimSpace(values[j])
  606. }
  607. if len(values) != len(fields) {
  608. return nil, fmt.Errorf("row %d has %d values, but %d fields are expected", idx+1, len(values), len(fields))
  609. }
  610.  
  611. obj := map[string]interface{}{}
  612. for j, field := range fields {
  613. value := values[j]
  614. if strings.ToLower(field) == "id" || strings.HasSuffix(strings.ToLower(field), "id") {
  615. if num, err := strconv.Atoi(value); err == nil {
  616. obj[field] = num
  617. continue
  618. }
  619. }
  620. obj[field] = value
  621. }
  622. result = append(result, obj)
  623. }
  624.  
  625. return result, nil
  626. }
  627.  
  628. func main() {
  629. if len(os.Args) < 2 {
  630. fmt.Printf("Usage: %s \"your-text-here\"\n", os.Args[0])
  631. fmt.Println("Example:")
  632. fmt.Printf(" %s \"employees[2]{id,name,dept}: 1,Alice,IT 2,Bob,HR\"\n", os.Args[0])
  633. os.Exit(1)
  634. }
  635.  
  636. inputText := strings.Join(os.Args[1:], " ")
  637. array, err := convertToIndexedArray(inputText)
  638. if err != nil {
  639. fmt.Println("Error:", err)
  640. os.Exit(1)
  641. }
  642.  
  643. jsonBytes, err := json.MarshalIndent(array, "", " ")
  644. if err != nil {
  645. fmt.Println("Error marshaling JSON:", err)
  646. os.Exit(1)
  647. }
  648. fmt.Println(string(jsonBytes))
  649. }
  650.  
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
Add Comment
Please, Sign In to add comment