diff options
author | Adrian Thurston <thurston@colm.net> | 2018-07-07 12:36:30 +0800 |
---|---|---|
committer | Adrian Thurston <thurston@colm.net> | 2018-07-07 12:36:30 +0800 |
commit | deb9efc408109ad13846d2d6d3b1fe0e2f62ddf2 (patch) | |
tree | 9a6f10b24888673c52ff9d56a86a7e0ad02bfb04 /src/synthesis.cc | |
parent | 13627232094ba6b31937448f011553f44b1f8519 (diff) | |
download | colm-deb9efc408109ad13846d2d6d3b1fe0e2f62ddf2.tar.gz |
make it possible to set parser input before parsing
Make it possible to set the parser input (sourced from some other parser) the
same way the parser context is set. Previously would "send" the input the same
way a stream was sent, but this was inconsistent with how the system operates.
The "send" of an input was actually a hack that replaced the input. We are not
supporting recursing input structures. Just an input and underneath that
possibly some streams or data.
Diffstat (limited to 'src/synthesis.cc')
-rw-r--r-- | src/synthesis.cc | 281 |
1 files changed, 156 insertions, 125 deletions
diff --git a/src/synthesis.cc b/src/synthesis.cc index d6f5cf4d..4eff7e99 100644 --- a/src/synthesis.cc +++ b/src/synthesis.cc @@ -1291,7 +1291,7 @@ UniqueType *LangTerm::evaluateNew( Compiler *pd, CodeVect &code ) const newUT->generic->elUt->langEl->contextIn != 0 ) { if ( fieldInitArgs == 0 || fieldInitArgs->length() != 1 ) - error(loc) << "parse command requires just input" << endp; + error(loc) << "parse command requires just context " << endp; context = true; } @@ -1316,14 +1316,20 @@ UniqueType *LangTerm::evaluateNew( Compiler *pd, CodeVect &code ) const * First load the context into the parser. */ if ( context ) { - /* Eval the context. */ - UniqueType *argUT = fieldInitArgs->data[0]->expr->evaluate( pd, code ); + for ( int i = 0; i < fieldInitArgs->length(); i++ ) { + /* Eval what we are initializing with. */ + UniqueType *argUT = fieldInitArgs->data[i]->expr->evaluate( pd, code ); - if ( argUT != pd->uniqueTypeStream && argUT->typeId != TYPE_STRUCT ) - error(loc) << "context argument must be a stream or a tree" << endp; - - /* Store the context. Leaves the parser on the stack. */ - code.append( IN_SET_PARSER_CONTEXT ); + if ( argUT == pd->uniqueTypeInput ) { + code.append( IN_SET_PARSER_INPUT ); + } + else if ( argUT->typeId == TYPE_STRUCT ) { + code.append( IN_SET_PARSER_CONTEXT ); + } + else { + error(loc) << "cannot initialize parser with this type, context or input only" << endp; + } + } } evaluateCapture( pd, code, newUT ); @@ -1474,9 +1480,9 @@ UniqueType *LangTerm::evaluateParse( Compiler *pd, CodeVect &code, int stopId = stop ? targetUT->langEl->id : 0; bool context = false; - if ( targetUT->langEl->contextIn != 0 ) { - if ( fieldInitArgs == 0 || fieldInitArgs->length() != 1 ) - error(loc) << "parse command requires just input" << endp; + if ( fieldInitArgs != 0 ) { + if ( fieldInitArgs == 0 || ( fieldInitArgs->length() != 1 && fieldInitArgs->length() != 2 ) ) + error(loc) << "parse command requires just context and input" << endp; context = true; } @@ -1509,82 +1515,97 @@ UniqueType *LangTerm::evaluateParse( Compiler *pd, CodeVect &code, * First load the context into the parser. */ if ( context ) { - /* Eval the context. */ - UniqueType *argUT = fieldInitArgs->data[0]->expr->evaluate( pd, code ); + for ( int i = 0; i < fieldInitArgs->length(); i++ ) { + /* Eval what we are initializing with. */ + UniqueType *argUT = fieldInitArgs->data[i]->expr->evaluate( pd, code ); - if ( argUT != pd->uniqueTypeStream && argUT->typeId != TYPE_STRUCT ) - error(loc) << "context argument must be a stream or a tree" << endp; - - /* Store the context. */ - code.append( IN_SET_PARSER_CONTEXT ); + if ( argUT == pd->uniqueTypeInput ) { + code.append( IN_SET_PARSER_INPUT ); + } + else if ( argUT->typeId == TYPE_STRUCT && targetUT->langEl->contextIn != 0 ) { + code.append( IN_SET_PARSER_CONTEXT ); + } + else { + error(loc) << "cannot initialize parser with this type, context or input only" << endp; + } + } } /*****************************/ code.append( IN_GET_PARSER_STREAM ); - for ( ConsItemList::Iter item = *parserText->list; item.lte(); item++ ) { - bool isInput = false; - bool isStream = false; - switch ( item->type ) { - case ConsItem::LiteralType: { - String result; - bool unusedCI; - prepareLitString( result, unusedCI, - item->prodEl->typeRef->pdaLiteral->data, - item->prodEl->typeRef->pdaLiteral->loc ); - - /* Make sure we have this string. */ - StringMapEl *mapEl = 0; - if ( pd->literalStrings.insert( result, &mapEl ) ) - mapEl->value = pd->literalStrings.length()-1; - - code.append( IN_LOAD_STR ); - code.appendWord( mapEl->value ); - break; - } - case ConsItem::InputText: { - /* Make sure we have this string. */ - StringMapEl *mapEl = 0; - if ( pd->literalStrings.insert( item->data, &mapEl ) ) - mapEl->value = pd->literalStrings.length()-1; - - code.append( IN_LOAD_STR ); - code.appendWord( mapEl->value ); - break; - } - case ConsItem::ExprType: { - UniqueType *ut = item->expr->evaluate( pd, code ); + if ( parserText->list->length() == 0 ) { + code.append( IN_SEND_NOTHING ); - if ( ut->typeId == TYPE_VOID ) { - /* Clear it away if return type is void. */ - code.append( IN_POP_VAL ); - continue; + /* Parse instruction, dependent on whether or not we are producing + * revert or commit code. */ + parseFrag( pd, code, stopId ); + } + else { + for ( ConsItemList::Iter item = *parserText->list; item.lte(); item++ ) { + bool isInput = false; + bool isStream = false; + switch ( item->type ) { + case ConsItem::LiteralType: { + String result; + bool unusedCI; + prepareLitString( result, unusedCI, + item->prodEl->typeRef->pdaLiteral->data, + item->prodEl->typeRef->pdaLiteral->loc ); + + /* Make sure we have this string. */ + StringMapEl *mapEl = 0; + if ( pd->literalStrings.insert( result, &mapEl ) ) + mapEl->value = pd->literalStrings.length()-1; + + code.append( IN_LOAD_STR ); + code.appendWord( mapEl->value ); + break; + } + case ConsItem::InputText: { + /* Make sure we have this string. */ + StringMapEl *mapEl = 0; + if ( pd->literalStrings.insert( item->data, &mapEl ) ) + mapEl->value = pd->literalStrings.length()-1; + + code.append( IN_LOAD_STR ); + code.appendWord( mapEl->value ); + break; } + case ConsItem::ExprType: { + UniqueType *ut = item->expr->evaluate( pd, code ); - if ( ut->typeId == TYPE_INT || ut->typeId == TYPE_BOOL ) - code.append( IN_INT_TO_STR ); + if ( ut->typeId == TYPE_VOID ) { + /* Clear it away if return type is void. */ + code.append( IN_POP_VAL ); + continue; + } - if ( ut == pd->uniqueTypeInput ) - isInput = true; - if ( ut == pd->uniqueTypeStream ) - isStream = true; + if ( ut->typeId == TYPE_INT || ut->typeId == TYPE_BOOL ) + code.append( IN_INT_TO_STR ); - break; - }} + if ( ut == pd->uniqueTypeInput ) + isInput = true; + if ( ut == pd->uniqueTypeStream ) + isStream = true; - if ( isInput ) - code.append( IN_REPLACE_STREAM ); - else if ( isStream ) - code.append( IN_SEND_STREAM_W ); - else if ( tree ) - code.append( IN_SEND_TREE_W ); - else - code.append( IN_SEND_TEXT_W ); + break; + }} + + if ( isInput ) + code.append( IN_REPLACE_STREAM ); + else if ( isStream ) + code.append( IN_SEND_STREAM_W ); + else if ( tree ) + code.append( IN_SEND_TREE_W ); + else + code.append( IN_SEND_TEXT_W ); - /* Parse instruction, dependent on whether or not we are producing - * revert or commit code. */ - parseFrag( pd, code, stopId ); + /* Parse instruction, dependent on whether or not we are producing + * revert or commit code. */ + parseFrag( pd, code, stopId ); + } } /* @@ -1629,66 +1650,76 @@ void LangTerm::evaluateSendParser( Compiler *pd, CodeVect &code, bool strings ) code.appendHalf( 0 ); } - /* Assign bind ids to the variables in the replacement. */ - for ( ConsItemList::Iter item = *parserText->list; item.lte(); item++ ) { - bool isInput = false; - bool isStream = false; - switch ( item->type ) { - case ConsItem::LiteralType: { - String result; - bool unusedCI; - prepareLitString( result, unusedCI, - item->prodEl->typeRef->pdaLiteral->data, - item->prodEl->typeRef->pdaLiteral->loc ); - - /* Make sure we have this string. */ - StringMapEl *mapEl = 0; - if ( pd->literalStrings.insert( result, &mapEl ) ) - mapEl->value = pd->literalStrings.length()-1; + if ( parserText->list->length() == 0 ) { + code.append( IN_SEND_NOTHING ); - code.append( IN_LOAD_STR ); - code.appendWord( mapEl->value ); - break; - } - case ConsItem::InputText: { - /* Make sure we have this string. */ - StringMapEl *mapEl = 0; - if ( pd->literalStrings.insert( item->data, &mapEl ) ) - mapEl->value = pd->literalStrings.length()-1; + /* Parse instruction, dependent on whether or not we are producing + * revert or commit code. */ + parseFrag( pd, code, 0 ); + } + else { - code.append( IN_LOAD_STR ); - code.appendWord( mapEl->value ); - break; - } - case ConsItem::ExprType: - UniqueType *ut = item->expr->evaluate( pd, code ); - if ( ut->typeId == TYPE_VOID ) { - /* Clear it away if return type is void. */ - code.append( IN_POP_VAL ); - continue; + /* Assign bind ids to the variables in the replacement. */ + for ( ConsItemList::Iter item = *parserText->list; item.lte(); item++ ) { + bool isInput = false; + bool isStream = false; + switch ( item->type ) { + case ConsItem::LiteralType: { + String result; + bool unusedCI; + prepareLitString( result, unusedCI, + item->prodEl->typeRef->pdaLiteral->data, + item->prodEl->typeRef->pdaLiteral->loc ); + + /* Make sure we have this string. */ + StringMapEl *mapEl = 0; + if ( pd->literalStrings.insert( result, &mapEl ) ) + mapEl->value = pd->literalStrings.length()-1; + + code.append( IN_LOAD_STR ); + code.appendWord( mapEl->value ); + break; + } + case ConsItem::InputText: { + /* Make sure we have this string. */ + StringMapEl *mapEl = 0; + if ( pd->literalStrings.insert( item->data, &mapEl ) ) + mapEl->value = pd->literalStrings.length()-1; + + code.append( IN_LOAD_STR ); + code.appendWord( mapEl->value ); + break; } + case ConsItem::ExprType: + UniqueType *ut = item->expr->evaluate( pd, code ); + if ( ut->typeId == TYPE_VOID ) { + /* Clear it away if return type is void. */ + code.append( IN_POP_VAL ); + continue; + } - if ( ut == pd->uniqueTypeInput ) - isInput = true; - if ( ut == pd->uniqueTypeStream ) - isStream = true; + if ( ut == pd->uniqueTypeInput ) + isInput = true; + if ( ut == pd->uniqueTypeStream ) + isStream = true; - if ( ut->typeId == TYPE_INT || ut->typeId == TYPE_BOOL ) - code.append( IN_INT_TO_STR ); + if ( ut->typeId == TYPE_INT || ut->typeId == TYPE_BOOL ) + code.append( IN_INT_TO_STR ); - break; - } + break; + } - if ( isInput ) - code.append( IN_REPLACE_STREAM ); - else if ( isStream ) - code.append( IN_SEND_STREAM_W ); - else if ( !strings ) - code.append( IN_SEND_TREE_W ); - else - code.append( IN_SEND_TEXT_W ); + if ( isInput ) + code.append( IN_REPLACE_STREAM ); + else if ( isStream ) + code.append( IN_SEND_STREAM_W ); + else if ( !strings ) + code.append( IN_SEND_TREE_W ); + else + code.append( IN_SEND_TEXT_W ); - parseFrag( pd, code, 0 ); + parseFrag( pd, code, 0 ); + } } if ( eof ) { |