read.red 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. %
  2. % READ.RED - S-expression parser
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 28 August 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % <PSL.KERNEL>READ.RED.6, 20-Oct-82 11:07:28, Edit by BENSON
  12. % Extra right paren in file only prints warning, not error
  13. % <PSL.KERNEL>READ.RED.5, 6-Oct-82 11:37:33, Edit by BENSON
  14. % Took away CATCH in READ, EOF error binds *InsideStructureRead to NIL
  15. % <PSL.KERNEL>READ.RED.2, 20-Sep-82 11:24:32, Edit by BENSON
  16. % Right parens at top level cause an error in a file
  17. % <PSL.INTERP>READ.RED.6, 2-Sep-82 14:07:37, Edit by BENSON
  18. % Right parens are ignored at the top level
  19. fluid '(CurrentReadMacroIndicator!* % Get to find read macro function
  20. CurrentScanTable!* % vector of character types
  21. !*InsideStructureRead); % indicates within compound read
  22. global '(TokType!* % Set by token scanner, type of token
  23. LispScanTable!* % CurrentScanTable!* when READing
  24. IN!* % Current input channel
  25. !$EOF!$); % has value returned when EOF is read
  26. CurrentReadMacroIndicator!* := 'LispReadMacro;
  27. CompileTime flag('(DotContextError), 'InternalFunction);
  28. lisp procedure ChannelReadTokenWithHooks Channel; % Scan token w/read macros
  29. %
  30. % This is ReadToken with hooks for read macros
  31. %
  32. begin scalar Tkn, Fn;
  33. Tkn := ChannelReadToken Channel;
  34. if TokType!* eq 3 and (Fn := get(Tkn, CurrentReadMacroIndicator!*)) then
  35. return IDApply2(Channel, Tkn, Fn);
  36. return Tkn;
  37. end;
  38. lisp procedure ChannelRead Channel; %. Parse S-expression from channel
  39. begin scalar CurrentScanTable!*, CurrentReadMacroIndicator!*;
  40. CurrentScanTable!* := LispScanTable!*;
  41. CurrentReadMacroIndicator!* := 'LispReadMacro;
  42. return ChannelReadTokenWithHooks Channel;
  43. end;
  44. lisp procedure Read(); %. Parse S-expr from current input
  45. << MakeInputAvailable();
  46. ChannelRead IN!* >>;
  47. lisp procedure ChannelReadEof(Channel, Ef); % Handle end-of-file in Read
  48. if !*InsideStructureRead then return
  49. begin scalar !*InsideStructureRead;
  50. return
  51. StdError BldMsg("Unexpected EOF while reading on channel %r",
  52. Channel);
  53. end else !$EOF!$;
  54. lisp procedure ChannelReadQuotedExpression(Channel, Qt); % read macro '
  55. MkQuote ChannelReadTokenWithHooks Channel;
  56. lisp procedure ChannelReadListOrDottedPair(Channel, Pa); % read macro (
  57. %
  58. % Read list or dotted pair. Collect items until closing right paren.
  59. % Check for dot context errors.
  60. %
  61. begin scalar Elem, StartPointer, EndPointer, !*InsideStructureRead;
  62. !*InsideStructureRead := T;
  63. Elem := ChannelReadTokenWithHooks Channel;
  64. if TokType!* eq 3 then
  65. if Elem eq '!. then return DotContextError()
  66. else if Elem eq '!) then return NIL;
  67. StartPointer := EndPointer := list Elem;
  68. LoopBegin:
  69. Elem := ChannelReadTokenWithHooks Channel;
  70. if TokType!* eq 3 then
  71. if Elem eq '!) then return StartPointer
  72. else if Elem eq '!. then
  73. << Elem := ChannelReadTokenWithHooks Channel;
  74. if TokType!* eq 3 and (Elem eq '!) or Elem eq '!.) then
  75. return DotContextError()
  76. else
  77. << RplacD(EndPointer, Elem);
  78. Elem := ChannelReadTokenWithHooks Channel;
  79. if TokType!* eq 3 and Elem eq '!) then return StartPointer
  80. else return DotContextError() >> >>;
  81. % If we had splice macros, I think they would be checked here
  82. RplacD(EndPointer, list Elem);
  83. EndPointer := cdr EndPointer;
  84. goto LoopBegin;
  85. end;
  86. lisp procedure ChannelReadRightParen(Channel, Tok);
  87. % Ignore right parens at the top
  88. if !*InsideStructureRead then Tok
  89. else
  90. << if not (Channel eq StdIN!*) then % if not reading from the terminal
  91. ErrorPrintF "*** Unmatched right parenthesis";
  92. ChannelReadTokenWithHooks Channel >>;
  93. lisp procedure DotContextError(); % Parsing error
  94. IOError "Dot context error";
  95. % List2Vector is found in TYPE-CONVERSIONS.RED
  96. lisp procedure ChannelReadVector Channel; % read macro [
  97. begin scalar Elem, StartPointer, EndPointer, !*InsideStructureRead;
  98. !*InsideStructureRead := T;
  99. StartPointer := EndPointer := (NIL . NIL);
  100. while << Elem := ChannelReadTokenWithHooks Channel;
  101. TokType!* neq 3 or Elem neq '!] >> do
  102. << RplacD(EndPointer, list Elem);
  103. EndPointer := cdr EndPointer >>;
  104. return List2Vector cdr StartPointer;
  105. end;
  106. StartupTime <<
  107. put('!', 'LispReadMacro, function ChannelReadQuotedExpression);
  108. put('!( , 'LispReadMacro, function ChannelReadListOrDottedPair);
  109. put('!) , 'LispReadMacro, function ChannelReadRightParen);
  110. put('![, 'LispReadMacro, function ChannelReadVector);
  111. put(MkID char EOF, 'LispReadMacro, function ChannelReadEOF);
  112. >>;
  113. END;