Statement Parser

【使用前先看介绍/有问题可反馈】声明解析器 (Statement Parser):通过语言,类型,变量名,以及赋值,直接生成可被解析的声明语句。

当前为 2021-09-15 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Statement Parser
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.1
  5. // @description 【使用前先看介绍/有问题可反馈】声明解析器 (Statement Parser):通过语言,类型,变量名,以及赋值,直接生成可被解析的声明语句。
  6. // @author cc
  7. // @include *
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. const __VERSION__ = '1.0.1';
  13. class StatementParser {
  14. static __VERSION__ = __VERSION__;
  15. static #conf = {
  16. 'Java': {
  17. lang: 'Java',
  18. baseType: ['boolean', 'byte', 'char', 'short', 'int', 'long', 'long', 'float', 'double', 'String'],
  19. extendType: [/^ListNode$/],
  20. useArray: true,
  21. arrayBrackets: '{}',
  22. squareBracketsPostPosition: false,
  23. usePointer: false,
  24. useGenerics: true,
  25. useNew: true,
  26. accessProperty: '.',
  27. nullValue: 'null',
  28. classStructSlice: [2, -1],
  29. commentChar: '*',
  30. endsWithSemicolon: true,
  31. typePostPosition: false,
  32. useTypeDeclare: true,
  33. ignoreThisArg: false,
  34. declareTemplate: /public\s+[\w<>]+\s+\w+\(\s*(.+?)\s*\)/,
  35. template: /^(.+)\s+(\w+)$/,
  36. },
  37. 'C++': {
  38. lang: 'C++',
  39. baseType: ['void', 'bool', 'char', 'short', 'int', 'long', 'float', 'double', 'string'],
  40. extendType: [/^ListNode\*$/, /^vector<(.+)>$/],
  41. useArray: false,
  42. arrayBrackets: '{}',
  43. squareBracketsPostPosition: true,
  44. usePointer: true,
  45. useGenerics: true,
  46. useNew: true,
  47. accessProperty: '->',
  48. nullValue: 'NULL',
  49. classStructSlice: [2, -1],
  50. commentChar: '*',
  51. endsWithSemicolon: true,
  52. typePostPosition: false,
  53. useTypeDeclare: true,
  54. ignoreThisArg: false,
  55. declareTemplate: /public:\s+[\w<>*]+\s*[&*]?\s*\w+\(\s*(.+?)\s*\)/,
  56. template: /^(.+?\s*?\*?)&?\s*(\w+)$/,
  57. },
  58. 'Python3': {
  59. lang: 'Python3',
  60. baseType: ['bool', 'int', 'float', 'str'],
  61. extendType: [/^List\[(.+)]$/, /^ListNode$/],
  62. useArray: false,
  63. arrayBrackets: '[]',
  64. squareBracketsPostPosition: true,
  65. usePointer: false,
  66. useGenerics: true,
  67. useNew: false,
  68. accessProperty: '.',
  69. nullValue: 'None',
  70. classStructSlice: [1, 0],
  71. commentChar: '#',
  72. endsWithSemicolon: false,
  73. typePostPosition: true,
  74. useTypeDeclare: false,
  75. ignoreThisArg: true,
  76. declareTemplate: /Solution:\s+def\s+\w+\((.+?)\)/,
  77. template: /^(.+?\s*?\*?)&?\s*(\w+)$/,
  78. },
  79. };
  80. #support;
  81. #config;
  82.  
  83. /**
  84. * 通过语言类型指定语句解析器
  85. * @param lang {string} 编程语言
  86. */
  87. constructor(lang) {
  88. if (lang in StatementParser.#conf) {
  89. this.#support = true;
  90. this.#config = StatementParser.#conf[lang];
  91. } else {
  92. this.#support = false;
  93. }
  94. }
  95.  
  96. /**
  97. * 通过代码和输入直接获得对应声明语句
  98. * @param declares {array[array[string]]} 声明类型及变量名的数组
  99. * @param expressions {string} 声明表达式数组
  100. */
  101. getStatementsFromDeclaresAndExpressions(declares, expressions) {
  102. let statementCount = declares.length;
  103. let statements = [];
  104. for (let i = 0; i < statementCount; ++i) {
  105. let value = this.parseExpression(expressions[i]);
  106. let [type, name] = declares[i];
  107. statements.push(this.getStatement(type, name, value));
  108. }
  109. return statements.join('\n');
  110. }
  111.  
  112. /**
  113. * 从代码中获取参数声明
  114. * @param code {string} 代码字符串
  115. * @returns {array[string]} 变量声明数组,每个元素为 [类型, 变量名]
  116. */
  117. getDeclaresFromCode(code) {
  118. code = code.replace(/\n/g, '');
  119. let pattern = this.#config.declareTemplate;
  120. let rawDeclares = code.match(pattern)[1];
  121. let declares = rawDeclares.replace(/\s+([&*])\s*/g, '$1 ').split(/\s*,\s*/);
  122. if (this.#config.ignoreThisArg)
  123. declares = declares.slice(1);
  124. declares = declares.map(pair => pair.split(/:?\s+/));
  125. if (this.#config.typePostPosition)
  126. declares = declares.map(pair => [pair[1], pair[0]]);
  127. declares.forEach(pair => {
  128. pair[0] = pair[0].replace(/&$/, '');
  129. });
  130. return declares;
  131. }
  132.  
  133. /**
  134. * 通过类型,变量名,以及字面值,生成赋值表达式
  135. * @param type {string} 类型
  136. * @param name {string} 变量名
  137. * @param value {string} 字面值
  138. * @returns {string} 可被解析的赋值表达式
  139. */
  140. getStatement(type, name, value) {
  141. let useTypeDeclare = this.#config.useTypeDeclare;
  142. let endsWithSemicolon = this.#config.endsWithSemicolon;
  143. let strOfDeclare = this.#config.useTypeDeclare ? `${type} ` : '';
  144. let strOfEnd = this.#config.endsWithSemicolon ? ';' : '';
  145. let [belongsBaseType, baseType, dimension] = this.resolveType(type);
  146. if (belongsBaseType) {
  147. value = this.parseValue(baseType, value, dimension)[0];
  148. return `${strOfDeclare}${name} = ${value}${strOfEnd}`;
  149. } else {
  150. let pattern = this.#findExtendType(type);
  151. if (pattern && pattern.toString().includes('ListNode')) {
  152. let array = value.match(/\d+/g).map(e => parseInt(e));
  153. return this.#makeListNode(name, array);
  154. } else if (pattern && pattern.toString().includes('vector')) {
  155. let elementType = type.match(pattern)[1];
  156. return this.#makeVector(name, elementType, value);
  157. } else if (pattern && pattern.toString().match(/List\\\[.+]/)) {
  158. let elementType = type.match(pattern)[1];
  159. return this.#makeList(name, elementType, value);
  160. }
  161. }
  162. return `${type} ${name}; // cannot resolve this type`;
  163. }
  164.  
  165. /**
  166. * 从代码中获取注释结构类声明代码
  167. * @param code {string} 代码字符串
  168. * @returns {string|null} 结构类声明代码,不存在则返回 null
  169. */
  170. getClassStructFromCode(code) {
  171. let commentChar = this.#config.commentChar;
  172. let [start, end] = this.#config.classStructSlice;
  173. let prefixPattern = new RegExp(`^\\s*${commentChar === '*' ? '\\*' : commentChar}\\s`);
  174. if (commentChar === '*') {
  175. let [matchLeft, matchRight] = [code.match(/\/\*\*/), code.match(/\*\//)];
  176. if (!matchLeft || !matchRight)
  177. return null;
  178. let [commentStart, commentEnd] = [matchLeft.index, matchRight.index + 2];
  179. let structComment = code.slice(commentStart, commentEnd).split('\n');
  180. structComment = structComment.slice(start, structComment.length + end);
  181. return structComment.map(line => line.replace(prefixPattern, '')).join('\n');
  182. } else if (commentChar === '#') {
  183. let leftIndex = /#/m.exec(code).index;
  184. let rightIndex = /\n[^#]/m.exec(code).index + 1;
  185. let structComment = code.slice(leftIndex, rightIndex).split('\n');
  186. structComment = structComment.slice(start, structComment.length + end);
  187. return structComment.map(line => line.replace(prefixPattern, '')).join('\n').trim();
  188. }
  189. }
  190.  
  191. /**
  192. * 解析赋值表达式中的被赋予的字面值,无回车无前后空格无末尾逗号
  193. * @param expression 表达式,形式为 "name = value"
  194. * @returns {string} 表达式中被赋予的字面值
  195. */
  196. parseExpression(expression) {
  197. let value;
  198. expression = expression.trim().replace(/,$/, '');
  199. if (expression.includes('=')) {
  200. value = expression.split(/\s*=\s*/)[1];
  201. } else {
  202. value = expression;
  203. }
  204. value = value.replace(/\n/g, '');
  205. return value;
  206. }
  207.  
  208. /**
  209. * 分析被赋予的字面值
  210. * @param baseType {string} 基本类型
  211. * @param value {string} 被赋予的字面值
  212. * @param dimension {number} 类型维度
  213. * @returns {array[string|any]} 处理后的可解析的可被赋予的值
  214. */
  215. parseValue(baseType, value, dimension) {
  216. let brackets = this.#config.arrayBrackets.split('');
  217. let extractElementsPattern = /^\[\s*(.+?)\s*]$/;
  218. let extractStringsPattern = /(".*?")/g;
  219. let CommaTrimPattern = /\s*,\s*/g;
  220. if (dimension === 0) {
  221. if (baseType === 'char') {
  222. if (value.match(/"."/)) {
  223. value = value.replace(/"/g, '\'');
  224. } else if (value.match(/^.$/)) {
  225. value = `'${value}'`;
  226. }
  227. }
  228. return [value, value];
  229. } else if (dimension === 1) {
  230. if (baseType.toLowerCase() === 'string' || baseType === 'str') {
  231. let elements = value.match(extractStringsPattern);
  232. let elementsStr = elements.join(', ');
  233. value = `${brackets[0]}${elementsStr}${brackets[1]}`;
  234. return [value, elements];
  235. } else {
  236. let rawElementsStr = value.match(extractElementsPattern)[1];
  237. let elements = rawElementsStr.split(/\s*,\s*/);
  238. let elementsStr = elements.join(', ');
  239. if (baseType === 'char')
  240. elementsStr = elementsStr.replace(/"/g, '\'');
  241. value = `${brackets[0]}${elementsStr}${brackets[1]}`;
  242. return [value, elements];
  243. }
  244. } else if (dimension === 2) {
  245. if (baseType.toLowerCase() === 'string' || baseType === 'str') {
  246. let strMatrix = StatementParser.#parseStringMatrix(value, '[]');
  247. value = `${brackets[0]}\n\t${strMatrix.map(strArray => {
  248. return `${brackets[0]}${strArray.join(', ')}${brackets[1]}`;
  249. }).join('\n\t')}\n${brackets[1]}`;
  250. return [value, strMatrix];
  251. } else {
  252. let arraysStr = value.match(extractElementsPattern)[1];
  253. let arraysStrFmt = arraysStr.replace(/\s+/g, '').replace(/(],)/g, '$1 ');
  254. let arrayStrs = arraysStrFmt.split(/,\s+/);
  255. let arrayStrFmts = arrayStrs.map(arrayStr => {
  256. let elementsStr = arrayStr.match(extractElementsPattern)[1];
  257. if (baseType === 'char')
  258. elementsStr = elementsStr.replace(/"/g, '\'');
  259. return `${brackets[0]}${elementsStr.replace(/,/g, ', ')}${brackets[1]}`;
  260. });
  261. let realValue = arrayStrs.map(arrayStr => {
  262. let elementsStr = arrayStr.match(extractElementsPattern)[1];
  263. return elementsStr.split(',');
  264. });
  265. value = `${brackets[0]}\n\t${arrayStrFmts.join(',\n\t')}\n${brackets[1]}`;
  266. return [value, realValue];
  267. }
  268. }
  269. return [value, value];
  270. }
  271.  
  272. /**
  273. * 解析类型,检查是否属于基础类型,以及分析类型的维度
  274. * @param type {string} 类型
  275. * @returns {[boolean, string, number]} 是否属于基本类型,解析后的基本类型,类型维度
  276. */
  277. resolveType(type) {
  278. let dimension = 0;
  279. if (type.endsWith('[][]')) {
  280. type = type.slice(0, type.length - 4);
  281. dimension = 2;
  282. } else if (type.endsWith('[]')) {
  283. type = type.slice(0, type.length - 2);
  284. dimension = 1;
  285. }
  286. let isBaseType = !!this.#findBaseType(type);
  287. return [isBaseType, type, dimension];
  288. }
  289.  
  290. /**
  291. * 判断类型是否在基本类型中,并返回匹配到的基本类型,匹配失败返回 null
  292. * @param type {string} 类型
  293. * @returns {string|null} 匹配到的基本类型,或 null
  294. */
  295. #findBaseType(type) {
  296. let index = this.#config.baseType.indexOf(type);
  297. if (index < 0)
  298. return null;
  299. return this.#config.baseType[index];
  300. }
  301.  
  302. /**
  303. * 判断类型是否在扩展类型中,并返回匹配到的扩展类型,匹配失败返回 null
  304. * @param type {string} 类型
  305. * @returns {RegExp|null} 匹配到的扩展类型,或 null
  306. */
  307. #findExtendType(type) {
  308. for (let pattern of this.#config.extendType)
  309. if (type.match(pattern))
  310. return pattern;
  311. return null;
  312. }
  313.  
  314. /**
  315. * 通过链表元素生成链表声明语句
  316. * @param name {string} 变量名
  317. * @param array {array[number]} 链表的所有元素
  318. * @returns {string} 链表声明语句集合的字符串
  319. */
  320. #makeListNode(name, array) {
  321. let strOfPtr = this.#config.usePointer ? '*' : '';
  322. let strOfDeclare = this.#config.useTypeDeclare ? `ListNode${strOfPtr} ` : '';
  323. let strOfNew = this.#config.useNew ? 'new ' : '';
  324. let strOfNullValue = this.#config.nullValue;
  325. let strOfNext = this.#config.accessProperty;
  326. let strOfEnd = this.#config.endsWithSemicolon ? ';' : '';
  327. if (array.length === 0)
  328. return `${strOfDeclare}${name} = ${strOfNullValue}${strOfEnd}`;
  329. let statementList = [`${strOfDeclare}${name} = ${strOfNew}ListNode(${array[0]})${strOfEnd}`];
  330. if (array.length === 1)
  331. return statementList[0];
  332. statementList.push(`${strOfDeclare}${name}Next = ${name}${strOfEnd}`);
  333. for (let i = 1; i < array.length; ++i) {
  334. statementList.push(`${name}Next${strOfNext}next = ${strOfNew}ListNode(${array[i]})${strOfEnd}`);
  335. if (i + 1 < array.length)
  336. statementList.push(`${name}Next = ${name}Next${strOfNext}next${strOfEnd}`);
  337. }
  338. return statementList.join('\n');
  339. }
  340.  
  341. /**
  342. * 通过变量名,元素类型,以及字面值生成 vector 的赋值表达式
  343. * @param name {string} vector 变量名
  344. * @param elementType {string} 元素类型
  345. * @param value {string} 已处理的被赋值字面值
  346. * @returns {string} 可被解析的赋值表达式
  347. */
  348. #makeVector(name, elementType, value) {
  349. if (this.#findBaseType(elementType)) {
  350. // vector<baseType>
  351. let [formatValue, realValue] = this.parseValue(elementType, value, 1);
  352. return `vector<${elementType}> ${name} ${formatValue};`;
  353. } else {
  354. // vector<...>
  355. let pattern = this.#findExtendType(elementType);
  356. if (pattern && pattern.toString().includes('vector')) {
  357. // vector<vector<...>>
  358. let baseType = elementType.match(pattern)[1];
  359. if (this.#findBaseType(baseType)) {
  360. // vector<vector<baseType>>
  361. let [formatValue, matrix] = this.parseValue(baseType, value, 2);
  362. let [row, col] = [matrix.length, matrix[0].length];
  363. let statements = [
  364. `vector<vector<${baseType}>> ${name};`,
  365. `${baseType} ${name}Matrix[${row}][${col}] = {`
  366. ];
  367. for (let i = 0; i < row; ++i) {
  368. let rowInitValues = `\t{${matrix[i].join(', ')}}`;
  369. if (i + 1 < row)
  370. rowInitValues += ',';
  371. statements.push(rowInitValues);
  372. }
  373. statements.push(`};`);
  374. statements.push(`for (int ${name}RowIndex = 0; ${name}RowIndex < ${row}; ++${name}RowIndex) {`);
  375. statements.push(`\tvector<${baseType}> ${name}Row(begin(${name}Matrix[${name}RowIndex]), end(${name}Matrix[${name}RowIndex]));`);
  376. statements.push(`\t${name}.push_back(${name}Row);`);
  377. statements.push(`};`);
  378. return statements.join('\n');
  379. }
  380. }
  381. }
  382. return `vector<${elementType}> ${name}; // cannot resolve this type`;
  383. }
  384.  
  385. /**
  386. * 通过变量名,元素类型,以及字面值生成 List 的赋值表达式
  387. * @param name {string} vector 变量名
  388. * @param elementType {string} 元素类型
  389. * @param value {string} 已处理的被赋值字面值
  390. * @returns {string} 可被解析的赋值表达式
  391. */
  392. #makeList(name, elementType, value) {
  393. if (this.#findBaseType(elementType)) {
  394. // List[baseType]
  395. let [formatValue, realValue] = this.parseValue(elementType, value, 1);
  396. return `${name} = ${formatValue}`;
  397. } else {
  398. // List[...]
  399. let pattern = this.#findExtendType(elementType);
  400. if (pattern && pattern.toString().match(/List\\\[.+]/)) {
  401. // List[List[...]]
  402. let baseType = elementType.match(pattern)[1];
  403. if (this.#findBaseType(baseType)) {
  404. // List[List[baseType]]
  405. let formatValue = this.parseValue(baseType, value, 2)[0];
  406. return `${name} = ${formatValue}`;
  407. }
  408. }
  409. }
  410. return `${name} = None # cannot resolve this type`;
  411. }
  412.  
  413. /**
  414. * 获取已处理二维数组字面值的行列信息
  415. * @param value {string} 二维数组字面值
  416. * @returns {[number, number, array[string]]} 二维数组的行,列,以及每一行初始值的字符串列表
  417. */
  418. static #getMatrixInfo(value) {
  419. value = value.replace(/\n/g, '');
  420. let arrays = value.match(/^{\s*(.+?)\s*}$/)[1].match(/{(.+?)}/g);
  421. let [row, col] = [arrays.length, arrays[0].match(/".+?"/g).length];
  422. return [row, col, arrays];
  423. }
  424.  
  425. /**
  426. * 搜索字符串中首个
  427. * @param str {string} 需要搜索的字符串
  428. * @param brackets {string} 括号类型
  429. * @param start {number} 开始搜索的索引
  430. * @returns {array[number]} 返回搜索到的首对最外层括号的索引
  431. */
  432. static #findBrackets(str, brackets, start) {
  433. let stack = [], left = start, length = str.length;
  434. let [l, r] = brackets.split('');
  435. while (left < length && str[left] !== l)
  436. ++left;
  437. if (left >= length)
  438. return [-1, -1];
  439. let right = left;
  440. while (right < length) {
  441. let c = str[right];
  442. let peekElement = stack[stack.length - 1];
  443. if (c === l) {
  444. if (peekElement === '"') {
  445. ++right;
  446. continue;
  447. } else {
  448. stack.push(c);
  449. }
  450. } else if (c === '"') {
  451. if (peekElement === '"') {
  452. stack.pop();
  453. } else {
  454. stack.push(c);
  455. }
  456. } else if (c === r) {
  457. if (peekElement === '"') {
  458. ++right;
  459. continue;
  460. } else if (peekElement === l) {
  461. stack.pop();
  462. if (stack.length === 0)
  463. return [left, right];
  464. }
  465. }
  466. ++right;
  467. }
  468. return [-1, -1];
  469. }
  470.  
  471. /**
  472. * 解析二维字符串数组字面值为真实二维数组
  473. * @param value {string} 二维字符串数组字面值
  474. * @param brackets {string} 括号类型
  475. * @returns {array[array[string]]} 二维字符串数组
  476. */
  477. static #parseStringMatrix(value, brackets) {
  478. let extractElementsPattern = new RegExp(`^\\${brackets[0]}\\s*(.+?)\\s*${brackets[1]}$`);
  479. let extractStringsPattern = /(".*?")/g;
  480. let rawArraysStr = value.match(extractElementsPattern)[1];
  481. let index = 0, strMatrix = [];
  482. let [left, right] = StatementParser.#findBrackets(rawArraysStr, brackets, index);
  483. while (left >= 0 && right >= 0) {
  484. let arrayStr = rawArraysStr.slice(left, right + 1);
  485. let strArray = arrayStr.match(extractStringsPattern);
  486. strMatrix.push(strArray);
  487. index = right + 1;
  488. [left, right] = StatementParser.#findBrackets(rawArraysStr, brackets, index);
  489. }
  490. return strMatrix;
  491. }
  492. }
  493. window.StatementParser = StatementParser;
  494. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址