PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Runtime/Samples/sympl/csharp/Parser.cs

http://github.com/IronLanguages/main
C# | 1121 lines | 869 code | 138 blank | 114 comment | 249 complexity | 890794a68483bf760655b25d73a10927 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Dynamic;
  4. using System.IO;
  5. using System.Linq.Expressions;
  6. using System.Linq;
  7. namespace SymplSample {
  8. public class Parser {
  9. // ParseFile returns an array of top-level expressions parsed in the
  10. // TextReader.
  11. //
  12. public SymplExpr[] ParseFile(TextReader reader) {
  13. if (reader == null) {
  14. throw new ArgumentException("Reader must not be null.");
  15. }
  16. Lexer lexer = new Lexer(reader);
  17. var body = new List<SymplExpr>();
  18. var token = lexer.GetToken();
  19. while (token != SyntaxToken.EOF) {
  20. lexer.PutToken(token);
  21. body.Add(ParseExprAux(lexer));
  22. token = lexer.GetToken();
  23. }
  24. return body.ToArray();
  25. }
  26. // Parse returns a single expression parsed from the TextReader.
  27. //
  28. public SymplExpr ParseExpr(TextReader reader) {
  29. if (reader == null) {
  30. throw new ArgumentException("Reader must not be null.");
  31. }
  32. return ParseExprAux(new Lexer(reader));
  33. }
  34. // _parseExpr parses an expression from the Lexer passed in.
  35. //
  36. private SymplExpr ParseExprAux(Lexer lexer) {
  37. Token token = lexer.GetToken();
  38. SymplExpr res = null;
  39. if (token == SyntaxToken.EOF) {
  40. throw new SymplParseException(
  41. "Unexpected EOF encountered while parsing expression.");
  42. }
  43. if (token == SyntaxToken.Quote) {
  44. lexer.PutToken(token);
  45. res = ParseQuoteExpr(lexer);
  46. } else if (token == SyntaxToken.Paren) {
  47. lexer.PutToken(token);
  48. res = ParseForm(lexer);
  49. } else if (token is IdOrKeywordToken) {
  50. // If we encounter literal kwd constants, they get turned into ID
  51. // Exprs. Code that accepts Id Exprs, needs to check if the token is
  52. // kwd or not when it matters.
  53. if ((token is KeywordToken) && !(token == KeywordToken.Nil) &&
  54. !(token == KeywordToken.True) && !(token == KeywordToken.False)) {
  55. throw new InvalidCastException("Keyword cannot be an expression");
  56. } else {
  57. res = new SymplIdExpr((IdOrKeywordToken)token);
  58. }
  59. } else if (token is LiteralToken) {
  60. res = new SymplLiteralExpr(((LiteralToken)token).Value);
  61. }
  62. // check for dotted expr
  63. if (res != null) {
  64. Token next = lexer.GetToken();
  65. lexer.PutToken(next);
  66. if (next == SyntaxToken.Dot) {
  67. return ParseDottedExpr(lexer, res);
  68. } else {
  69. return res;
  70. }
  71. }
  72. throw new SymplParseException(
  73. "Unexpected token when expecting " +
  74. "beginning of expression -- " + token.ToString() + " ... " +
  75. lexer.GetToken().ToString() + lexer.GetToken().ToString() +
  76. lexer.GetToken().ToString() + lexer.GetToken().ToString());
  77. }
  78. // _parseForm parses a parenthetic form. If the first token after the paren
  79. // is a keyword, then it something like defun, loop, if, try, etc. If the
  80. // first sub expr is another parenthetic form, then it must be an expression
  81. // that returns a callable object.
  82. //
  83. private SymplExpr ParseForm(Lexer lexer) {
  84. Token token = lexer.GetToken();
  85. if (token != SyntaxToken.Paren) {
  86. throw new SymplParseException(
  87. "List expression must start with '('.");
  88. }
  89. token = lexer.GetToken();
  90. if (token is IdOrKeywordToken) {
  91. lexer.PutToken(token);
  92. if (token is KeywordToken) {
  93. // Defun, Let*, Set, Import, ...
  94. return ParseKeywordForm(lexer);
  95. } else {
  96. return ParseFunctionCall(lexer);
  97. }
  98. } else {
  99. lexer.PutToken(token);
  100. return ParseFunctionCall(lexer);
  101. }
  102. }
  103. // _parseKeywordForm parses parenthetic built in forms such as defun, if,
  104. // loop, etc.
  105. //
  106. private SymplExpr ParseKeywordForm(Lexer lexer) {
  107. Token name = lexer.GetToken();
  108. if (!(name is KeywordToken)) {
  109. throw new SymplParseException(
  110. "Internal error: parsing keyword form?");
  111. }
  112. lexer.PutToken(name);
  113. if (name == KeywordToken.Import) {
  114. return ParseImport(lexer);
  115. } else if (name == KeywordToken.Defun) {
  116. return ParseDefun(lexer);
  117. } else if (name == KeywordToken.Lambda) {
  118. return ParseLambda(lexer);
  119. } else if (name == KeywordToken.Set) {
  120. return ParseSet(lexer);
  121. } else if (name == KeywordToken.LetStar) {
  122. return ParseLetStar(lexer);
  123. } else if (name == KeywordToken.Block) {
  124. return ParseBlock(lexer);
  125. } else if (name == KeywordToken.Eq) {
  126. return ParseEq(lexer);
  127. } else if (name == KeywordToken.Cons) {
  128. return ParseCons(lexer);
  129. } else if (name == KeywordToken.List) {
  130. return ParseListCall(lexer);
  131. } else if (name == KeywordToken.If) {
  132. return ParseIf(lexer);
  133. } else if (name == KeywordToken.New) {
  134. return ParseNew(lexer);
  135. } else if (name == KeywordToken.Loop) {
  136. return ParseLoop(lexer);
  137. } else if (name == KeywordToken.Break) {
  138. return ParseBreak(lexer);
  139. } else if (name == KeywordToken.Elt) {
  140. return ParseElt(lexer);
  141. } else if (name == KeywordToken.Add ||
  142. name == KeywordToken.Substract ||
  143. name == KeywordToken.Muliply ||
  144. name == KeywordToken.Divide ||
  145. name == KeywordToken.Equal ||
  146. name == KeywordToken.NotEqual ||
  147. name == KeywordToken.GreaterThan ||
  148. name == KeywordToken.LessThan ||
  149. name == KeywordToken.And ||
  150. name == KeywordToken.Or) {
  151. return ParseExprTreeBinaryOp(lexer);
  152. } else if (name == KeywordToken.Not) {
  153. return ParseExprTreeUnaryOp(lexer);
  154. }
  155. throw new SymplParseException(
  156. "Internal: unrecognized keyword form?");
  157. }
  158. private SymplExpr ParseDefun(Lexer lexer) {
  159. Token token = lexer.GetToken();
  160. if (token != KeywordToken.Defun) {
  161. throw new SymplParseException("Internal: parsing Defun?");
  162. }
  163. IdOrKeywordToken name = lexer.GetToken() as IdOrKeywordToken;
  164. if (name == null || name.IsKeywordToken) {
  165. throw new SymplParseException(
  166. "Defun must have an ID for name -- " + name.ToString());
  167. }
  168. var parms = ParseParams(lexer, "Defun");
  169. var body = ParseBody(lexer, "Hit EOF in function body" +
  170. name.Name);
  171. return new SymplDefunExpr(name.Name, parms, body);
  172. }
  173. private SymplExpr ParseLambda(Lexer lexer) {
  174. Token token = lexer.GetToken();
  175. if (token != KeywordToken.Lambda) {
  176. throw new SymplParseException("Internal: parsing Lambda?");
  177. }
  178. var parms = ParseParams(lexer, "Lambda");
  179. var body = ParseBody(lexer, "Hit EOF in function body");
  180. return new SymplLambdaExpr(parms, body);
  181. }
  182. // _parseParams parses sequence of vars for Defuns and Lambdas, and always
  183. // returns a list of IdTokens.
  184. //
  185. private IdOrKeywordToken[] ParseParams(Lexer lexer, string definer) {
  186. Token token = lexer.GetToken();
  187. if (token != SyntaxToken.Paren) {
  188. throw new SymplParseException(
  189. definer + " must have param list following name.");
  190. }
  191. lexer.PutToken(token);
  192. return EnsureListOfIds(ParseList(lexer, "param list.").Elements, false,
  193. definer + " params must be valid IDs.");
  194. }
  195. // _parseBody parses sequence of expressions as for Defun, Let, etc., and
  196. // always returns a list, even if empty. It gobbles the close paren too.
  197. //
  198. private SymplExpr[] ParseBody(Lexer lexer, string error) {
  199. Token token = lexer.GetToken();
  200. List<SymplExpr> body = new List<SymplExpr>();
  201. while (token != SyntaxToken.EOF && token != SyntaxToken.CloseParen) {
  202. lexer.PutToken(token);
  203. body.Add(ParseExprAux(lexer));
  204. token = lexer.GetToken();
  205. }
  206. if (token == SyntaxToken.EOF) {
  207. throw new SymplParseException(error);
  208. }
  209. return body.ToArray();
  210. }
  211. // (import id[.id]* [{id | (id [id]*)} [{id | (id [id]*)}]] )
  212. // (import file-or-dotted-Ids name-or-list-of-members reanme-or-list-of)
  213. //
  214. private SymplExpr ParseImport(Lexer lexer) {
  215. if (lexer.GetToken() != KeywordToken.Import) {
  216. throw new SymplParseException(
  217. "Internal: parsing Import call?");
  218. }
  219. IdOrKeywordToken[] ns_or_module = ParseImportNameOrModule(lexer);
  220. IdOrKeywordToken[] members = ParseImportNames(lexer, "member names", true);
  221. IdOrKeywordToken[] as_names = ParseImportNames(lexer, "renames", false);
  222. if (members.Length != as_names.Length && as_names.Length != 0) {
  223. throw new SymplParseException(
  224. "Import as-names must be same form as member names.");
  225. }
  226. if (lexer.GetToken() != SyntaxToken.CloseParen) {
  227. throw new SymplParseException(
  228. "Import must end with closing paren.");
  229. }
  230. return new SymplImportExpr(ns_or_module, members, as_names);
  231. }
  232. // Parses dotted namespaces or Sympl.Globals members to import.
  233. //
  234. private IdOrKeywordToken[] ParseImportNameOrModule(Lexer lexer) {
  235. Token token = lexer.GetToken();
  236. if (!(token is IdOrKeywordToken)) { // Keywords are ok here.
  237. throw new SymplParseException(
  238. "Id must follow Import symbol");
  239. }
  240. Token dot = lexer.GetToken();
  241. List<IdOrKeywordToken> ns_or_module = new List<IdOrKeywordToken>();
  242. if (dot == SyntaxToken.Dot) {
  243. lexer.PutToken(dot);
  244. var tmp = ParseDottedExpr(
  245. lexer, new SymplIdExpr((IdOrKeywordToken)token));
  246. foreach (var e in tmp.Exprs) {
  247. if (!(e is SymplIdExpr)) { // Keywords are ok here.
  248. throw new SymplParseException(
  249. "Import targets must be dotted identifiers." +
  250. e.ToString() + ns_or_module.ToString());
  251. }
  252. ns_or_module.Add(((SymplIdExpr)e).IdToken);
  253. }
  254. token = lexer.GetToken();
  255. } else {
  256. ns_or_module.Add((IdOrKeywordToken)token);
  257. token = dot;
  258. }
  259. lexer.PutToken(token);
  260. return ns_or_module.ToArray();
  261. }
  262. // Parses list of member names to import from the object represented in the
  263. // result of _parseImportNameOrModule, which will be a file module or object
  264. // from Sympl.Globals. This is also used to parse the list of renames for
  265. // these same members.
  266. //
  267. private IdOrKeywordToken[] ParseImportNames(Lexer lexer, string nameKinds,
  268. bool allowKeywords) {
  269. Token token = lexer.GetToken();
  270. List<IdOrKeywordToken> names = new List<IdOrKeywordToken>();
  271. if (token is IdOrKeywordToken) {
  272. IdOrKeywordToken idToken = (IdOrKeywordToken)token;
  273. if (!idToken.IsKeywordToken) {
  274. names.Add(idToken);
  275. }
  276. } else if (token == SyntaxToken.Paren) {
  277. lexer.PutToken(token);
  278. object[] memberTokens = ParseList(lexer, "Import " + nameKinds + ".")
  279. .Elements;
  280. IdOrKeywordToken[] memberIdTokens =
  281. EnsureListOfIds(memberTokens, allowKeywords,
  282. "Import " + nameKinds + " must be valid IDs.");
  283. } else if (token == SyntaxToken.CloseParen) {
  284. lexer.PutToken(token);
  285. } else {
  286. throw new SymplParseException(
  287. "Import takes dotted names, then member vars.");
  288. }
  289. return names.ToArray();
  290. }
  291. private IdOrKeywordToken[] EnsureListOfIds(object[] list,
  292. bool allowKeywords,
  293. string error) {
  294. foreach (var t in list) {
  295. IdOrKeywordToken id = t as IdOrKeywordToken;
  296. if (id == null || (!allowKeywords && id.IsKeywordToken)) {
  297. throw new SymplParseException(error);
  298. }
  299. }
  300. return list.Select(t => (IdOrKeywordToken)t).ToArray();
  301. }
  302. // _parseDottedExpr gathers infix dotted member access expressions. The
  303. // object expression can be anything and is passed in via expr. Successive
  304. // member accesses must be dotted identifier expressions or member invokes --
  305. // a.b.(c 3).d. The member invokes cannot have dotted expressions for the
  306. // member name such as a.(b.c 3).
  307. //
  308. private SymplDottedExpr ParseDottedExpr(Lexer lexer, SymplExpr objExpr) {
  309. Token token = lexer.GetToken();
  310. if (token != SyntaxToken.Dot) {
  311. throw new SymplParseException(
  312. "Internal: parsing dotted expressions?");
  313. }
  314. List<SymplExpr> exprs = new List<SymplExpr>();
  315. token = lexer.GetToken();
  316. while (token is IdOrKeywordToken || token == SyntaxToken.Paren) {
  317. // Needs to be fun call or IDs
  318. SymplExpr expr;
  319. if (token is IdOrKeywordToken) {
  320. // Keywords are ok as member names.
  321. expr = new SymplIdExpr((IdOrKeywordToken)token);
  322. } else {
  323. lexer.PutToken(token);
  324. expr = ParseForm(lexer);
  325. SymplFunCallExpr funCall = expr as SymplFunCallExpr;
  326. if (funCall != null || !(funCall.Function is SymplIdExpr)) {
  327. throw new SymplParseException(
  328. "Dotted expressions must be identifiers or " +
  329. "function calls with identiers as the function " +
  330. "value -- " + expr.ToString());
  331. }
  332. }
  333. exprs.Add(expr);
  334. token = lexer.GetToken();
  335. if (token != SyntaxToken.Dot) {
  336. break;
  337. }
  338. token = lexer.GetToken();
  339. }
  340. lexer.PutToken(token);
  341. return new SymplDottedExpr(objExpr, exprs.ToArray());
  342. }
  343. // _parseSet parses a LHS expression and value expression. All analysis on
  344. // the LHS is in etgen.py.
  345. //
  346. private SymplAssignExpr ParseSet(Lexer lexer) {
  347. if (lexer.GetToken() != KeywordToken.Set) {
  348. throw new SymplParseException("Internal error: parsing Set?");
  349. }
  350. var lhs = ParseExprAux(lexer);
  351. var val = ParseExprAux(lexer);
  352. if (lexer.GetToken() != SyntaxToken.CloseParen) {
  353. throw new SymplParseException(
  354. "Expected close paren for Set expression.");
  355. }
  356. return new SymplAssignExpr(lhs, val);
  357. }
  358. // _parseLetStar parses (let* ((<var> <expr>)*) <body>).
  359. //
  360. private SymplLetStarExpr ParseLetStar(Lexer lexer) {
  361. if (lexer.GetToken() != KeywordToken.LetStar) {
  362. throw new SymplParseException("Internal error: parsing Let?");
  363. }
  364. var token = lexer.GetToken();
  365. if (token != SyntaxToken.Paren) {
  366. throw new SymplParseException(
  367. "Let expression has no bindings? Missing '('.");
  368. }
  369. // Get bindings
  370. List<LetBinding> bindings = new List<LetBinding>();
  371. token = lexer.GetToken();
  372. while (token == SyntaxToken.Paren) {
  373. var e = ParseExprAux(lexer);
  374. var id = e as SymplIdExpr;
  375. if (id == null || id.IdToken.IsKeywordToken) {
  376. throw new SymplParseException(
  377. "Let binding must be (<ID> <expr>) -- ");
  378. }
  379. var init = ParseExprAux(lexer);
  380. bindings.Add(new LetBinding(id.IdToken, init));
  381. token = lexer.GetToken();
  382. if (token != SyntaxToken.CloseParen) {
  383. throw new SymplParseException(
  384. "Let binding missing close paren -- ");
  385. }
  386. token = lexer.GetToken();
  387. }
  388. if (token != SyntaxToken.CloseParen) {
  389. throw new SymplParseException(
  390. "Let bindings missing close paren.");
  391. }
  392. var body = ParseBody(lexer, "Unexpected EOF in Let.");
  393. return new SymplLetStarExpr(bindings.ToArray(), body);
  394. }
  395. // _parseBlock parses a block expression, a sequence of exprs to
  396. // execute in order, returning the last expression's value.
  397. //
  398. private SymplBlockExpr ParseBlock(Lexer lexer) {
  399. if (lexer.GetToken() != KeywordToken.Block) {
  400. throw new SymplParseException(
  401. "Internal error: parsing Block?");
  402. }
  403. var body = ParseBody(lexer, "Unexpected EOF in Block.");
  404. return new SymplBlockExpr(body);
  405. }
  406. // first sub form must be expr resulting in callable, but if it is dotted expr,
  407. // then eval the first N-1 dotted exprs and use invoke member or get member
  408. // on last of dotted exprs so that the 2..N sub forms are the arguments to
  409. // the invoke member. It's as if the call breaks into a block of a temp
  410. // assigned to the N-1 dotted exprs followed by an invoke member (or a get
  411. // member and call, which the runtime binder decides). The non-dotted expr
  412. // simply evals to an object that better be callable with the supplied args,
  413. // which may be none.
  414. //
  415. private SymplFunCallExpr ParseFunctionCall(Lexer lexer) {
  416. // First sub expr is callable object or invoke member expr.
  417. var fun = ParseExprAux(lexer);
  418. if (fun is SymplDottedExpr) {
  419. SymplDottedExpr dottedExpr = (SymplDottedExpr)fun;
  420. // Keywords ok as members.
  421. if (!(dottedExpr.Exprs.Last() is SymplIdExpr)) {
  422. throw new SymplParseException(
  423. "Function call with dotted expression for function must " +
  424. "end with ID Expr, not member invoke." +
  425. dottedExpr.Exprs.Last().ToString());
  426. }
  427. }
  428. // Tail exprs are args.
  429. var args = ParseBody(lexer, "Unexpected EOF in arg list for " +
  430. fun.ToString());
  431. return new SymplFunCallExpr(fun, args);
  432. }
  433. // This parses a quoted list, ID/keyword, or literal.
  434. //
  435. private SymplQuoteExpr ParseQuoteExpr(Lexer lexer) {
  436. var token = lexer.GetToken();
  437. if (token != SyntaxToken.Quote) {
  438. throw new SymplParseException("Internal: parsing Quote?.");
  439. }
  440. token = lexer.GetToken();
  441. object expr;
  442. if (token == SyntaxToken.Paren) {
  443. lexer.PutToken(token);
  444. expr = ParseList(lexer, "quoted list.");
  445. } else if (token is IdOrKeywordToken ||
  446. token is LiteralToken) {
  447. expr = token;
  448. } else {
  449. throw new SymplParseException(
  450. "Quoted expression can only be list, ID/Symbol, or literal.");
  451. }
  452. return new SymplQuoteExpr(expr);
  453. }
  454. private SymplEqExpr ParseEq (Lexer lexr) {
  455. var token = lexr.GetToken();
  456. if (token != KeywordToken.Eq) {
  457. throw new SymplParseException("Internal: parsing Eq?");
  458. }
  459. SymplExpr left, right;
  460. ParseBinaryRuntimeCall(lexr, out left, out right);
  461. return new SymplEqExpr(left, right);
  462. }
  463. private SymplConsExpr ParseCons (Lexer lexr) {
  464. var token = lexr.GetToken();
  465. if (token != KeywordToken.Cons) {
  466. throw new SymplParseException("Internal: parsing Cons?");
  467. }
  468. SymplExpr left, right;
  469. ParseBinaryRuntimeCall(lexr, out left, out right);
  470. return new SymplConsExpr(left, right);
  471. }
  472. // _parseBinaryRuntimeCall parses two exprs and a close paren, returning the
  473. // two exprs.
  474. //
  475. private void ParseBinaryRuntimeCall(Lexer lexr, out SymplExpr left,
  476. out SymplExpr right) {
  477. left = ParseExprAux(lexr);
  478. right = ParseExprAux(lexr);
  479. if (lexr.GetToken() != SyntaxToken.CloseParen) {
  480. throw new SymplParseException(
  481. "Expected close paren for Eq call.");
  482. }
  483. }
  484. // _parseListCall parses a call to the List built-in keyword form that takes
  485. // any number of arguments.
  486. //
  487. private SymplListCallExpr ParseListCall (Lexer lexr) {
  488. Token token = lexr.GetToken();
  489. if (token != KeywordToken.List) {
  490. throw new SymplParseException("Internal: parsing List call?");
  491. }
  492. var args = ParseBody(lexr, "Unexpected EOF in arg list for call to List.");
  493. return new SymplListCallExpr(args);
  494. }
  495. private SymplIfExpr ParseIf (Lexer lexr) {
  496. var token = lexr.GetToken();
  497. if (token != KeywordToken.If) {
  498. throw new SymplParseException("Internal: parsing If?");
  499. }
  500. var args = ParseBody(lexr, "Unexpected EOF in If form.");
  501. int argslen = args.Length;
  502. if (argslen == 2) {
  503. return new SymplIfExpr(args[0], args[1], null);
  504. } else if (argslen == 3) {
  505. return new SymplIfExpr(args[0], args[1], args[2]);
  506. } else {
  507. throw new SymplParseException(
  508. "IF must be (if <test> <consequent> [<alternative>]).");
  509. }
  510. }
  511. // This parses pure list and atom structure. Atoms are IDs, strs, and nums.
  512. // _parseLoop parses a loop expression, a sequence of exprs to
  513. // execute in order, forever. See Break for returning expression's value.
  514. //
  515. private SymplLoopExpr ParseLoop (Lexer lexr) {
  516. if (lexr.GetToken() != KeywordToken.Loop) {
  517. throw new SymplParseException("Internal error: parsing Loop?");
  518. }
  519. var body = ParseBody(lexr, "Unexpected EOF in Loop.");
  520. return new SymplLoopExpr(body);
  521. }
  522. // _parseBreak parses a Break expression, which has an optional value that
  523. // becomes a loop expression's value.
  524. //
  525. private SymplBreakExpr ParseBreak (Lexer lexr) {
  526. if (lexr.GetToken() != KeywordToken.Break) {
  527. throw new SymplParseException("Internal error: parsing Break?");
  528. }
  529. var token = lexr.GetToken();
  530. SymplExpr value;
  531. if (token == SyntaxToken.CloseParen) {
  532. value = null;
  533. } else {
  534. lexr.PutToken(token);
  535. value = ParseExprAux(lexr);
  536. token = lexr.GetToken();
  537. if (token != SyntaxToken.CloseParen) {
  538. throw new SymplParseException(
  539. "Break expression missing close paren.");
  540. }
  541. }
  542. return new SymplBreakExpr(value);
  543. }
  544. // Parse a New form for creating instances of types. Second sub expr (one
  545. // after kwd New) evals to a type.
  546. //
  547. // Consider adding a new kwd form generic-type-args that could be the third
  548. // sub expr and take any number of sub exprs that eval to types. These could
  549. // be used to specific concrete generic type instances. Without this support
  550. // SymPL programmers need to open code this as the examples show.
  551. //
  552. private SymplNewExpr ParseNew(Lexer lexr) {
  553. Token token = lexr.GetToken();
  554. if (token != KeywordToken.New) {
  555. throw new SymplParseException("Internal: parsing New?");
  556. }
  557. var type = ParseExprAux(lexr);
  558. var args = ParseBody(lexr, "Unexpected EOF in arg list for call to New.");
  559. return new SymplNewExpr(type, args);
  560. }
  561. // This parses pure list and atom structure. Atoms are IDs, strs, and nums.
  562. // Need quoted form of dotted exprs, quote, etc., if want to have macros one
  563. // day. This is used for Import name parsing, Defun/Lambda params, and quoted
  564. // lists.
  565. //
  566. private SymplListExpr ParseList(Lexer lexer, string errStr) {
  567. var token = lexer.GetToken();
  568. if (token != SyntaxToken.Paren) {
  569. throw new SymplParseException(
  570. "List expression must start with '('.");
  571. }
  572. token = lexer.GetToken();
  573. List<object> res = new List<object>();
  574. while (token != SyntaxToken.EOF && token != SyntaxToken.CloseParen) {
  575. lexer.PutToken(token);
  576. object elt;
  577. if (token == SyntaxToken.Paren) {
  578. elt = ParseList(lexer, errStr);
  579. } else if (token is IdOrKeywordToken || token is LiteralToken) {
  580. elt = token;
  581. lexer.GetToken();
  582. } else if (token == SyntaxToken.Dot) {
  583. throw new SymplParseException(
  584. "Can't have dotted syntax in " + errStr);
  585. } else {
  586. throw new SymplParseException(
  587. "Unexpected token in list -- " + token.ToString());
  588. }
  589. if (elt == null) {
  590. throw new SymplParseException(
  591. "Internal: no next element in list?");
  592. }
  593. res.Add(elt);
  594. token = lexer.GetToken();
  595. }
  596. if (token == SyntaxToken.EOF) {
  597. throw new SymplParseException(
  598. "Unexpected EOF encountered while parsing list.");
  599. }
  600. return new SymplListExpr(res.ToArray());
  601. }
  602. public SymplEltExpr ParseElt(Lexer lexr) {
  603. Token token = lexr.GetToken();
  604. if (token != KeywordToken.Elt) {
  605. throw new SymplParseException("Internal: parsing Elt?");
  606. }
  607. var obj = ParseExprAux(lexr);
  608. var indexes = ParseBody(lexr,
  609. "Unexpected EOF in arg list for call to Elt.");
  610. return new SymplEltExpr(obj, indexes);
  611. }
  612. // This parses a BinaryOp expression.
  613. //
  614. private SymplBinaryExpr ParseExprTreeBinaryOp(Lexer lexr) {
  615. KeywordToken keyword = lexr.GetToken() as KeywordToken;
  616. if (keyword == null) {
  617. throw new SymplParseException(
  618. "Internal error: parsing Binary?");
  619. }
  620. SymplExpr left, right;
  621. ParseBinaryRuntimeCall(lexr, out left, out right);
  622. var op = GetOpType(keyword);
  623. return new SymplBinaryExpr(left, right, op);
  624. }
  625. // This parses a UnaryOp expression.
  626. //
  627. private SymplUnaryExpr ParseExprTreeUnaryOp(Lexer lexr) {
  628. KeywordToken keyword = lexr.GetToken() as KeywordToken;
  629. if (keyword == null) {
  630. throw new SymplParseException(
  631. "Internal error: parsing Unary?");
  632. }
  633. var op = GetOpType(keyword);
  634. var operand = ParseExprAux(lexr);
  635. if (lexr.GetToken() != SyntaxToken.CloseParen) {
  636. throw new SymplParseException(
  637. "Unary expression missing close paren.");
  638. }
  639. return new SymplUnaryExpr(operand, op);
  640. }
  641. // Get the ExpressionType for an operator
  642. private ExpressionType GetOpType(KeywordToken keyword) {
  643. if (keyword == KeywordToken.Add) {
  644. return ExpressionType.Add;
  645. }
  646. if (keyword == KeywordToken.Substract) {
  647. return ExpressionType.Subtract;
  648. }
  649. if (keyword == KeywordToken.Muliply) {
  650. return ExpressionType.Multiply;
  651. }
  652. if (keyword == KeywordToken.Divide) {
  653. return ExpressionType.Divide;
  654. }
  655. if (keyword == KeywordToken.Equal) {
  656. return ExpressionType.Equal;
  657. }
  658. if (keyword == KeywordToken.NotEqual) {
  659. return ExpressionType.NotEqual;
  660. }
  661. if (keyword == KeywordToken.GreaterThan) {
  662. return ExpressionType.GreaterThan;
  663. }
  664. if (keyword == KeywordToken.LessThan) {
  665. return ExpressionType.LessThan;
  666. }
  667. if (keyword == KeywordToken.And) {
  668. return ExpressionType.And;
  669. }
  670. if (keyword == KeywordToken.Or) {
  671. return ExpressionType.Or;
  672. }
  673. if (keyword == KeywordToken.Not) {
  674. return ExpressionType.Not;
  675. }
  676. throw new SymplParseException(
  677. "Unrecognized keyword for operators");
  678. }
  679. }
  680. //###################
  681. // SymplExpr Classes
  682. //###################
  683. public class SymplExpr {
  684. }
  685. // SymplIdExpr represents identifiers, but the IdToken can be a keyword
  686. // sometimes. For example, in quoted lists, import expressions, and as
  687. // members of objects in dotted exprs. Need to check for .IsKeywordToken
  688. // when it matters.
  689. //
  690. public class SymplIdExpr : SymplExpr {
  691. private IdOrKeywordToken _idToken;
  692. public IdOrKeywordToken IdToken {
  693. get { return _idToken; }
  694. }
  695. public SymplIdExpr(IdOrKeywordToken id) {
  696. _idToken = id;
  697. }
  698. public override string ToString() {
  699. return "<IdExpr " + _idToken.Name + ">";
  700. }
  701. }
  702. public class SymplListExpr : SymplExpr {
  703. private object[] _elements;
  704. // This is always a list of Tokens or SymplListExprs.
  705. public object[] Elements { get { return _elements; } }
  706. public SymplListExpr(object[] elements) {
  707. _elements = elements;
  708. }
  709. public override string ToString() {
  710. return "<ListExpr " + _elements.ToString() + ">";
  711. }
  712. }
  713. public class SymplFunCallExpr : SymplExpr {
  714. private SymplExpr _fun;
  715. private SymplExpr[] _args;
  716. public SymplFunCallExpr(SymplExpr fun, SymplExpr[] args) {
  717. _fun = fun;
  718. _args = args;
  719. }
  720. public SymplExpr Function { get { return _fun; } }
  721. public SymplExpr[] Arguments { get { return _args; } }
  722. public override string ToString() {
  723. return "<Funcall ( " + _fun.ToString() + " " + _args.ToString() + " )>";
  724. }
  725. }
  726. public class SymplDefunExpr : SymplExpr {
  727. private string _name;
  728. private IdOrKeywordToken[] _params;
  729. private SymplExpr[] _body;
  730. public SymplDefunExpr(string name, IdOrKeywordToken[] parms,
  731. SymplExpr[] body) {
  732. _name = name;
  733. _params = parms;
  734. _body = body;
  735. }
  736. public string Name { get { return _name; } }
  737. public IdOrKeywordToken[] Params { get { return _params; } }
  738. public SymplExpr[] Body { get { return _body; } }
  739. public override string ToString() {
  740. return "<Defun " + _name + " (" + _body.ToString() + ") ...>";
  741. }
  742. }
  743. public class SymplLambdaExpr : SymplExpr {
  744. private IdOrKeywordToken[] _params;
  745. private SymplExpr[] _body;
  746. public SymplLambdaExpr(IdOrKeywordToken[] parms, SymplExpr[] body) {
  747. _params = parms;
  748. _body = body;
  749. }
  750. public IdOrKeywordToken[] Params { get { return _params; } }
  751. public SymplExpr[] Body { get { return _body; } }
  752. public override string ToString() {
  753. return "<Lambda " + " (" + _params.ToString() + ") ...>";
  754. }
  755. }
  756. // Used to represent numbers and strings, but not Quote.
  757. public class SymplLiteralExpr : SymplExpr {
  758. private object _value;
  759. public object Value { get { return _value; } }
  760. public SymplLiteralExpr(object val) {
  761. _value = val;
  762. }
  763. public override string ToString() {
  764. return "<LiteralExpr " + _value.ToString() +">";
  765. }
  766. }
  767. public class SymplDottedExpr : SymplExpr {
  768. private SymplExpr _obj;
  769. // exprs is always a list of SymplIdExprs or SymplFunCallExprs,
  770. // ending with a SymplIdExpr when used as SymplFunCallExpr.Function.
  771. private SymplExpr[] _exprs;
  772. public SymplExpr ObjectExpr { get { return _obj; } }
  773. public SymplExpr[] Exprs { get { return _exprs; } }
  774. public SymplDottedExpr(SymplExpr obj, SymplExpr[] exprs) {
  775. _obj = obj;
  776. _exprs = exprs;
  777. }
  778. public override string ToString() {
  779. return "<DotExpr " + _obj.ToString() + "." + _exprs.ToString() + ">";
  780. }
  781. }
  782. public class SymplImportExpr : SymplExpr {
  783. private IdOrKeywordToken[] _nsOrModule;
  784. private IdOrKeywordToken[] _members;
  785. private IdOrKeywordToken[] _asNames;
  786. public SymplImportExpr(IdOrKeywordToken[] nsOrModule,
  787. IdOrKeywordToken[] members,
  788. IdOrKeywordToken[] asNames) {
  789. _nsOrModule = nsOrModule;
  790. _members = members;
  791. _asNames = asNames;
  792. }
  793. public IdOrKeywordToken[] NamespaceExpr { get { return _nsOrModule; } }
  794. public IdOrKeywordToken[] MemberNames { get { return _members; } }
  795. public IdOrKeywordToken[] Renames { get { return _asNames; } }
  796. public override string ToString() {
  797. return "<ImportExpr>";
  798. }
  799. }
  800. public class SymplAssignExpr : SymplExpr {
  801. private SymplExpr _lhs;
  802. private SymplExpr _value;
  803. public SymplAssignExpr(SymplExpr lhs, SymplExpr value) {
  804. _lhs = lhs;
  805. _value = value;
  806. }
  807. public SymplExpr Location { get { return _lhs; } }
  808. public SymplExpr Value { get { return _value; } }
  809. public override string ToString() {
  810. return "<AssignExpr " + _lhs.ToString() + "=" + _value.ToString() + ">";
  811. }
  812. }
  813. public class SymplLetStarExpr : SymplExpr {
  814. private LetBinding[] _bindings;
  815. private SymplExpr[] _body ;
  816. public SymplLetStarExpr(LetBinding[] bindings,
  817. SymplExpr[] body) {
  818. _bindings = bindings;
  819. _body = body;
  820. }
  821. public LetBinding[] Bindings {
  822. get { return _bindings; }
  823. }
  824. public SymplExpr[] Body { get { return _body; } }
  825. public override string ToString() {
  826. return "<Let* (" + _bindings.ToString() + ")" + _body.ToString() + ">";
  827. }
  828. }
  829. // Represents a binding defined in a LetStarExpr
  830. public class LetBinding {
  831. private IdOrKeywordToken _variable;
  832. private SymplExpr _value;
  833. public LetBinding(IdOrKeywordToken variable, SymplExpr value) {
  834. _variable = variable;
  835. _value = value;
  836. }
  837. public IdOrKeywordToken Variable { get { return _variable; } }
  838. public SymplExpr Value { get { return _value; } }
  839. }
  840. public class SymplBlockExpr : SymplExpr {
  841. private SymplExpr[] _body ;
  842. public SymplBlockExpr(SymplExpr[] body) {
  843. _body = body;
  844. }
  845. public SymplExpr[] Body { get { return _body; } }
  846. public override string ToString() {
  847. return "<Block* (" + _body.ToString() + ">";
  848. }
  849. }
  850. public class SymplEltExpr : SymplExpr {
  851. private SymplExpr _obj;
  852. private SymplExpr[] _indexes;
  853. public SymplEltExpr(SymplExpr obj, SymplExpr[] indexes) {
  854. _obj = obj;
  855. _indexes = indexes;
  856. }
  857. public SymplExpr ObjectExpr { get { return _obj; } }
  858. public SymplExpr[] Indexes { get { return _indexes; } }
  859. public override string ToString() {
  860. return "<EltExpr " + _obj.ToString() + "[" + _indexes.ToString() + "] >";
  861. }
  862. }
  863. public class SymplQuoteExpr : SymplExpr {
  864. // Expr must be SymplListExpr, SymplIdExpr, or SymplLIteralExpr
  865. private object _expr;
  866. public SymplQuoteExpr(object expr) {
  867. _expr = expr;
  868. }
  869. public object Expr { get { return _expr; } }
  870. public override string ToString() {
  871. return "<QuoteExpr " + _expr.ToString() + ">";
  872. }
  873. }
  874. public class SymplEqExpr : SymplExpr {
  875. private SymplExpr _left;
  876. private SymplExpr _right;
  877. public SymplEqExpr (SymplExpr left, SymplExpr right) {
  878. _left = left;
  879. _right = right;
  880. }
  881. public SymplExpr Left { get {return _left;}}
  882. public SymplExpr Right { get {return _right;}}
  883. }
  884. public class SymplConsExpr : SymplExpr {
  885. private SymplExpr _left;
  886. private SymplExpr _right;
  887. public SymplConsExpr (SymplExpr left, SymplExpr right) {
  888. _left = left;
  889. _right = right;
  890. }
  891. public SymplExpr Left { get {return _left;}}
  892. public SymplExpr Right { get {return _right;}}
  893. }
  894. public class SymplListCallExpr : SymplExpr {
  895. private SymplExpr[] _elements;
  896. // This is always a list of Tokens or SymplListExprs.
  897. public SymplExpr[] Elements { get { return _elements; } }
  898. public SymplListCallExpr(SymplExpr[] elements) {
  899. _elements = elements;
  900. }
  901. }
  902. public class SymplIfExpr : SymplExpr {
  903. private SymplExpr _test;
  904. private SymplExpr _consequent;
  905. private SymplExpr _alternative;
  906. public SymplIfExpr (SymplExpr test, SymplExpr consequent,
  907. SymplExpr alternative) {
  908. _test = test;
  909. _consequent = consequent;
  910. _alternative = alternative;
  911. }
  912. public SymplExpr Test {
  913. get { return _test;}
  914. }
  915. public SymplExpr Consequent {
  916. get { return _consequent;}
  917. }
  918. public SymplExpr Alternative {
  919. get { return _alternative;}
  920. }
  921. }
  922. public class SymplLoopExpr : SymplExpr {
  923. private SymplExpr[] _body;
  924. public SymplLoopExpr(SymplExpr[] body) {
  925. _body = body;
  926. }
  927. public SymplExpr[] Body {
  928. get { return _body; }
  929. }
  930. public override string ToString() {
  931. return "<Loop ...>";
  932. }
  933. }
  934. public class SymplBreakExpr : SymplExpr {
  935. private SymplExpr _value;
  936. public SymplBreakExpr (SymplExpr value) {
  937. // Can be null.
  938. _value = value;
  939. }
  940. public SymplExpr Value {
  941. get { return _value; }
  942. }
  943. public override string ToString() {
  944. return "<Break ...)>";
  945. }
  946. }
  947. public class SymplNewExpr : SymplExpr {
  948. private SymplExpr _type;
  949. private SymplExpr[] _arguments;
  950. public SymplExpr Type { get { return _type; } }
  951. public SymplExpr[] Arguments { get { return _arguments; } }
  952. public SymplNewExpr(SymplExpr type, SymplExpr[] arguments) {
  953. _type = type;
  954. _arguments = arguments;
  955. }
  956. }
  957. public class SymplBinaryExpr : SymplExpr {
  958. private SymplExpr _left;
  959. private SymplExpr _right;
  960. ExpressionType _operation;
  961. public SymplExpr Left { get { return _left; } }
  962. public SymplExpr Right { get { return _right; } }
  963. public ExpressionType Operation { get { return _operation; } }
  964. public SymplBinaryExpr(SymplExpr left, SymplExpr right, ExpressionType operation) {
  965. _left = left;
  966. _right = right;
  967. _operation = operation;
  968. }
  969. }
  970. public class SymplUnaryExpr : SymplExpr {
  971. private SymplExpr _operand;
  972. ExpressionType _operation;
  973. public SymplExpr Operand { get { return _operand; } }
  974. public ExpressionType Operation { get { return _operation; } }
  975. public SymplUnaryExpr(SymplExpr expression, ExpressionType operation) {
  976. _operand = expression;
  977. _operation = operation;
  978. }
  979. }
  980. public class SymplParseException : Exception {
  981. public SymplParseException(string msg) : base(msg) { }
  982. }
  983. } //SymplSample