parser.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. import { ParseException, Span, TokenStream, TokenType } from './index.js'
  2. import tokenizer from './tokenizer.js'
  3. import JavaClass from '../editor/java-class.js'
  4. import {
  5. Assert,
  6. AsyncCall,
  7. BinaryOperation,
  8. Break,
  9. ClassConverter,
  10. Continue,
  11. Exit,
  12. ForStatement,
  13. FunctionCall,
  14. IfStatement,
  15. Import,
  16. LambdaFunction,
  17. LanguageExpression,
  18. LinqField,
  19. LinqJoin,
  20. LinqOrder,
  21. LinqSelect,
  22. ListLiteral,
  23. Literal,
  24. MapLiteral,
  25. MapOrArrayAccess,
  26. MemberAccess,
  27. MethodCall,
  28. NewStatement,
  29. Return,
  30. Spread,
  31. TernaryOperation,
  32. TryStatement,
  33. UnaryOperation,
  34. VarDefine,
  35. VarDestructuringDefine,
  36. VariableAccess,
  37. WhileStatement,
  38. WholeLiteral,
  39. Throw
  40. } from './ast.js'
  41. import RequestParameter from '../editor/request-parameter.js'
  42. export const keywords = ["import", "as", "var", "let", "const", "return", "break", "continue", "if", "for", "in", "new", "true", "false", "null", "else", "try", "catch", "finally", "async", "while", "exit", "and", "or", "throw"/*"assert"*/];
  43. export const linqKeywords = ["from", "join", "left", "group", "by", "as", "having", "and", "or", "in", "where", "on", "limit", "offset"];
  44. const binaryOperatorPrecedence = [
  45. [TokenType.Assignment],
  46. [TokenType.RShift2Equal, TokenType.RShiftEqual, TokenType.LShiftEqual, TokenType.XorEqual, TokenType.BitOrEqual, TokenType.BitAndEqual, TokenType.PercentEqual, TokenType.ForwardSlashEqual, TokenType.AsteriskEqual, TokenType.MinusEqual, TokenType.PlusEqual],
  47. [TokenType.Or, TokenType.SqlOr],
  48. [TokenType.And, TokenType.SqlAnd],
  49. [TokenType.BitOr],
  50. [TokenType.Xor],
  51. [TokenType.BitAnd],
  52. [TokenType.EqualEqualEqual, TokenType.Equal, TokenType.NotEqualEqual, TokenType.NotEqual, TokenType.SqlNotEqual],
  53. [TokenType.Less, TokenType.LessEqual, TokenType.Greater, TokenType.GreaterEqual, TokenType.InstanceOf],
  54. [TokenType.Plus, TokenType.Minus],
  55. [TokenType.LShift, TokenType.RShift, TokenType.RShift2],
  56. [TokenType.Asterisk, TokenType.ForwardSlash, TokenType.Percentage]
  57. ];
  58. const linqBinaryOperatorPrecedence = [
  59. [TokenType.RShift2Equal, TokenType.RShiftEqual, TokenType.LShiftEqual, TokenType.XorEqual, TokenType.BitOrEqual, TokenType.BitAndEqual, TokenType.PercentEqual, TokenType.ForwardSlashEqual, TokenType.AsteriskEqual, TokenType.MinusEqual, TokenType.PlusEqual],
  60. [TokenType.Or, TokenType.SqlOr],
  61. [TokenType.And, TokenType.SqlAnd],
  62. [TokenType.BitOr],
  63. [TokenType.Xor],
  64. [TokenType.BitAnd],
  65. [TokenType.Assignment, TokenType.EqualEqualEqual, TokenType.Equal, TokenType.NotEqualEqual, TokenType.Equal, TokenType.NotEqual, TokenType.SqlNotEqual],
  66. [TokenType.Less, TokenType.LessEqual, TokenType.Greater, TokenType.GreaterEqual, TokenType.InstanceOf],
  67. [TokenType.Plus, TokenType.Minus],
  68. [TokenType.LShift, TokenType.RShift, TokenType.RShift2],
  69. [TokenType.Asterisk, TokenType.ForwardSlash, TokenType.Percentage]
  70. ]
  71. const unaryOperators = [TokenType.MinusMinus, TokenType.PlusPlus, TokenType.BitNot, TokenType.Minus, TokenType.Plus, TokenType.Not];
  72. export class Parser {
  73. constructor(stream) {
  74. this.stream = stream;
  75. this.linqLevel = 0;
  76. }
  77. parse(ignoreError) {
  78. let nodes = [];
  79. try {
  80. while (this.stream.hasMore()) {
  81. let node = this.parseStatement();
  82. if (node != null) {
  83. this.validateNode(node);
  84. nodes.push(node);
  85. }
  86. }
  87. } catch (e) {
  88. //console.error(e)
  89. if (ignoreError !== true) {
  90. throw e;
  91. }
  92. }
  93. return nodes;
  94. }
  95. async parseBest(position) {
  96. let nodes = this.parse()
  97. let env = await this.processEnv(nodes)
  98. return {
  99. best: this.findBestMatch(nodes[nodes.length - 1], position),
  100. env
  101. }
  102. }
  103. async processEnv(nodes) {
  104. let nodeLen = nodes.length
  105. let env = {
  106. ...RequestParameter.environmentFunction(),
  107. ...JavaClass.getAutoImportClass(),
  108. ...JavaClass.getAutoImportModule(),
  109. '@import': []
  110. }
  111. for (let i = 0; i < nodeLen; i++) {
  112. await nodes[i].getJavaType(env)
  113. }
  114. return env
  115. }
  116. validateNode(node) {
  117. if (node instanceof Literal) {
  118. throw new ParseException('literal cannot be used alone', node.getSpan());
  119. }
  120. }
  121. parseStatement(expectRightCurly) {
  122. let result = null;
  123. if (this.stream.match("import", false)) {
  124. result = this.parseImport();
  125. } else if (this.matchVarDefine()) {
  126. result = this.parseVarDefine();
  127. } else if (this.stream.match("if", false)) {
  128. result = this.parseIfStatement();
  129. } else if (this.stream.match("return", false)) {
  130. result = this.parseReturn();
  131. } else if (this.stream.match("for", false)) {
  132. result = this.parseForStatement();
  133. } else if (this.stream.match("while", false)) {
  134. result = this.parseWhileStatement();
  135. } else if (this.stream.match("continue", false)) {
  136. result = new Continue(this.stream.consume().getSpan());
  137. } else if (this.stream.match("async", false)) {
  138. result = this.parseAsync();
  139. } else if (this.stream.match("try", false)) {
  140. result = this.parseTryStatement();
  141. } else if (this.stream.match("break", false)) {
  142. result = new Break(this.stream.consume().getSpan());
  143. } else if (this.stream.match("exit", false)) {
  144. result = this.parseExit();
  145. } else if (this.stream.match("throw", false)) {
  146. result = this.parseThrow();
  147. } else if (this.stream.match("assert", false)) {
  148. result = this.parseAssert();
  149. } else {
  150. let index = this.stream.makeIndex();
  151. if (this.matchTypeDefine()) {
  152. this.stream.resetIndex(index);
  153. result = this.parseVarDefine();
  154. }
  155. if (result == null) {
  156. this.stream.resetIndex(index);
  157. result = this.parseExpression(expectRightCurly);
  158. }
  159. }
  160. while (this.stream.match(";", true)) {
  161. }
  162. return result;
  163. }
  164. matchTypeDefine() {
  165. return this.stream.match(TokenType.Identifier, true) && this.stream.match(TokenType.Identifier, false);
  166. }
  167. matchVarDefine() {
  168. return this.stream.match(["var", "let", "const"], false);
  169. }
  170. checkKeyword(span) {
  171. if (keywords.indexOf(span.getText()) > -1) {
  172. throw new ParseException('变量名不能定义为关键字', span);
  173. }
  174. }
  175. parseThrow() {
  176. let opening = this.stream.consume().getSpan();
  177. let expression = this.parseExpression();
  178. return new Throw(new Span(opening, this.stream.getPrev().getSpan()), expression);
  179. }
  180. parseExit() {
  181. let opening = this.stream.expect("exit").getSpan();
  182. let expressionList = [];
  183. do {
  184. expressionList.push(this.parseExpression());
  185. } while (this.stream.match(TokenType.Comma, true));
  186. return new Exit(new Span(opening, this.stream.getPrev().getSpan()), expressionList);
  187. }
  188. parseAssert() {
  189. let index = this.stream.makeIndex()
  190. try {
  191. let opening = this.stream.expect("assert").getSpan();
  192. let condition = this.parseExpression();
  193. this.stream.expect(TokenType.Colon);
  194. let expressionList = [];
  195. do {
  196. expressionList.push(this.parseExpression());
  197. } while (this.stream.match(TokenType.Comma, true));
  198. return new Assert(new Span(opening, this.stream.getPrev().getSpan()), condition, expressionList);
  199. } catch (e) {
  200. this.stream.resetIndex(index)
  201. return this.parseExpression();
  202. }
  203. }
  204. parseImport() {
  205. let opening = this.stream.expect("import").getSpan();
  206. if (this.stream.hasMore()) {
  207. let expected = this.stream.consume();
  208. let packageName = null;
  209. let isStringLiteral = expected.getTokenType() === TokenType.StringLiteral
  210. if (isStringLiteral) {
  211. packageName = this.createStringLiteral(expected).getValue();
  212. } else if (expected.type === TokenType.Identifier) {
  213. let startSpan = expected.getSpan();
  214. let endSpan = null;
  215. packageName = startSpan.getText();
  216. while (this.stream.match(TokenType.Period, true)) {
  217. isStringLiteral = true;
  218. if (this.stream.match(TokenType.Asterisk, false)) {
  219. expected = this.stream.consume()
  220. break;
  221. }
  222. expected = this.stream.expect(TokenType.Identifier)
  223. }
  224. if (isStringLiteral) {
  225. endSpan = expected.getSpan();
  226. packageName = new Span(startSpan, endSpan).getText();
  227. }
  228. } else {
  229. throw new ParseException("Expected identifier or string, but got stream is " + expected.getTokenType().error, this.stream.getPrev().getSpan());
  230. }
  231. let varName = packageName;
  232. if (isStringLiteral) {
  233. if (this.stream.match("as", true)) {
  234. expected = this.stream.expect(TokenType.Identifier);
  235. this.checkKeyword(expected.getSpan());
  236. varName = expected.getSpan().getText();
  237. } else {
  238. let temp = packageName;
  239. if (!temp.startsWith("@")) {
  240. let index = temp.lastIndexOf(".");
  241. if (index != -1) {
  242. temp = temp.substring(index + 1);
  243. }
  244. } else {
  245. throw new ParseException("Expected as", this.stream.getPrev().getSpan());
  246. }
  247. varName = temp;
  248. }
  249. }
  250. return new Import(new Span(opening, expected.getSpan()), packageName, varName, !isStringLiteral);
  251. }
  252. throw new ParseException("Expected identifier or string, but got stream is EOF", this.stream.getPrev().getSpan());
  253. }
  254. parseReturn() {
  255. let returnSpan = this.stream.expect("return").getSpan();
  256. if (this.stream.match(";", false)) return new Return(returnSpan, null);
  257. let returnValue = this.parseExpression();
  258. return new Return(new Span(returnSpan, returnValue.getSpan()), returnValue);
  259. }
  260. parseAsync() {
  261. let opening = this.stream.expect("async").getSpan();
  262. let expression = this.parseExpression();
  263. return new AsyncCall(new Span(opening, this.stream.getPrev().getSpan()), expression);
  264. }
  265. parseIfStatement() {
  266. let openingIf = this.stream.expect("if").getSpan();
  267. let condition = this.parseExpression();
  268. let trueBlock = this.parseFunctionBody();
  269. let elseIfs = [];
  270. let falseBlock = [];
  271. while (this.stream.hasMore() && this.stream.match("else", true)) {
  272. if (this.stream.hasMore() && this.stream.match("if", false)) {
  273. let elseIfOpening = this.stream.expect("if").getSpan();
  274. let elseIfCondition = this.parseExpression();
  275. let elseIfBlock = this.parseFunctionBody();
  276. let elseIfSpan = new Span(elseIfOpening, elseIfBlock.length > 0 ? elseIfBlock[(elseIfBlock.length - 1)].getSpan() : elseIfOpening);
  277. elseIfs.push(new IfStatement(elseIfSpan, elseIfCondition, elseIfBlock, [],));
  278. } else {
  279. falseBlock = falseBlock.concat(this.parseFunctionBody());
  280. break;
  281. }
  282. }
  283. let closingEnd = this.stream.getPrev().getSpan();
  284. return new IfStatement(new Span(openingIf, closingEnd), condition, trueBlock, elseIfs, falseBlock);
  285. }
  286. parseNewExpression(opening) {
  287. let expression = this.parseAccessOrCall(TokenType.Identifier, true);
  288. let span = new Span(opening.getSource(), opening.getStart(), this.stream.getPrev().getSpan().getEnd())
  289. if (expression instanceof MethodCall) {
  290. return this.parseAccessOrCall(new NewStatement(span, expression.getMethod(), expression.getArguments()));
  291. } else if (expression instanceof FunctionCall) {
  292. return this.parseAccessOrCall(new NewStatement(span, expression.getFunction(), expression.getArguments()));
  293. }
  294. return this.parseAccessOrCall(new NewStatement(span, expression, []));
  295. // throw new ParseException("Expected MethodCall or FunctionCall or LambdaFunction", this.stream.getPrev().getSpan());
  296. }
  297. parseArguments() {
  298. this.stream.expect(TokenType.LeftParantheses);
  299. let args = [];
  300. while (this.stream.hasMore() && !this.stream.match(TokenType.RightParantheses, false)) {
  301. args.push(this.parseExpression());
  302. if (!this.stream.match(TokenType.RightParantheses, false)) this.stream.expect(TokenType.Comma);
  303. }
  304. return args;
  305. }
  306. parseForStatement() {
  307. let openingFor = this.stream.expect("for").getSpan();
  308. this.stream.expect("(");
  309. let index = null;
  310. let value = this.stream.expect(TokenType.Identifier).getSpan();
  311. this.checkKeyword(value);
  312. if (this.stream.match(TokenType.Comma, true)) {
  313. index = value;
  314. value = this.stream.expect(TokenType.Identifier).getSpan();
  315. this.checkKeyword(value);
  316. }
  317. this.stream.expect("in");
  318. let mapOrArray = this.parseExpression();
  319. this.stream.expect(")");
  320. let body = this.parseFunctionBody();
  321. return new ForStatement(new Span(openingFor, this.stream.getPrev().getSpan()), index && index.getText(), value && value.getText(), mapOrArray, body);
  322. }
  323. parseVarDefine() {
  324. let opening = this.stream.consume().getSpan();
  325. // destructuring
  326. let isMapAccess;
  327. if ( (isMapAccess = this.stream.match(TokenType.LeftCurly, false)) || this.stream.match(TokenType.LeftBracket, false) ) {
  328. this.stream.expect(TokenType.LeftCurly, TokenType.LeftBracket);
  329. let tokens = [];
  330. do {
  331. let token = this.stream.expect(TokenType.Identifier);
  332. tokens.push(token);
  333. } while (this.stream.match(TokenType.Comma, true));
  334. if (isMapAccess) {
  335. this.stream.match(TokenType.RightCurly);
  336. } else {
  337. this.stream.match(TokenType.RightBracket);
  338. }
  339. this.stream.match(TokenType.Assignment, true);
  340. return new VarDestructuringDefine(new Span(opening, this.stream.getPrev().getSpan()), tokens, this.parseExpression(), opening.getText())
  341. }
  342. let token = this.stream.expect(TokenType.Identifier);
  343. this.checkKeyword(token.getSpan());
  344. let varDefine;
  345. if (this.stream.match(TokenType.Assignment, true)) {
  346. varDefine = new VarDefine(new Span(opening, this.stream.getPrev().getSpan()), token.getText(), this.parseExpression(), opening.getText());
  347. } else {
  348. varDefine = new VarDefine(new Span(opening, this.stream.getPrev().getSpan()), token.getText(), null, opening.getText());
  349. }
  350. return varDefine;
  351. }
  352. parseTryStatement() {
  353. let opening = this.stream.expect("try");
  354. let tryResources = [];
  355. if (this.stream.match("(", true)) {
  356. if (this.stream.match(")", false)) {
  357. // 空的 try-with-resource
  358. } else {
  359. while (!this.stream.match(")", false)) {
  360. if (this.stream.match(";", true)) {
  361. continue;
  362. }
  363. let result = null;
  364. if (this.matchVarDefine()) {
  365. result = this.parseVarDefine();
  366. } else {
  367. if (this.stream.matchAny(keywords, false)) {
  368. throw new ParseException("try 括号中只允许写赋值语句", this.stream.consume().getSpan());
  369. }
  370. let index = this.stream.makeIndex();
  371. if (this.matchTypeDefine()) {
  372. this.stream.resetIndex(index);
  373. result = this.parseVarDefine();
  374. }
  375. if (result == null) {
  376. this.stream.resetIndex(index);
  377. throw new ParseException("try 括号中只允许写赋值语句", this.stream.consume().getSpan());
  378. }
  379. }
  380. tryResources.push(result);
  381. }
  382. }
  383. this.stream.expect(")");
  384. }
  385. let tryBlocks = this.parseFunctionBody();
  386. let catchBlocks = [];
  387. let finallyBlocks = [];
  388. let exception = null;
  389. if (this.stream.match("catch", true)) {
  390. if (this.stream.match("(", true)) {
  391. exception = this.stream.expect(TokenType.Identifier).getText();
  392. this.stream.expect(")");
  393. }
  394. catchBlocks = catchBlocks.concat(this.parseFunctionBody());
  395. }
  396. if (this.stream.match("finally", true)) {
  397. finallyBlocks = finallyBlocks.concat(this.parseFunctionBody());
  398. }
  399. return new TryStatement(new Span(opening.getSpan(), this.stream.getPrev().getSpan()), exception, tryBlocks, tryResources, catchBlocks, finallyBlocks);
  400. }
  401. parseWhileStatement() {
  402. let openingWhile = this.stream.expect("while").getSpan();
  403. let condition = this.parseExpression();
  404. let trueBlock = this.parseFunctionBody();
  405. let closingEnd = this.stream.getPrev().getSpan();
  406. return new WhileStatement(new Span(openingWhile, closingEnd), condition, trueBlock);
  407. }
  408. parseFunctionBody() {
  409. this.stream.expect("{");
  410. let blocks = [];
  411. while (this.stream.hasMore() && !this.stream.match("}", false)) {
  412. let node = this.parseStatement(true);
  413. if (node != null) {
  414. this.validateNode(node);
  415. blocks.push(node);
  416. }
  417. }
  418. this.expectCloseing();
  419. return blocks;
  420. }
  421. expectCloseing() {
  422. if (!this.stream.hasMore()) {
  423. // throw new ParseException("Did not find closing }.", this.stream.prev().getSpan());
  424. }
  425. return this.stream.expect("}").getSpan();
  426. }
  427. parseExpression(expectRightCurly) {
  428. return this.parseTernaryOperator(expectRightCurly);
  429. }
  430. parseTernaryOperator(expectRightCurly) {
  431. let condition = this.parseBinaryOperator(0, expectRightCurly);
  432. if (this.stream.match(TokenType.Questionmark, true)) {
  433. let trueExpression = this.parseTernaryOperator(expectRightCurly);
  434. this.stream.expect(TokenType.Colon);
  435. let falseExpression = this.parseTernaryOperator(expectRightCurly);
  436. if (condition instanceof BinaryOperation && condition.getOperator() === TokenType.Assignment) {
  437. condition.setRightOperand(new TernaryOperation(condition.getRightOperand(), trueExpression, falseExpression));
  438. return condition;
  439. }
  440. return new TernaryOperation(condition, trueExpression, falseExpression);
  441. } else {
  442. return condition;
  443. }
  444. }
  445. parseBinaryOperator(level, expectRightCurly) {
  446. let nextLevel = level + 1;
  447. let precedence = this.linqLevel > 0 ? linqBinaryOperatorPrecedence : binaryOperatorPrecedence;
  448. let left = nextLevel === precedence.length ? this.parseUnaryOperator(expectRightCurly) : this.parseBinaryOperator(nextLevel, expectRightCurly);
  449. let operators = precedence[level];
  450. while (this.stream.hasMore() && this.stream.match(operators, false)) {
  451. let operator = this.stream.consume();
  452. if (operator.type.inLinq && this.linqLevel === 0) {
  453. throw new ParseException(operator.getText() + " 只能在Linq中使用", this.stream.hasMore() ? this.stream.consume().getSpan() : this.stream.getPrev().getSpan());
  454. }
  455. let right = nextLevel === precedence.length ? this.parseUnaryOperator(expectRightCurly) : this.parseBinaryOperator(nextLevel, expectRightCurly);
  456. left = new BinaryOperation(left, operator, right, this.linqLevel);
  457. }
  458. return left;
  459. }
  460. parseUnaryOperator(expectRightCurly) {
  461. if (this.stream.match(unaryOperators, false)) {
  462. return new UnaryOperation(this.stream.consume(), this.parseUnaryOperator(expectRightCurly));
  463. } else {
  464. if (this.stream.match(TokenType.LeftParantheses, false)) { //(
  465. let openSpan = this.stream.expect(TokenType.LeftParantheses).getSpan();
  466. let index = this.stream.makeIndex();
  467. let parameters = [];
  468. while (this.stream.match(TokenType.Identifier, false)) {
  469. let identifier = this.stream.expect(TokenType.Identifier);
  470. parameters.push(identifier.getSpan().getText());
  471. if (this.stream.match(TokenType.Comma, true)) { //,
  472. continue;
  473. }
  474. if (this.stream.match(TokenType.RightParantheses, true)) { //)
  475. if (this.stream.match(TokenType.Lambda, true)) { // =>
  476. return this.parseLambdaBody(openSpan, parameters);
  477. }
  478. break;
  479. }
  480. }
  481. if (this.stream.match(TokenType.RightParantheses, true) && this.stream.match(TokenType.Lambda, true)) {
  482. return this.parseLambdaBody(openSpan, parameters);
  483. }
  484. this.stream.resetIndex(index);
  485. let expression = this.parseExpression();
  486. this.stream.expect(TokenType.RightParantheses);
  487. return this.parseAccessOrCall(expression);
  488. } else {
  489. let expression = this.parseAccessOrCallOrLiteral(expectRightCurly);
  490. if (expression instanceof MemberAccess || expression instanceof VariableAccess || expression instanceof MapOrArrayAccess) {
  491. if (this.stream.match([TokenType.PlusPlus, TokenType.MinusMinus], false)) {
  492. return new UnaryOperation(this.stream.consume(), expression);
  493. }
  494. }
  495. return expression;
  496. }
  497. }
  498. }
  499. parseLambdaBody(openSpan, parameters) {
  500. let index = this.stream.makeIndex();
  501. let childNodes = [];
  502. try {
  503. let expression = this.parseExpression();
  504. childNodes.push(new Return(new Span("return", 0, 6), expression));
  505. return new LambdaFunction(new Span(openSpan, expression.getSpan()), parameters, childNodes);
  506. } catch (e) {
  507. this.stream.resetIndex(index);
  508. if (this.stream.match(TokenType.LeftCurly, true)) {
  509. while (this.stream.hasMore() && !this.stream.match("}", false)) {
  510. let node = this.parseStatement(true);
  511. this.validateNode(node);
  512. childNodes.push(node);
  513. }
  514. let closeSpan = this.expectCloseing();
  515. return new LambdaFunction(new Span(openSpan, closeSpan), parameters, childNodes);
  516. } else {
  517. let node = this.parseStatement();
  518. childNodes.push(new Return(new Span("return", 0, 6), node));
  519. return new LambdaFunction(new Span(openSpan, node.getSpan()), parameters, childNodes);
  520. }
  521. }
  522. }
  523. parseSpreadAccess(spread) {
  524. if (!spread) {
  525. spread = this.stream.expect(TokenType.Spread);
  526. }
  527. let target = this.parseExpression();
  528. return new Spread(new Span(spread.getSpan(), target.getSpan()), target);
  529. }
  530. parseAccessOrCall(target, isNew) {
  531. if (target === TokenType.StringLiteral || target === TokenType.Identifier) {
  532. let token = this.stream.expect(target);
  533. let identifier = token.getSpan();
  534. if (target === TokenType.Identifier && "new" === identifier.getText()) {
  535. return this.parseNewExpression(identifier);
  536. }
  537. if (target === TokenType.Identifier && this.stream.match(TokenType.Lambda, true)) {
  538. return this.parseLambdaBody(identifier, [identifier.getText()]);
  539. }
  540. let result = target === TokenType.StringLiteral ? this.createStringLiteral(token) : new VariableAccess(identifier, identifier.getText());
  541. return this.parseAccessOrCall(result, isNew);
  542. } else {
  543. while (this.stream.hasMore() && this.stream.match([TokenType.LeftParantheses, TokenType.LeftBracket, TokenType.Period, TokenType.QuestionPeriod, TokenType.ColonColon], false)) {
  544. if (this.stream.match(TokenType.ColonColon, false)) {
  545. let open = this.stream.consume().getSpan();
  546. let args = [];
  547. let identifier = this.stream.expect(TokenType.Identifier);
  548. let closing = identifier.getSpan();
  549. if (this.stream.match(TokenType.LeftParantheses, false)) {
  550. args = this.parseArguments();
  551. closing = this.stream.expect(TokenType.RightParantheses).getSpan();
  552. }
  553. target = new ClassConverter(new Span(open, closing), identifier.getText(), target, args);
  554. }
  555. // function or method call
  556. else if (this.stream.match(TokenType.LeftParantheses, false)) {
  557. let args = this.parseArguments();
  558. let closingSpan = this.stream.expect(TokenType.RightParantheses).getSpan();
  559. if (target instanceof VariableAccess || target instanceof MapOrArrayAccess)
  560. target = new FunctionCall(new Span(target.getSpan(), closingSpan), target, args, this.linqLevel > 0);
  561. else if (target instanceof MemberAccess) {
  562. target = new MethodCall(new Span(target.getSpan(), closingSpan), target, args, this.linqLevel > 0);
  563. } else {
  564. throw new ParseException("Expected a variable, field or method.", this.stream.hasMore() ? this.stream.consume().getSpan() : this.stream.getPrev().getSpan());
  565. }
  566. if (isNew) {
  567. break;
  568. }
  569. }
  570. // map or array access
  571. else if (this.stream.match(TokenType.LeftBracket, true)) {
  572. let keyOrIndex = this.parseExpression();
  573. let closingSpan = this.stream.expect(TokenType.RightBracket).getSpan();
  574. target = new MapOrArrayAccess(new Span(target.getSpan(), closingSpan), target, keyOrIndex);
  575. }
  576. // field or method access
  577. else if (this.stream.match([TokenType.Period, TokenType.QuestionPeriod], false)) {
  578. let optional = this.stream.consume().getTokenType() === TokenType.QuestionPeriod;
  579. if (this.linqLevel > 0 && this.stream.match(TokenType.Asterisk, false)) {
  580. target = new MemberAccess(target.getSpan(), optional, this.stream.expect(TokenType.Asterisk).getSpan(), true);
  581. } else {
  582. let name = this.stream.expect([TokenType.Identifier, TokenType.SqlAnd, TokenType.SqlOr]).getSpan()
  583. target = new MemberAccess(new Span(target.getSpan(), name), target, optional, name, false);
  584. }
  585. }
  586. }
  587. return target;
  588. }
  589. }
  590. parseMapLiteral() {
  591. let openCurly = this.stream.expect(TokenType.LeftCurly).getSpan();
  592. let keys = [];
  593. let values = [];
  594. while (this.stream.hasMore() && !this.stream.match("}", false)) {
  595. let key;
  596. if (this.stream.hasPrev()) {
  597. let prev = this.stream.getPrev();
  598. if (this.stream.match(TokenType.Spread, false) && (prev.getTokenType() === TokenType.LeftCurly || prev.getTokenType() === TokenType.Comma)) {
  599. let spread = this.stream.expect(TokenType.Spread);
  600. keys.push(spread);
  601. values.push(this.parseSpreadAccess(spread));
  602. if (this.stream.match([TokenType.Comma, TokenType.RightCurly], false)) {
  603. this.stream.match(TokenType.Comma, true);
  604. }
  605. continue;
  606. }
  607. }
  608. if (this.stream.match(TokenType.StringLiteral, false)) {
  609. key = this.stream.expect(TokenType.StringLiteral);
  610. } else if (this.stream.match(TokenType.LeftBracket, true)) { // [key]
  611. key = this.parseExpression()
  612. this.stream.expect(TokenType.RightBracket);
  613. } else {
  614. key = this.stream.expect(TokenType.Identifier);
  615. }
  616. keys.push(key);
  617. if (this.stream.match([TokenType.Comma, TokenType.RightCurly], false)) {
  618. this.stream.match(TokenType.Comma, true);
  619. if (key instanceof VariableAccess) {
  620. values.push(key)
  621. } else if (key.getTokenType() === TokenType.Identifier) {
  622. values.push(new VariableAccess(key.getSpan(), key.getText()));
  623. } else {
  624. values.push(new Literal(key.getSpan(), 'java.lang.String'));
  625. }
  626. } else {
  627. this.stream.expect(":");
  628. values.push(this.parseExpression());
  629. if (!this.stream.match("}", false)) {
  630. this.stream.expect(TokenType.Comma);
  631. }
  632. }
  633. }
  634. let closeCurly = this.stream.expect("}").getSpan();
  635. return new MapLiteral(new Span(openCurly, closeCurly), keys, values);
  636. }
  637. parseListLiteral() {
  638. let openBracket = this.stream.expect(TokenType.LeftBracket).getSpan();
  639. let values = [];
  640. while (this.stream.hasMore() && !this.stream.match(TokenType.RightBracket, false)) {
  641. values.push(this.parseExpression());
  642. if (!this.stream.match(TokenType.RightBracket, false)) {
  643. this.stream.expect(TokenType.Comma);
  644. }
  645. }
  646. let closeBracket = this.stream.expect(TokenType.RightBracket).getSpan();
  647. return new ListLiteral(new Span(openBracket, closeBracket), values);
  648. }
  649. parseSelect() {
  650. let opening = this.stream.expect("select", true).getSpan();
  651. this.linqLevel++;
  652. let fields = this.parseLinqFields();
  653. this.stream.expect("from", true);
  654. let from = this.parseLinqField();
  655. let joins = this.parseLinqJoins();
  656. let where;
  657. if (this.stream.match("where", true, true)) {
  658. where = this.parseExpression();
  659. }
  660. let groups = this.parseGroup();
  661. let having;
  662. if (this.stream.match("having", true, true)) {
  663. having = this.parseExpression();
  664. }
  665. let orders = this.parseLinqOrders();
  666. this.linqLevel--;
  667. let limit, offset;
  668. if (this.stream.match("limit", true, true)) {
  669. limit = this.parseExpression();
  670. if (this.stream.match("offset", true, true)) {
  671. offset = this.parseExpression();
  672. }
  673. }
  674. let close = this.stream.getPrev().getSpan();
  675. return new LinqSelect(new Span(opening, close), fields, from, joins, where, groups, having, orders, limit, offset);
  676. }
  677. parseGroup() {
  678. let groups = [];
  679. if (this.stream.match("group", true, true)) {
  680. this.stream.expect("by", true);
  681. do {
  682. let expression = this.parseExpression();
  683. groups.push(new LinqField(expression.getSpan(), expression, null));
  684. } while (this.stream.match(TokenType.Comma, true));
  685. }
  686. return groups;
  687. }
  688. parseLinqOrders() {
  689. let orders = [];
  690. if (this.stream.match("order", true, true)) {
  691. this.stream.expect("by", true);
  692. do {
  693. let expression = this.parseExpression();
  694. let order = 1;
  695. if (this.stream.match(["desc", "asc"], false, true)) {
  696. if ("desc" === this.stream.consume().getText()) {
  697. order = -1;
  698. }
  699. }
  700. orders.push(new LinqOrder(new Span(expression.getSpan(), this.stream.getPrev().getSpan()), expression, null, order));
  701. } while (this.stream.match(TokenType.Comma, true));
  702. }
  703. return orders;
  704. }
  705. parseLinqField() {
  706. let expression = this.parseExpression();
  707. if (this.stream.match(TokenType.Identifier, false) && !this.stream.match(linqKeywords, false, true)) {
  708. let alias = this.stream.expect(TokenType.Identifier).getSpan();
  709. return new LinqField(new Span(expression.getSpan(), alias), expression, alias.getText());
  710. }
  711. return new LinqField(expression.getSpan(), expression, null);
  712. }
  713. parseLinqFields() {
  714. let fields = [];
  715. do {
  716. let expression = this.parseExpression();
  717. if (this.stream.match(TokenType.Identifier, false) && !this.stream.match(linqKeywords, false, true)) {
  718. if (expression instanceof WholeLiteral) {
  719. throw new ParseException("* 后边不能跟别名", this.stream.hasMore() ? this.stream.consume().getSpan() : this.stream.getPrev().getSpan());
  720. } else if (expression instanceof MemberAccess && expression.isWhole()) {
  721. throw new ParseException(expression.getSpan().getText() + " 后边不能跟别名", this.stream.hasMore() ? this.stream.consume().getSpan() : this.stream.getPrev().getSpan());
  722. }
  723. let alias = this.stream.consume().getSpan();
  724. fields.push(new LinqField(new Span(expression.getSpan(), alias), expression, alias.getText()));
  725. } else {
  726. fields.push(new LinqField(expression.getSpan(), expression, null));
  727. }
  728. } while (this.stream.match(TokenType.Comma, true)); //,
  729. if (fields.length === 0) {
  730. throw new ParseException("至少要查询一个字段", this.stream.hasMore() ? this.stream.consume().getSpan() : this.stream.getPrev().getSpan());
  731. }
  732. return fields;
  733. }
  734. parseLinqJoins() {
  735. let joins = [];
  736. do {
  737. let isLeft = this.stream.match("left", false);
  738. let opeing = isLeft ? this.stream.consume().getSpan() : null;
  739. if (this.stream.match("join", true)) {
  740. opeing = isLeft ? opeing : this.stream.getPrev().getSpan();
  741. let target = this.parseLinqField();
  742. this.stream.expect("on");
  743. let condition = this.parseExpression();
  744. joins.push(new LinqJoin(new Span(opeing, this.stream.getPrev().getSpan()), isLeft, target, condition));
  745. }
  746. } while (this.stream.match(["left", "join"], false));
  747. return joins;
  748. }
  749. parseAccessOrCallOrLiteral(expectRightCurly) {
  750. let expression;
  751. if (expectRightCurly && this.stream.match("}", false)) {
  752. return null;
  753. } else if (this.stream.match(TokenType.Spread, false)) {
  754. expression = this.parseSpreadAccess();
  755. } else if (this.stream.match(TokenType.Identifier, false)) {
  756. if (this.stream.match("async", false)) {
  757. expression = this.parseAsync();
  758. } else if (this.stream.match("select", false, true)) {
  759. expression = this.parseSelect();
  760. } else {
  761. expression = this.parseAccessOrCall(TokenType.Identifier);
  762. }
  763. } else if (this.stream.match(TokenType.LeftCurly, false)) {
  764. expression = this.parseMapLiteral();
  765. } else if (this.stream.match(TokenType.LeftBracket, false)) {
  766. expression = this.parseListLiteral();
  767. } else if (this.stream.match(TokenType.StringLiteral, false)) {
  768. expression = this.createStringLiteral(this.stream.expect(TokenType.StringLiteral));
  769. } else if (this.stream.match(TokenType.BooleanLiteral, false)) {
  770. expression = new Literal(this.stream.expect(TokenType.BooleanLiteral).getSpan(), 'java.lang.Boolean');
  771. } else if (this.stream.match(TokenType.DoubleLiteral, false)) {
  772. expression = new Literal(this.stream.expect(TokenType.DoubleLiteral).getSpan(), 'java.lang.Double');
  773. } else if (this.stream.match(TokenType.FloatLiteral, false)) {
  774. expression = new Literal(this.stream.expect(TokenType.FloatLiteral).getSpan(), 'java.lang.Float');
  775. } else if (this.stream.match(TokenType.ByteLiteral, false)) {
  776. expression = new Literal(this.stream.expect(TokenType.ByteLiteral).getSpan(), 'java.lang.Byte');
  777. } else if (this.stream.match(TokenType.ShortLiteral, false)) {
  778. expression = new Literal(this.stream.expect(TokenType.ShortLiteral).getSpan(), 'java.lang.Short');
  779. } else if (this.stream.match(TokenType.IntegerLiteral, false)) {
  780. expression = new Literal(this.stream.expect(TokenType.IntegerLiteral).getSpan(), 'java.lang.Integer');
  781. } else if (this.stream.match(TokenType.LongLiteral, false)) {
  782. expression = new Literal(this.stream.expect(TokenType.LongLiteral).getSpan(), 'java.lang.Long');
  783. } else if (this.stream.match(TokenType.DecimalLiteral, false)) {
  784. expression = new Literal(this.stream.expect(TokenType.DecimalLiteral).getSpan(), 'java.math.BigDecimal');
  785. } else if (this.stream.match(TokenType.RegexpLiteral, false)) {
  786. let token = this.stream.expect(TokenType.RegexpLiteral);
  787. expression = new Literal(token.getSpan(), 'java.util.regex.Pattern');
  788. } else if (this.stream.match(TokenType.NullLiteral, false)) {
  789. expression = new Literal(this.stream.expect(TokenType.NullLiteral).getSpan(), 'null');
  790. } else if (this.linqLevel > 0 && this.stream.match(TokenType.Asterisk, false)) {
  791. expression = new WholeLiteral(this.stream.expect(TokenType.Asterisk).getSpan());
  792. } else if (this.stream.match(TokenType.Language, false)) {
  793. expression = new LanguageExpression(this.stream.consume().getSpan(), this.stream.consume().getSpan());
  794. }
  795. if (expression == null) {
  796. throw new ParseException("Expected a variable, field, map, array, function or method call, or literal.", this.stream.hasMore() ? this.stream.consume().getSpan() : this.stream.getPrev().getSpan());
  797. }
  798. return this.parseAccessOrCall(expression);
  799. }
  800. createStringLiteral(token) {
  801. if (token.getTokenStream() == null) {
  802. return new Literal(token.getSpan(), 'java.lang.String');
  803. }
  804. let tempStream = this.stream;
  805. this.stream = token.getTokenStream();
  806. let expressions = [];
  807. while (this.stream.hasMore()) {
  808. expressions.push(this.parseExpression());
  809. }
  810. this.stream = tempStream;
  811. return new Literal(token.getSpan(), 'java.lang.String', expressions);
  812. }
  813. findBestMatch(node, position) {
  814. let expressions = node.expressions().filter(it => it);
  815. for (let index in expressions) {
  816. let best = this.findBestMatch(expressions[index], position)
  817. if (best) {
  818. return best;
  819. }
  820. }
  821. if (node.getSpan().inPosition(position)) {
  822. return node;
  823. }
  824. return null;
  825. }
  826. }
  827. const objToMap = obj => {
  828. const map = {}
  829. obj?.children?.forEach(it => map[it.name] = it)
  830. return map
  831. }
  832. function processBody(body, srcObj) {
  833. let arr = []
  834. let defaultParam = {
  835. name: '',
  836. value: '',
  837. dataType: '',
  838. required: false,
  839. validateType: '',
  840. expression: '',
  841. error: '',
  842. description: '',
  843. children: [],
  844. }
  845. if (body instanceof MapLiteral) {
  846. body.keys.forEach((key, index) => {
  847. const name = key.span.getText().replace(/['"]/g, '');
  848. let value = body.values[index];
  849. let param = {
  850. ...defaultParam,
  851. description: srcObj[name]?.description || '',
  852. required: srcObj[name]?.required === true,
  853. validateType: srcObj[name]?.validateType || '',
  854. expression: srcObj[name]?.expression || '',
  855. error: srcObj[name]?.error || '',
  856. name,
  857. value: isSimpleObject(value) ? value.span.getText().trim() : '',
  858. dataType: getType(value),
  859. }
  860. if (value instanceof MapLiteral || value instanceof ListLiteral) {
  861. param.children = processBody(value, objToMap(srcObj[name]));
  862. }
  863. arr.push(param)
  864. });
  865. } else if (body instanceof ListLiteral) {
  866. if (body.values[0]) {
  867. let value = body.values[0]
  868. let param = {
  869. ...defaultParam,
  870. value: isSimpleObject(value) ? value.span.getText().trim() : '',
  871. dataType: getType(value),
  872. }
  873. if (value instanceof MapLiteral || value instanceof ListLiteral) {
  874. param.children = processBody(value, {});
  875. }
  876. arr.push(param)
  877. }
  878. }
  879. return arr;
  880. }
  881. function isSimpleObject(object) {
  882. return !(object instanceof MapLiteral || object instanceof ListLiteral)
  883. }
  884. function getType(object) {
  885. if (object instanceof MapLiteral) {
  886. return "Object";
  887. }
  888. if (object instanceof ListLiteral) {
  889. return "Array";
  890. }
  891. if (object instanceof UnaryOperation) {
  892. object = object.operand;
  893. }
  894. let type = object.javaType.substring(object.javaType.lastIndexOf(".") + 1);
  895. if (type === 'Integer' && Number(object.span.getText()) > 0x7fffffff || Number(object.span.getText()) < -0x80000000) {
  896. return 'Long'
  897. }
  898. return type === 'null' ? 'Object' : type;
  899. }
  900. export function parseJson(bodyStr, srcObj) {
  901. srcObj = srcObj || {}
  902. try {
  903. JSON.parse(bodyStr)
  904. let parser = new Parser(new TokenStream(tokenizer(bodyStr)))
  905. let expr = parser.parseExpression();
  906. return {
  907. name: '',
  908. value: '',
  909. dataType: getType(expr),
  910. required: srcObj.required,
  911. validateType: srcObj.validateType || '',
  912. expression: srcObj.expression || '',
  913. error: srcObj.error || '',
  914. description: srcObj.description || '',
  915. children: processBody(expr, objToMap(srcObj))
  916. }
  917. } catch (e) {
  918. // console.error(e)
  919. }
  920. }