parser.js 41 KB

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