Statement Parser

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

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

  1. // ==UserScript==
  2. // @name Statement Parser
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.5
  5. // @description 【使用前先看介绍/有问题可反馈】声明解析器 (Statement Parser):通过语言,类型,变量名,以及赋值,直接生成可被解析的声明语句。
  6. // @author cc
  7. // @include *
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. const __VERSION__ = '1.0.4';
  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 {array[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 strOfDeclare = this.#config.useTypeDeclare ? `${type} ` : '';
  142. let strOfEnd = this.#config.endsWithSemicolon ? ';' : '';
  143. let [belongsBaseType, baseType, dimension] = this.resolveType(type);
  144. if (belongsBaseType) {
  145. value = this.parseValue(baseType, value, dimension)[0];
  146. return `${strOfDeclare}${name} = ${value}${strOfEnd}`;
  147. } else {
  148. let pattern = this.#findExtendType(type);
  149. if (pattern && pattern.toString().includes('ListNode')) {
  150. let array = value.match(/\d+/g).map(e => parseInt(e));
  151. return this.#makeListNode(name, array);
  152. } else if (pattern && pattern.toString().includes('vector')) {
  153. let elementType = type.match(pattern)[1];
  154. return this.#makeVector(name, elementType, value);
  155. } else if (pattern && pattern.toString().match(/List\\\[.+]/)) {
  156. let elementType = type.match(pattern)[1];
  157. return this.#makeList(name, elementType, value);
  158. }
  159. }
  160. return `${type} ${name}; // cannot resolve this type`;
  161. }
  162.  
  163. /**
  164. * 从代码中获取注释结构类声明代码
  165. * @param code {string} 代码字符串
  166. * @returns {string|null} 结构类声明代码,不存在则返回 null
  167. */
  168. getClassStructFromCode(code) {
  169. let commentChar = this.#config.commentChar;
  170. let [start, end] = this.#config.classStructSlice;
  171. let prefixPattern = new RegExp(`^\\s*${commentChar === '*' ? '\\*' : commentChar}\\s`);
  172. if (commentChar === '*') {
  173. let [matchLeft, matchRight] = [code.match(/\/\*/), code.match(/\*\//)];
  174. if (!matchLeft || !matchRight)
  175. return null;
  176. let [commentStart, commentEnd] = [matchLeft.index, matchRight.index + 2];
  177. let structComment = code.slice(commentStart, commentEnd).split('\n');
  178. structComment = structComment.slice(start, structComment.length + end);
  179. return structComment.map(line => line.replace(prefixPattern, '')).join('\n');
  180. } else if (commentChar === '#') {
  181. let leftIndex = /#/m.exec(code).index;
  182. let rightIndex = /\n[^#]/m.exec(code).index + 1;
  183. let structComment = code.slice(leftIndex, rightIndex).split('\n');
  184. structComment = structComment.slice(start, structComment.length + end);
  185. return structComment.map(line => line.replace(prefixPattern, '')).join('\n').trim();
  186. }
  187. }
  188.  
  189. /**
  190. * 解析赋值表达式中的被赋予的字面值,无回车无前后空格无末尾逗号
  191. * @param expression 表达式,形式为 "name = value"
  192. * @returns {string} 表达式中被赋予的字面值
  193. */
  194. parseExpression(expression) {
  195. let value;
  196. expression = expression.trim().replace(/,$/, '');
  197. if (expression.includes('=')) {
  198. value = expression.split(/\s*=\s*/)[1];
  199. } else {
  200. value = expression;
  201. }
  202. value = value.replace(/\n/g, '');
  203. return value;
  204. }
  205.  
  206. /**
  207. * 分析被赋予的字面值
  208. * @param baseType {string} 基本类型
  209. * @param value {string} 被赋予的字面值
  210. * @param dimension {number} 类型维度
  211. * @returns {array[string|any]} 处理后的可解析的可被赋予的值
  212. */
  213. parseValue(baseType, value, dimension) {
  214. let brackets = this.#config.arrayBrackets.split('');
  215. let extractElementsPattern = /^\[\s*(.*?)\s*]$/;
  216. let extractStringsPattern = /(".*?")/g;
  217. if (dimension === 0) {
  218. if (baseType === 'char') {
  219. if (value.match(/"."/)) {
  220. value = value.replace(/"/g, '\'');
  221. } else if (value.match(/^.$/)) {
  222. value = `'${value}'`;
  223. }
  224. }
  225. return [value, value];
  226. } else if (dimension === 1) {
  227. if (baseType.toLowerCase() === 'string' || baseType === 'str') {
  228. let elements = value.match(extractStringsPattern);
  229. elements = elements || [];
  230. let elementsStr = elements.join(', ');
  231. value = `${brackets[0]}${elementsStr}${brackets[1]}`;
  232. return [value, elements];
  233. } else {
  234. let rawElementsStr = value.match(extractElementsPattern)[1];
  235. let elements = rawElementsStr.split(/\s*,\s*/);
  236. elements = rawElementsStr ? elements : [];
  237. let elementsStr = elements.join(', ');
  238. if (baseType === 'char')
  239. elementsStr = elementsStr.replace(/"/g, '\'');
  240. value = `${brackets[0]}${elementsStr}${brackets[1]}`;
  241. return [value, elements];
  242. }
  243. } else if (dimension === 2) {
  244. if (baseType.toLowerCase() === 'string' || baseType === 'str') {
  245. let strMatrix = StatementParser.#parseStringMatrix(value, '[]');
  246. value = `${brackets[0]}\n\t${strMatrix.map(strArray => {
  247. return `${brackets[0]}${strArray.join(', ')}${brackets[1]}`;
  248. }).join('\n\t')}\n${brackets[1]}`;
  249. return [value, strMatrix];
  250. } else {
  251. let arraysStr = value.match(extractElementsPattern)[1];
  252. if (!arraysStr)
  253. return [brackets.join(''), []];
  254. let arraysStrFmt = arraysStr.replace(/\s+/g, '').replace(/(],)/g, '$1 ');
  255. let arrayStrs = arraysStrFmt.split(/,\s+/);
  256. let arrayStrFmts = arrayStrs.map(arrayStr => {
  257. let elementsStr = arrayStr.match(extractElementsPattern)[1];
  258. if (baseType === 'char')
  259. elementsStr = elementsStr.replace(/"/g, '\'');
  260. return `${brackets[0]}${elementsStr.replace(/,/g, ', ')}${brackets[1]}`;
  261. });
  262. let realValue = arrayStrs.map(arrayStr => {
  263. let elementsStr = arrayStr.match(extractElementsPattern)[1];
  264. return elementsStr.split(',');
  265. });
  266. value = `${brackets[0]}\n\t${arrayStrFmts.join(',\n\t')}\n${brackets[1]}`;
  267. return [value, realValue];
  268. }
  269. }
  270. return [value, value];
  271. }
  272.  
  273. /**
  274. * 解析类型,检查是否属于基础类型,以及分析类型的维度
  275. * @param type {string} 类型
  276. * @returns {[boolean, string, number]} 是否属于基本类型,解析后的基本类型,类型维度
  277. */
  278. resolveType(type) {
  279. let dimension = 0;
  280. if (type.endsWith('[][]')) {
  281. type = type.slice(0, type.length - 4);
  282. dimension = 2;
  283. } else if (type.endsWith('[]')) {
  284. type = type.slice(0, type.length - 2);
  285. dimension = 1;
  286. }
  287. let isBaseType = !!this.#findBaseType(type);
  288. return [isBaseType, type, dimension];
  289. }
  290.  
  291. /**
  292. * 判断类型是否在基本类型中,并返回匹配到的基本类型,匹配失败返回 null
  293. * @param type {string} 类型
  294. * @returns {string|null} 匹配到的基本类型,或 null
  295. */
  296. #findBaseType(type) {
  297. let index = this.#config.baseType.indexOf(type);
  298. if (index < 0)
  299. return null;
  300. return this.#config.baseType[index];
  301. }
  302.  
  303. /**
  304. * 判断类型是否在扩展类型中,并返回匹配到的扩展类型,匹配失败返回 null
  305. * @param type {string} 类型
  306. * @returns {RegExp|null} 匹配到的扩展类型,或 null
  307. */
  308. #findExtendType(type) {
  309. for (let pattern of this.#config.extendType)
  310. if (type.match(pattern))
  311. return pattern;
  312. return null;
  313. }
  314.  
  315. /**
  316. * 通过链表元素生成链表声明语句
  317. * @param name {string} 变量名
  318. * @param array {array[number]} 链表的所有元素
  319. * @returns {string} 链表声明语句集合的字符串
  320. */
  321. #makeListNode(name, array) {
  322. let strOfPtr = this.#config.usePointer ? '*' : '';
  323. let strOfDeclare = this.#config.useTypeDeclare ? `ListNode${strOfPtr} ` : '';
  324. let strOfNew = this.#config.useNew ? 'new ' : '';
  325. let strOfNullValue = this.#config.nullValue;
  326. let strOfNext = this.#config.accessProperty;
  327. let strOfEnd = this.#config.endsWithSemicolon ? ';' : '';
  328. if (array.length === 0)
  329. return `${strOfDeclare}${name} = ${strOfNullValue}${strOfEnd}`;
  330. let statementList = [`${strOfDeclare}${name} = ${strOfNew}ListNode(${array[0]})${strOfEnd}`];
  331. if (array.length === 1)
  332. return statementList[0];
  333. statementList.push(`${strOfDeclare}${name}Next = ${name}${strOfEnd}`);
  334. for (let i = 1; i < array.length; ++i) {
  335. statementList.push(`${name}Next${strOfNext}next = ${strOfNew}ListNode(${array[i]})${strOfEnd}`);
  336. if (i + 1 < array.length)
  337. statementList.push(`${name}Next = ${name}Next${strOfNext}next${strOfEnd}`);
  338. }
  339. return statementList.join('\n');
  340. }
  341.  
  342. /**
  343. * 通过变量名,元素类型,以及字面值生成 vector 的赋值表达式
  344. * @param name {string} vector 变量名
  345. * @param elementType {string} 元素类型
  346. * @param value {string} 已处理的被赋值字面值
  347. * @returns {string} 可被解析的赋值表达式
  348. */
  349. #makeVector(name, elementType, value) {
  350. if (this.#findBaseType(elementType)) {
  351. // vector<baseType>
  352. let formatValue = this.parseValue(elementType, value, 1)[0];
  353. return `vector<${elementType}> ${name} ${formatValue};`;
  354. } else {
  355. // vector<...>
  356. let pattern = this.#findExtendType(elementType);
  357. if (pattern && pattern.toString().includes('vector')) {
  358. // vector<vector<...>>
  359. let baseType = elementType.match(pattern)[1];
  360. if (this.#findBaseType(baseType)) {
  361. // vector<vector<baseType>>
  362. let matrix = this.parseValue(baseType, value, 2)[1];
  363. let [row, col] = [matrix.length, matrix[0].length];
  364. let statements = [
  365. `vector<vector<${baseType}>> ${name};`,
  366. `${baseType} ${name}Matrix[${row}][${col}] = {`
  367. ];
  368. for (let i = 0; i < row; ++i) {
  369. let rowInitValues = `{${matrix[i].join(', ')}}`;
  370. if (i + 1 < row)
  371. rowInitValues += ',';
  372. statements.push(rowInitValues);
  373. }
  374. statements.push(`};`);
  375. statements.push(`for (int ${name}RowIndex = 0; ${name}RowIndex < ${row}; ++${name}RowIndex) {`);
  376. statements.push(`\tvector<${baseType}> ${name}Row(begin(${name}Matrix[${name}RowIndex]), end(${name}Matrix[${name}RowIndex]));`);
  377. statements.push(`\t${name}.push_back(${name}Row);`);
  378. statements.push(`};`);
  379. return statements.join('\n');
  380. }
  381. }
  382. }
  383. return `vector<${elementType}> ${name}; // cannot resolve this type`;
  384. }
  385.  
  386. /**
  387. * 通过变量名,元素类型,以及字面值生成 List 的赋值表达式
  388. * @param name {string} vector 变量名
  389. * @param elementType {string} 元素类型
  390. * @param value {string} 已处理的被赋值字面值
  391. * @returns {string} 可被解析的赋值表达式
  392. */
  393. #makeList(name, elementType, value) {
  394. if (this.#findBaseType(elementType)) {
  395. // List[baseType]
  396. let formatValue = this.parseValue(elementType, value, 1)[0];
  397. return `${name} = ${formatValue}`;
  398. } else {
  399. // List[...]
  400. let pattern = this.#findExtendType(elementType);
  401. if (pattern && pattern.toString().match(/List\\\[.+]/)) {
  402. // List[List[...]]
  403. let baseType = elementType.match(pattern)[1];
  404. if (this.#findBaseType(baseType)) {
  405. // List[List[baseType]]
  406. let formatValue = this.parseValue(baseType, value, 2)[0];
  407. return `${name} = ${formatValue}`;
  408. }
  409. }
  410. }
  411. return `${name} = None # cannot resolve this type`;
  412. }
  413.  
  414. /**
  415. * 搜索字符串中首个
  416. * @param str {string} 需要搜索的字符串
  417. * @param brackets {string} 括号类型
  418. * @param start {number} 开始搜索的索引
  419. * @returns {array[number]} 返回搜索到的首对最外层括号的索引
  420. */
  421. static #findBrackets(str, brackets, start) {
  422. let stack = [], left = start, length = str.length;
  423. let [l, r] = brackets.split('');
  424. while (left < length && str[left] !== l)
  425. ++left;
  426. if (left >= length)
  427. return [-1, -1];
  428. let right = left;
  429. while (right < length) {
  430. let c = str[right];
  431. let peekElement = stack[stack.length - 1];
  432. if (c === l) {
  433. if (peekElement === '"') {
  434. ++right;
  435. continue;
  436. } else {
  437. stack.push(c);
  438. }
  439. } else if (c === '"') {
  440. if (peekElement === '"') {
  441. stack.pop();
  442. } else {
  443. stack.push(c);
  444. }
  445. } else if (c === r) {
  446. if (peekElement === '"') {
  447. ++right;
  448. continue;
  449. } else if (peekElement === l) {
  450. stack.pop();
  451. if (stack.length === 0)
  452. return [left, right];
  453. }
  454. }
  455. ++right;
  456. }
  457. return [-1, -1];
  458. }
  459.  
  460. /**
  461. * 解析二维字符串数组字面值为真实二维数组
  462. * @param value {string} 二维字符串数组字面值
  463. * @param brackets {string} 括号类型
  464. * @returns {array[array[string]]} 二维字符串数组
  465. */
  466. static #parseStringMatrix(value, brackets) {
  467. let extractElementsPattern = new RegExp(`^\\${brackets[0]}\\s*(.+?)\\s*${brackets[1]}$`);
  468. let extractStringsPattern = /(".*?")/g;
  469. let rawArraysStr = value.match(extractElementsPattern)[1];
  470. let index = 0, strMatrix = [];
  471. let [left, right] = StatementParser.#findBrackets(rawArraysStr, brackets, index);
  472. while (left >= 0 && right >= 0) {
  473. let arrayStr = rawArraysStr.slice(left, right + 1);
  474. let strArray = arrayStr.match(extractStringsPattern);
  475. strMatrix.push(strArray);
  476. index = right + 1;
  477. [left, right] = StatementParser.#findBrackets(rawArraysStr, brackets, index);
  478. }
  479. return strMatrix;
  480. }
  481. }
  482. window.StatementParser = StatementParser;
  483. })();

QingJ © 2025

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