summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2012-01-02 20:24:43 +0000
committerAdrian Thurston <thurston@complang.org>2012-01-02 20:24:43 +0000
commit38e5314851fba1e548ea687519044644a8941879 (patch)
tree8f25cc8d3743872aeb163c378b897f9a15fe1f39
parentec497371a7fcab2aa2b0bbb21cb4c5064d5970e1 (diff)
downloadcolm-38e5314851fba1e548ea687519044644a8941879.tar.gz
Need symmetrical do/undo for append/prepend to streams. Can't use the consume
functions because in some instances streams are called. The undo of the prepend needs to distinguish between tree and data.
-rw-r--r--colm/input.c127
-rw-r--r--colm/input.h6
-rw-r--r--colm/pdarun.c29
3 files changed, 101 insertions, 61 deletions
diff --git a/colm/input.c b/colm/input.c
index ceed6bf3..a4deb06c 100644
--- a/colm/input.c
+++ b/colm/input.c
@@ -632,54 +632,97 @@ void undoConsumeLangEl( InputStream *is )
}
}
-
void prependData( InputStream *is, const char *data, long length )
{
-/// if ( isSourceStream( is ) ) {
-/// Stream *stream = (Stream*)is->queue->tree;
-/// return stream->in->funcs->prependData( stream->in, data, length );
-/// }
-/// else {
- // #ifdef COLM_LOG_PARSE
- // if ( colm_log_parse ) {
- // cerr << "readying fake push" << endl;
- // }
- // #endif
-
- // takeBackBuffered( inputStream );
-
- /* Create a new buffer for the data. This is the easy implementation.
- * Something better is needed here. It puts a max on the amount of
- * data that can be pushed back to the inputStream. */
- assert( length < FSM_BUFSIZE );
+ /* Create a new buffer for the data. This is the easy implementation.
+ * Something better is needed here. It puts a max on the amount of
+ * data that can be pushed back to the inputStream. */
+ assert( length < FSM_BUFSIZE );
- RunBuf *newBuf = newRunBuf();
- newBuf->length = length;
- memcpy( newBuf->data, data, length );
+ RunBuf *newBuf = newRunBuf();
+ newBuf->length = length;
+ memcpy( newBuf->data, data, length );
- inputStreamPrepend( is, newBuf );
-// }
+ inputStreamPrepend( is, newBuf );
}
-Tree *undoPrependData( InputStream *is, int length )
+int undoPrependData( InputStream *is, int length )
{
-// if ( isSourceStream( is ) ) {
-// Stream *stream = (Stream*)is->queue->tree;
-// return stream->in->funcs->undoPrependData( stream->in, length );
-// }
-// else {
- if ( is->queue->type == RunBufDataType ) {
- consumeData( is, length );
- return 0;
+ debug( REALM_INPUT, "consuming %d bytes\n", length );
+
+ int consumed = 0;
+
+ /* Move over skip bytes. */
+ while ( true ) {
+ RunBuf *buf = is->queue;
+
+ if ( buf == 0 )
+ break;
+
+ if ( buf->type == RunBufSourceType ) {
+ Stream *stream = (Stream*)buf->tree;
+ int slen = stream->in->funcs->consumeData( stream->in, length );
+
+ consumed += slen;
+ length -= slen;
}
+ else if ( buf->type == RunBufTokenType )
+ break;
+ else if ( buf->type == RunBufIgnoreType )
+ break;
else {
- /* FIXME: leak here. */
- RunBuf *rb = inputStreamPopHead( is );
- Tree *tree = rb->tree;
- free(rb);
- return tree;
+ /* Anything available in the current buffer. */
+ int avail = buf->length - buf->offset;
+ if ( avail > 0 ) {
+ /* The source data from the current buffer. */
+ int slen = avail <= length ? avail : length;
+ consumed += slen;
+ length -= slen;
+ buf->offset += slen;
+ }
}
-// }
+
+ if ( length == 0 )
+ break;
+
+ RunBuf *runBuf = inputStreamPopHead( is );
+ free( runBuf );
+ }
+
+ return consumed;
+}
+
+void prependTree( InputStream *is, Tree *tree, int ignore )
+{
+ if ( is->attached1 != 0 )
+ detachInput1( is->attached1, is );
+
+ /* Create a new buffer for the data. This is the easy implementation.
+ * Something better is needed here. It puts a max on the amount of
+ * data that can be pushed back to the inputStream. */
+ RunBuf *newBuf = newRunBuf();
+ newBuf->type = ignore ? RunBufIgnoreType : RunBufTokenType;
+ newBuf->tree = tree;
+ inputStreamPrepend( is, newBuf );
+}
+
+Tree *undoPrependTree( InputStream *is )
+{
+ while ( is->queue != 0 && is->queue->type == RunBufDataType && is->queue->offset == is->queue->length ) {
+ RunBuf *runBuf = inputStreamPopHead( is );
+ free( runBuf );
+ }
+
+ if ( is->queue != 0 && (is->queue->type == RunBufTokenType || is->queue->type == RunBufIgnoreType) ) {
+ RunBuf *runBuf = inputStreamPopHead( is );
+
+ /* FIXME: using runbufs here for this is a poor use of memory. */
+ Tree *tree = runBuf->tree;
+ free(runBuf);
+ return tree;
+ }
+
+ return 0;
}
void appendData( InputStream *is, const char *data, long len )
@@ -766,3 +809,11 @@ Tree *undoAppendStream( InputStream *in )
free( runBuf );
return tree;
}
+
+Tree *undoAppendTree( InputStream *in )
+{
+ RunBuf *runBuf = inputStreamPopTail( in );
+ Tree *tree = runBuf->tree;
+ free( runBuf );
+ return tree;
+}
diff --git a/colm/input.h b/colm/input.h
index 0f43eaaa..773b1bc8 100644
--- a/colm/input.h
+++ b/colm/input.h
@@ -195,13 +195,17 @@ void setEof( InputStream *is );
void unsetEof( InputStream *is );
void prependData( InputStream *in, const char *data, long len );
-struct ColmTree *undoPrependData( InputStream *in, int length );
+int undoPrependData( InputStream *is, int length );
+
+void prependTree( InputStream *is, struct ColmTree *tree, int ignore );
+struct ColmTree *undoPrependTree( InputStream *is );
void appendData( InputStream *in, const char *data, long len );
void appendTree( InputStream *in, struct ColmTree *tree );
void appendStream( InputStream *in, struct ColmTree *tree );
struct ColmTree *undoAppendData( InputStream *in, int length );
struct ColmTree *undoAppendStream( InputStream *in );
+struct ColmTree *undoAppendTree( InputStream *in );
#ifdef __cplusplus
}
diff --git a/colm/pdarun.c b/colm/pdarun.c
index f2e6317a..4e991da8 100644
--- a/colm/pdarun.c
+++ b/colm/pdarun.c
@@ -171,23 +171,25 @@ void streamPushText( FsmRun *fsmRun, InputStream *inputStream, const char *data,
void streamPushTree( FsmRun *fsmRun, InputStream *inputStream, Tree *tree, int ignore )
{
- undoConsumeTree( inputStream, tree, ignore );
+ prependTree( inputStream, tree, ignore );
}
void undoStreamPush( Program *prg, Tree **sp, FsmRun *fsmRun, InputStream *inputStream, long length )
{
if ( length < 0 )
- consumeTree( inputStream );
+ undoPrependTree( inputStream );
else
- consumeData( inputStream, length );
+ undoPrependData( inputStream, length );
}
void undoStreamAppend( Program *prg, Tree **sp, FsmRun *fsmRun, InputStream *inputStream, Tree *input, long length )
{
- if ( input->id == LEL_ID_STREAM )
+ if ( input->id == LEL_ID_STR )
+ undoAppendData( inputStream, length );
+ else if ( input->id == LEL_ID_STREAM )
undoAppendStream( inputStream );
else
- undoAppendData( inputStream, length );
+ undoAppendTree( inputStream );
}
/* Should only be sending back whole tokens/ignores, therefore the send back
@@ -200,24 +202,7 @@ static void sendBackText( FsmRun *fsmRun, InputStream *inputStream, const char *
if ( length == 0 )
return;
-// if ( fsmRun->p == fsmRun->runBuf->data )
-// sendBackRunBufHead( fsmRun, inputStream );
-
- /* If there is data in the current buffer then send the whole send back
- * should be in this buffer. */
- //clearBuffered( fsmRun );
-
- /* slide data back. */
-// fsmRun->p = fsmRun->pe = fsmRun->runBuf->data;
undoConsumeData( fsmRun, inputStream, data, length );
-
-// #if COLM_LOG
-// if ( memcmp( data, fsmRun->p, length ) != 0 )
-// debug( REALM_PARSE, "mismatch of pushed back text\n" );
-// #endif
-
-// assert( memcmp( data, fsmRun->p, length ) == 0 );
-
undoPosition( inputStream, data, length );
}