Parser.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // $Id$
  2. using System;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Collections;
  6. namespace Lisp
  7. {
  8. /// <summary>
  9. /// Lisp parser
  10. /// </summary>
  11. /// <seealso cref="Lexer"/>
  12. public sealed class Parser {
  13. private Lexer Lexer;
  14. private Lexer.Token Token;
  15. public Parser(Lexer Lexer) {
  16. this.Lexer = Lexer;
  17. }
  18. public List Parse() {
  19. Token = Lexer.GetNextToken();
  20. if(Token != Lexer.Token.OPEN_PAREN)
  21. ParseError("file does not start with '('");
  22. List Result = InternParse();
  23. if(Token != Lexer.Token.EOF) {
  24. if(Token == Lexer.Token.CLOSE_PAREN)
  25. ParseError("too many ')'");
  26. else
  27. ParseError("extra tokens at end of file");
  28. }
  29. return Result;
  30. }
  31. private List InternParse() {
  32. ArrayList Entries = new ArrayList();
  33. while(Token != Lexer.Token.CLOSE_PAREN && Token != Lexer.Token.EOF) {
  34. switch(Token) {
  35. case Lexer.Token.OPEN_PAREN:
  36. Token = Lexer.GetNextToken();
  37. if(Token == Lexer.Token.SYMBOL
  38. && Lexer.TokenString == "_") {
  39. Token = Lexer.GetNextToken();
  40. if(Token != Lexer.Token.STRING)
  41. ParseError("Expected string after '(_ ' sequence");
  42. // TODO translate
  43. Entries.Add(Lexer.TokenString);
  44. Token = Lexer.GetNextToken();
  45. if(Token != Lexer.Token.CLOSE_PAREN)
  46. ParseError("Expected ')' after '(_ \"\"' sequence");
  47. break;
  48. }
  49. Entries.Add(InternParse());
  50. if(Token != Lexer.Token.CLOSE_PAREN)
  51. ParseError("Expected ')' token, got " + Token);
  52. break;
  53. case Lexer.Token.SYMBOL:
  54. Entries.Add(new Symbol(Lexer.TokenString));
  55. break;
  56. case Lexer.Token.STRING:
  57. Entries.Add(Lexer.TokenString);
  58. break;
  59. case Lexer.Token.INTEGER:
  60. int ival = Int32.Parse(Lexer.TokenString, NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
  61. Entries.Add(ival);
  62. break;
  63. case Lexer.Token.REAL:
  64. float fval = Single.Parse(Lexer.TokenString, NumberStyles.Float, NumberFormatInfo.InvariantInfo);
  65. Entries.Add(fval);
  66. break;
  67. case Lexer.Token.TRUE:
  68. Entries.Add(true);
  69. break;
  70. case Lexer.Token.FALSE:
  71. Entries.Add(false);
  72. break;
  73. default:
  74. ParseError("Unexpected Token " + Token);
  75. break;
  76. }
  77. Token = Lexer.GetNextToken();
  78. }
  79. return new List(Entries.ToArray());
  80. }
  81. private void ParseError(string Message) {
  82. throw new LispException("Parse error in line "
  83. + Lexer.LineNumber + ": " + Message);
  84. }
  85. }
  86. }