Statement Parser

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

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