Statement Parser

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

当前为 2021-10-01 提交的版本,查看 最新版本

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

QingJ © 2025

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