Substantial work on read-list, not yet fully working.

This commit is contained in:
Simon Brooke 2026-05-06 23:42:25 +01:00
parent 80049f2272
commit 6b89779bab
5 changed files with 127 additions and 11 deletions

View file

@ -87,6 +87,13 @@ struct pso_pointer read_example( struct pso_pointer frame_pointer ) {
return result;
}
struct pso_pointer make_eof_exception( struct pso_pointer frame_pointer) {
return make_exception( make_frame( 1, frame_pointer,
c_string_to_lisp_string
( frame_pointer,
L"Read: end of input while reading" ) ) );
}
/**
* Function: return the next character from the stream indicated by arg 0;
* further arguments are ignored.
@ -115,6 +122,71 @@ struct pso_pointer read_character( struct pso_pointer frame_pointer ) {
return result;
}
/**
* @brief advance the `stream` indicated in arg[0] of this stack frame over any
* whitespace characters. The character indicated by arg[2] will be treated as
* potentially the first such character. Returns the first non-space character
* encountered, or an exception.
*/
struct pso_pointer skip_whitespace( struct pso_pointer frame_pointer ) {
struct pso4 *frame = pointer_to_pso4( frame_pointer );
struct pso_pointer stream = fetch_arg( frame, 0 );
struct pso_pointer readtable = fetch_arg( frame, 1 );
struct pso_pointer character = fetch_arg( frame, 2 );
struct pso_pointer result = nil;
if (characterp(character)) {
wchar_t wc = pointer_to_object(character)->payload.character.character;
if (!iswspace( wc) && wc != L',') {
result = character;
}
}
if (c_nilp( result) && readp( stream)) {
URL_FILE* input = pointer_to_object(stream)->payload.stream.stream;
wint_t wc = url_fgetwc( input);
while ( iswspace(wc) || wc==L',') { wc = url_fgetwc( input); }
result = (wc == WEOF) ? make_eof_exception(frame_pointer) : make_character(frame_pointer, wc);
}
return result;
}
struct pso_pointer read_list( struct pso_pointer frame_pointer ) {
struct pso4 *frame = pointer_to_pso4( frame_pointer );
struct pso_pointer stream = fetch_arg( frame, 0 );
struct pso_pointer readtable = fetch_arg( frame, 1 );
struct pso_pointer character = fetch_arg( frame, 2 );
struct pso_pointer result = nil;
if (!c_nilp(character) && characterp(character) &&
pointer_to_object(character)->payload.character.character == SYNTAX_LPAR) {
// it's OK if an LPAR is passed in, but we don't want it now.
character = nil;
}
if (!c_nilp( character)) {
// if anything other than LPAR is passed in as character, TODO: throw exception.
}
while ( c_nilp(character) || (characterp(character) &&
pointer_to_object(character)->payload.character.character != SYNTAX_RPAR)) {
character = skip_whitespace( make_frame(3, frame_pointer, stream, readtable, character));
struct pso_pointer r = read( make_frame(3, frame_pointer, stream, readtable, character));
if (exceptionp(r)) {
result = r;
break;
} else {
result = make_cons( frame_pointer, r, result);
character = skip_whitespace( make_frame(3, frame_pointer, stream, readtable, character));
}
}
return consp(result) ? c_reverse( frame_pointer, result) : result;
}
/**
* @brief Read one integer from the stream and return it.
*
@ -226,7 +298,7 @@ struct pso_pointer read( struct pso_pointer frame_pointer ) {
}
if ( c_nilp( character ) ) {
character = read_character( make_frame( 1, frame_pointer, stream ) );
character = skip_whitespace( make_frame( 1, frame_pointer, stream ) );
}
struct pso_pointer readmacro = c_assoc( character, readtable );
@ -239,16 +311,16 @@ struct pso_pointer read( struct pso_pointer frame_pointer ) {
URL_FILE *input = pointer_to_object( stream )->payload.stream.stream;
switch ( c ) {
case ';':
case SYNTAX_SEMICOLON:
for ( c = url_fgetwc( input ); c != '\n';
c = url_fgetwc( input ) );
/* skip all characters from semi-colon to the end of the line */
break;
case SYNTAX_LPAR:
result = read_list( make_frame(3, stream, readtable, character));
break;
case EOF:
result = make_exception( make_frame( 1, frame_pointer,
c_string_to_lisp_string
( frame_pointer,
L"Read: end of input while reading" ) ) );
result = make_eof_exception(frame_pointer);
break;
default:
struct pso_pointer next = make_frame( 3, frame_pointer, stream,