ReaderTypespec.java 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright (c) 2001 Per M.A. Bothner
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.kawa.lispexpr;
  4. import gnu.text.*;
  5. import gnu.kawa.io.InPort;
  6. /** Reader table entry for {@code '<'} to treat {@code '['}
  7. * and {@code ']'} as constituents.
  8. * Lets us use (say) {@code har[]>} as a token even if {@code '['}
  9. * and {@code ']'} are parens.
  10. * @author Bruce R. Lewis.
  11. */
  12. public class ReaderTypespec extends ReaderConstituent
  13. {
  14. public ReaderTypespec() { super(ReadTable.NON_TERMINATING_MACRO); }
  15. public Object read (Lexer in, int ch, int count)
  16. throws java.io.IOException, SyntaxException
  17. {
  18. if (! (in instanceof LispReader))
  19. return super.read(in, ch, count);
  20. int endChar = ch == '<' ? '>' : -2;
  21. LispReader reader = (LispReader) in;
  22. int startPos = in.tokenBufferLength;
  23. InPort port = in.getPort();
  24. ReadTable rtable = ReadTable.getCurrent();
  25. char saveReadState = '\0';
  26. in.tokenBufferAppend(ch);
  27. int c = ch;
  28. int prev;
  29. if (port instanceof InPort)
  30. {
  31. saveReadState = ((InPort) port).readState;
  32. ((InPort) port).readState = (char) ch;
  33. }
  34. try
  35. {
  36. boolean got_open_square = false;
  37. for (;;)
  38. {
  39. int next;
  40. prev = c;
  41. if (port.pos < port.limit && prev != '\n')
  42. c = port.buffer[port.pos++];
  43. else
  44. c = port.read();
  45. if (c == '\\')
  46. {
  47. in.tokenBufferAppend(LispReader.TOKEN_ESCAPE_CHAR);
  48. reader.seenEscapes = true;
  49. }
  50. else if (c == endChar && ! got_open_square)
  51. {
  52. reader.readToken('>', rtable);
  53. break;
  54. }
  55. else
  56. {
  57. int kind;
  58. if ( (!got_open_square && c == '['
  59. && true == (got_open_square = true))
  60. || (got_open_square && c == ']'
  61. && false == (got_open_square = false))
  62. || ((kind = rtable.lookup(c).getKind())
  63. == ReadTable.CONSTITUENT
  64. || kind == ReadTable.NON_TERMINATING_MACRO))
  65. {
  66. in.tokenBufferAppend(c);
  67. continue;
  68. }
  69. else
  70. {
  71. in.unread(c);
  72. break;
  73. }
  74. }
  75. }
  76. return reader.handleToken(startPos, rtable);
  77. }
  78. finally
  79. {
  80. in.tokenBufferLength = startPos;
  81. if (port instanceof InPort)
  82. ((InPort) port).readState = saveReadState;
  83. }
  84. }
  85. }