/* * Copyright 2006-2018 Adrian Thurston * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "parser.h" #include #include #include #include using std::endl; void BaseParser::listElDef( String name ) { /* * The unique type. This is a def with a single empty form. */ ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, name, pd->nextObjectId++ ); LelProdList *prodList = new LelProdList; Production *prod = BaseParser::production( InputLoc(), new ProdElList, String(), false, 0, 0 ); prodAppend( prodList, prod ); NtDef *ntDef = NtDef::cons( name, curNspace(), curStruct(), false ); BaseParser::cflDef( ntDef, objectDef, prodList ); /* * List element with the same name as containing context. */ NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); String id = curStruct()->objectDef->name; RepeatType repeatType = RepeatNone; TypeRef *objTr = TypeRef::cons( InputLoc(), nspaceQual, id, repeatType ); TypeRef *elTr = TypeRef::cons( InputLoc(), TypeRef::ListPtrs, 0, objTr, 0 ); ObjectField *of = ObjectField::cons( InputLoc(), ObjectField::GenericElementType, elTr, name ); structVarDef( InputLoc(), of ); } void BaseParser::mapElDef( String name, TypeRef *keyType ) { /* * The unique type. This is a def with a single empty form. */ ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, name, pd->nextObjectId++ ); LelProdList *prodList = new LelProdList; Production *prod = BaseParser::production( InputLoc(), new ProdElList, String(), false, 0, 0 ); prodAppend( prodList, prod ); NtDef *ntDef = NtDef::cons( name, curNspace(), curStruct(), false ); BaseParser::cflDef( ntDef, objectDef, prodList ); /* * Same name as containing context. */ NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); String id = curStruct()->objectDef->name; TypeRef *objTr = TypeRef::cons( InputLoc(), nspaceQual, id, RepeatNone ); TypeRef *elTr = TypeRef::cons( InputLoc(), TypeRef::MapPtrs, 0, objTr, keyType ); ObjectField *of = ObjectField::cons( InputLoc(), ObjectField::GenericElementType, elTr, name ); structVarDef( InputLoc(), of ); } #if 0 void BaseParser::argvDecl() { String structName = "argv_el"; structHead( internal, pd->rootNamespace, structName, ObjectDef::StructType ); /* First the argv value. */ String name = "value"; String type = "str"; NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); TypeRef *typeRef = TypeRef::cons( internal, nspaceQual, type, RepeatNone ); ObjectField *objField = ObjectField::cons( internal, ObjectField::StructFieldType, typeRef, name ); structVarDef( objField->loc, objField ); pd->argvEl = objField->context; /* Now the list element. */ listElDef( "el" ); structStack.pop(); namespaceStack.pop(); } #endif void BaseParser::init() { /* Set up the root namespace. */ pd->rootNamespace = createRootNamespace(); /* Setup the global object. */ String global = "global"; pd->globalObjectDef = ObjectDef::cons( ObjectDef::UserType, global, pd->nextObjectId++ ); pd->rootNamespace->rootScope->owningObj = pd->globalObjectDef; pd->global = new StructDef( internal, global, pd->globalObjectDef ); pd->globalSel = declareStruct( pd, 0, global, pd->global ); /* Setup the input object. */ global = "_input"; ObjectDef *objectDef = ObjectDef::cons( ObjectDef::BuiltinType, global, pd->nextObjectId++ ); pd->input = new StructDef( internal, global, objectDef ); pd->inputSel = declareStruct( pd, pd->rootNamespace, pd->input->name, pd->input ); /* Setup the stream object. */ global = "stream"; objectDef = ObjectDef::cons( ObjectDef::BuiltinType, global, pd->nextObjectId++ ); pd->stream = new StructDef( internal, global, objectDef ); pd->streamSel = declareStruct( pd, pd->rootNamespace, pd->stream->name, pd->stream ); /* Initialize the dictionary of graphs. This is our symbol table. The * initialization needs to be done on construction which happens at the * beginning of a machine spec so any assignment operators can reference * the builtins. */ pd->initGraphDict(); pd->rootLocalFrame = ObjectDef::cons( ObjectDef::FrameType, "local", pd->nextObjectId++ ); localFrameTop = pd->rootLocalFrame; scopeTop = pd->rootLocalFrame->rootScope; /* Declarations of internal types. They must be declared now because we use * them directly, rather than via type lookup. */ pd->declareBaseLangEls(); pd->initUniqueTypes(); //argvDecl(); /* Internal variables. */ addArgvList(); addStdsList(); } void BaseParser::addRegularDef( const InputLoc &loc, Namespace *nspace, const String &name, LexJoin *join ) { GraphDictEl *newEl = nspace->rlMap.insert( name ); if ( newEl != 0 ) { /* New element in the dict, all good. */ newEl->value = new LexDefinition( name, join ); newEl->isInstance = false; newEl->loc = loc; } else { // Recover by ignoring the duplicate. error(loc) << "regular definition \"" << name << "\" already exists" << endl; } } TokenRegion *BaseParser::createRegion( const InputLoc &loc, RegionImpl *impl ) { TokenRegion *tokenRegion = new TokenRegion( loc, pd->regionList.length(), impl ); pd->regionList.append( tokenRegion ); return tokenRegion; } void BaseParser::pushRegionSet( const InputLoc &loc ) { RegionImpl *implTokenIgnore = new RegionImpl; RegionImpl *implTokenOnly = new RegionImpl; RegionImpl *implIgnoreOnly = new RegionImpl; pd->regionImplList.append( implTokenIgnore ); pd->regionImplList.append( implTokenOnly ); pd->regionImplList.append( implIgnoreOnly ); TokenRegion *tokenIgnore = createRegion( loc, implTokenIgnore ); TokenRegion *tokenOnly = createRegion( loc, implTokenOnly ); TokenRegion *ignoreOnly = createRegion( loc, implIgnoreOnly ); TokenRegion *collectIgnore = createRegion( loc, implIgnoreOnly ); RegionSet *regionSet = new RegionSet( implTokenIgnore, implTokenIgnore, implIgnoreOnly, tokenIgnore, tokenOnly, ignoreOnly, collectIgnore ); collectIgnore->ignoreOnly = ignoreOnly; pd->regionSetList.append( regionSet ); regionStack.push( regionSet ); } void BaseParser::popRegionSet() { regionStack.pop(); } Namespace *BaseParser::createRootNamespace() { /* Gets id of zero and default name. No parent. */ Namespace *nspace = new Namespace( internal, String("___ROOT_NAMESPACE"), 0, 0 ); nspace->rootScope->owningObj = pd->globalObjectDef; pd->namespaceList.append( nspace ); namespaceStack.push( nspace ); return nspace; } Namespace *BaseParser::createNamespace( const InputLoc &loc, const String &name ) { Namespace *parent = namespaceStack.top(); /* Make the new namespace. */ Namespace *nspace = parent->findNamespace( name ); if ( nspace == 0 ) { nspace = new Namespace( loc, name, pd->namespaceList.length(), parent ); /* Link the new namespace's scope to the parent namespace's scope. */ nspace->rootScope->parentScope = parent->rootScope; nspace->rootScope->owningObj = pd->globalObjectDef; parent->childNamespaces.append( nspace ); pd->namespaceList.append( nspace ); } namespaceStack.push( nspace ); return nspace; } Reduction *BaseParser::createReduction( const InputLoc loc, const String &name ) { Namespace *parent = namespaceStack.top(); Reduction *reduction = parent->findReduction( name ); if ( reduction == 0 ) { reduction = new Reduction( loc, name ); parent->reductions.append( reduction ); } reductionStack.push( reduction ); return reduction; } LexJoin *BaseParser::literalJoin( const InputLoc &loc, const String &data ) { Literal *literal = Literal::cons( loc, data, Literal::LitString ); LexFactor *factor = LexFactor::cons( literal ); LexFactorNeg *factorNeg = LexFactorNeg::cons( factor ); LexFactorRep *factorRep = LexFactorRep::cons( factorNeg ); LexFactorAug *factorAug = LexFactorAug::cons( factorRep ); LexTerm *term = LexTerm::cons( factorAug ); LexExpression *expr = LexExpression::cons( term ); LexJoin *join = LexJoin::cons( expr ); return join; } void BaseParser::defineToken( const InputLoc &loc, String name, LexJoin *join, ObjectDef *objectDef, CodeBlock *transBlock, bool ignore, bool noPreIgnore, bool noPostIgnore ) { bool pushedRegion = false; if ( !insideRegion() ) { if ( ignore ) error(loc) << "ignore tokens can only appear inside scanners" << endp; pushedRegion = true; pushRegionSet( internal ); } /* Check the name if this is a token. */ if ( !ignore && name == 0 ) error(loc) << "tokens must have a name" << endp; /* Give a default name to ignores. */ if ( name == 0 ) name.setAs( 32, "_ignore_%.4x", pd->nextTokenId ); Namespace *nspace = curNspace(); RegionSet *regionSet = regionStack.top(); TokenDef *tokenDef = TokenDef::cons( name, String(), false, ignore, join, transBlock, loc, 0, nspace, regionSet, objectDef, curStruct() ); regionSet->tokenDefList.append( tokenDef ); nspace->tokenDefList.append( tokenDef ); tokenDef->noPreIgnore = noPreIgnore; tokenDef->noPostIgnore = noPostIgnore; TokenInstance *tokenInstance = TokenInstance::cons( tokenDef, join, loc, pd->nextTokenId++, nspace, regionSet->tokenIgnore ); regionSet->tokenIgnore->impl->tokenInstanceList.append( tokenInstance ); tokenDef->noPreIgnore = noPreIgnore; tokenDef->noPostIgnore = noPostIgnore; if ( ignore ) { /* The instance for the ignore-only. */ TokenInstance *tokenInstanceIgn = TokenInstance::cons( tokenDef, join, loc, pd->nextTokenId++, nspace, regionSet->ignoreOnly ); tokenInstanceIgn->dupOf = tokenInstance; regionSet->ignoreOnly->impl->tokenInstanceList.append( tokenInstanceIgn ); } else { /* The instance for the token-only. */ TokenInstance *tokenInstanceTok = TokenInstance::cons( tokenDef, join, loc, pd->nextTokenId++, nspace, regionSet->tokenOnly ); tokenInstanceTok->dupOf = tokenInstance; regionSet->tokenOnly->impl->tokenInstanceList.append( tokenInstanceTok ); } /* This is created and pushed in the name. */ if ( pushedRegion ) popRegionSet(); if ( join != 0 ) { /* Create a regular language definition so the token can be used to * make other tokens */ addRegularDef( loc, curNspace(), name, join ); } } void BaseParser::zeroDef( const InputLoc &loc, const String &name ) { if ( !insideRegion() ) error(loc) << "zero token should be inside token" << endp; RegionSet *regionSet = regionStack.top(); Namespace *nspace = curNspace(); LexJoin *join = literalJoin( loc, String("`") ); TokenDef *tokenDef = TokenDef::cons( name, String(), false, false, join, 0, loc, 0, nspace, regionSet, 0, curStruct() ); tokenDef->isZero = true; regionSet->tokenDefList.append( tokenDef ); nspace->tokenDefList.append( tokenDef ); /* No token instance created. */ } void BaseParser::literalDef( const InputLoc &loc, const String &data, bool noPreIgnore, bool noPostIgnore ) { /* Create a name for the literal. */ String name( 32, "_literal_%.4x", pd->nextTokenId ); bool pushedRegion = false; if ( !insideRegion() ) { pushRegionSet( loc ); pushedRegion = true; } bool unusedCI; String interp; prepareLitString( interp, unusedCI, data, loc ); /* Look for the production's associated region. */ Namespace *nspace = curNspace(); RegionSet *regionSet = regionStack.top(); LiteralDictEl *ldel = nspace->literalDict.find( interp ); if ( ldel != 0 ) error( loc ) << "literal already defined in this namespace" << endp; LexJoin *join = literalJoin( loc, data ); ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, name, pd->nextObjectId++ ); /* The token definition. */ TokenDef *tokenDef = TokenDef::cons( name, data, true, false, join, 0, loc, 0, nspace, regionSet, objectDef, 0 ); regionSet->tokenDefList.append( tokenDef ); nspace->tokenDefList.append( tokenDef ); /* The instance for the token/ignore region. */ TokenInstance *tokenInstance = TokenInstance::cons( tokenDef, join, loc, pd->nextTokenId++, nspace, regionSet->tokenIgnore ); regionSet->tokenIgnore->impl->tokenInstanceList.append( tokenInstance ); ldel = nspace->literalDict.insert( interp, tokenInstance ); /* Make the duplicate for the token-only region. */ tokenDef->noPreIgnore = noPreIgnore; tokenDef->noPostIgnore = noPostIgnore; /* The instance for the token-only region. */ TokenInstance *tokenInstanceTok = TokenInstance::cons( tokenDef, join, loc, pd->nextTokenId++, nspace, regionSet->tokenOnly ); tokenInstanceTok->dupOf = tokenInstance; regionSet->tokenOnly->impl->tokenInstanceList.append( tokenInstanceTok ); if ( pushedRegion ) popRegionSet(); } void BaseParser::addArgvList() { TypeRef *valType = TypeRef::cons( internal, pd->uniqueTypeStr ); TypeRef *elType = TypeRef::cons( internal, TypeRef::ListEl, valType ); pd->argvTypeRef = TypeRef::cons( internal, TypeRef::List, 0, elType, valType ); } void BaseParser::addStdsList() { TypeRef *valType = TypeRef::cons( internal, pd->uniqueTypeStream ); TypeRef *elType = TypeRef::cons( internal, TypeRef::ListEl, valType ); pd->stdsTypeRef = TypeRef::cons( internal, TypeRef::List, 0, elType, valType ); } ObjectDef *BaseParser::blockOpen() { /* Init the object representing the local frame. */ ObjectDef *frame = ObjectDef::cons( ObjectDef::FrameType, "local", pd->nextObjectId++ ); localFrameTop = frame; scopeTop = frame->rootScope; return frame; } void BaseParser::blockClose() { localFrameTop = pd->rootLocalFrame; scopeTop = pd->rootLocalFrame->rootScope; } void BaseParser::functionDef( StmtList *stmtList, ObjectDef *localFrame, ParameterList *paramList, TypeRef *typeRef, const String &name, bool exprt ) { CodeBlock *codeBlock = CodeBlock::cons( stmtList, localFrame ); Function *newFunction = Function::cons( curNspace(), typeRef, name, paramList, codeBlock, pd->nextFuncId++, false, exprt ); pd->functionList.append( newFunction ); newFunction->inContext = curStruct(); } void BaseParser::inHostDef( const String &hostCall, ObjectDef *localFrame, ParameterList *paramList, TypeRef *typeRef, const String &name, bool exprt ) { Function *newFunction = Function::cons( curNspace(), typeRef, name, paramList, 0, pd->nextHostId++, false, exprt ); newFunction->hostCall = hostCall; newFunction->localFrame = localFrame; newFunction->inHost = true; pd->inHostList.append( newFunction ); newFunction->inContext = curStruct(); } void BaseParser::iterDef( StmtList *stmtList, ObjectDef *localFrame, ParameterList *paramList, const String &name ) { CodeBlock *codeBlock = CodeBlock::cons( stmtList, localFrame ); Function *newFunction = Function::cons( curNspace(), 0, name, paramList, codeBlock, pd->nextFuncId++, true, false ); pd->functionList.append( newFunction ); } LangStmt *BaseParser::globalDef( ObjectField *objField, LangExpr *expr, LangStmt::Type assignType ) { LangStmt *stmt = 0; ObjectDef *object = pd->globalObjectDef; Namespace *nspace = curNspace(); //pd->rootNamespace; if ( nspace->rootScope->checkRedecl( objField->name ) != 0 ) error(objField->loc) << "object field renamed" << endp; object->insertField( nspace->rootScope, objField->name, objField ); if ( expr != 0 ) { LangVarRef *varRef = LangVarRef::cons( objField->loc, curNspace(), curStruct(), curScope(), objField->name ); stmt = LangStmt::cons( objField->loc, assignType, varRef, expr ); } return stmt; } LangStmt *BaseParser::exportStmt( ObjectField *objField, LangStmt::Type assignType, LangExpr *expr ) { LangStmt *stmt = 0; ObjectDef *object = pd->globalObjectDef; Namespace *nspace = curNspace(); //pd->rootNamespace; if ( curStruct() != 0 ) error(objField->loc) << "cannot export parser context variables" << endp; if ( nspace->rootScope->checkRedecl( objField->name ) != 0 ) error(objField->loc) << "object field renamed" << endp; object->insertField( nspace->rootScope, objField->name, objField ); objField->isExport = true; if ( expr != 0 ) { LangVarRef *varRef = LangVarRef::cons( objField->loc, curNspace(), 0, curScope(), objField->name ); stmt = LangStmt::cons( objField->loc, assignType, varRef, expr ); } return stmt; } void BaseParser::cflDef( NtDef *ntDef, ObjectDef *objectDef, LelProdList *prodList ) { Namespace *nspace = curNspace(); ntDef->objectDef = objectDef; ntDef->prodList = prodList; nspace->ntDefList.append( ntDef ); /* Declare the captures in the object. */ for ( LelProdList::Iter prod = *prodList; prod.lte(); prod++ ) { if ( prod->prodElList != 0 ) { for ( ProdElList::Iter pel = *prod->prodElList; pel.lte(); pel++ ) { /* If there is a capture, create the field. */ if ( pel->captureField != 0 ) { /* Might already exist. */ ObjectField *newOf = objectDef->rootScope->checkRedecl( pel->captureField->name ); if ( newOf != 0 ) { /* FIXME: check the types are the same. */ } else { newOf = pel->captureField; newOf->typeRef = pel->typeRef; objectDef->rootScope->insertField( newOf->name, newOf ); } newOf->rhsVal.append( RhsVal( pel ) ); } } } } } ReOrBlock *BaseParser::lexRegularExprData( ReOrBlock *reOrBlock, ReOrItem *reOrItem ) { ReOrBlock *ret; /* An optimization to lessen the tree size. If an or char is directly under * the left side on the right and the right side is another or char then * paste them together and return the left side. Otherwise just put the two * under a new or data node. */ if ( reOrItem->type == ReOrItem::Data && reOrBlock->type == ReOrBlock::RecurseItem && reOrBlock->item->type == ReOrItem::Data ) { /* Append the right side to right side of the left and toss the * right side. */ reOrBlock->item->data += reOrItem->data; delete reOrItem; ret = reOrBlock; } else { /* Can't optimize, put the left and right under a new node. */ ret = ReOrBlock::cons( reOrBlock, reOrItem ); } return ret; } LexFactor *BaseParser::lexRlFactorName( const String &data, const InputLoc &loc ) { LexFactor *factor = 0; /* Find the named graph. */ Namespace *nspace = curNspace(); while ( nspace != 0 ) { GraphDictEl *gdNode = nspace->rlMap.find( data ); if ( gdNode != 0 ) { if ( gdNode->isInstance ) { /* Recover by retuning null as the factor node. */ error(loc) << "references to graph instantiations not allowed " "in expressions" << endl; factor = 0; } else { /* Create a factor node that is a lookup of an expression. */ factor = LexFactor::cons( loc, gdNode->value ); } break; } nspace = nspace->parentNamespace; } if ( nspace == 0 ) { /* Recover by returning null as the factor node. */ error(loc) << "graph lookup of \"" << data << "\" failed" << endl; factor = 0; } return factor; } int BaseParser::lexFactorRepNum( const InputLoc &loc, const String &data ) { /* Convert the priority number to a long. Check for overflow. */ errno = 0; long rep = strtol( data, 0, 10 ); if ( errno == ERANGE && rep == LONG_MAX ) { /* Repetition too large. Recover by returing repetition 1. */ error(loc) << "repetition number " << data << " overflows" << endl; rep = 1; } return rep; } LexFactorAug *BaseParser::lexFactorLabel( const InputLoc &loc, const String &data, LexFactorAug *factorAug ) { /* Create the object field. */ TypeRef *typeRef = TypeRef::cons( loc, pd->uniqueTypeStr ); ObjectField *objField = ObjectField::cons( loc, ObjectField::LexSubstrType, typeRef, data ); /* Create the enter and leaving actions that will mark the substring. */ Action *enter = Action::cons( MarkMark, pd->nextMatchEndNum++ ); Action *leave = Action::cons( MarkMark, pd->nextMatchEndNum++ ); pd->actionList.append( enter ); pd->actionList.append( leave ); /* Add entering and leaving actions. */ factorAug->actions.append( ParserAction( loc, at_start, 0, enter ) ); factorAug->actions.append( ParserAction( loc, at_leave, 0, leave ) ); factorAug->reCaptureVect.append( ReCapture( enter, leave, objField ) ); return factorAug; } LexJoin *BaseParser::lexOptJoin( LexJoin *join, LexJoin *context ) { if ( context != 0 ) { /* Create the enter and leaving actions that will mark the substring. */ Action *mark = Action::cons( MarkMark, pd->nextMatchEndNum++ ); pd->actionList.append( mark ); join->context = context; join->mark = mark; } return join; } LangExpr *BaseParser::send( const InputLoc &loc, LangVarRef *varRef, ConsItemList *list, bool eof ) { ParserText *parserText = ParserText::cons( loc, curNspace(), list, true, false, false, "" ); pd->parserTextList.append( parserText ); return LangExpr::cons( LangTerm::consSend( loc, varRef, parserText, eof ) ); } LangExpr *BaseParser::sendTree( const InputLoc &loc, LangVarRef *varRef, ConsItemList *list, bool eof ) { ParserText *parserText = ParserText::cons( loc, curNspace(), list, true, false, false, "" ); pd->parserTextList.append( parserText ); return LangExpr::cons( LangTerm::consSendTree( loc, varRef, parserText, eof ) ); } LangExpr *BaseParser::parseCmd( const InputLoc &loc, bool tree, bool stop, ObjectField *objField, TypeRef *typeRef, FieldInitVect *fieldInitVect, ConsItemList *list, bool used, bool reduce, bool read, const String &reducer ) { LangExpr *expr = 0; /* Item list for what we are sending to the parser. */ ConsItemList *consItemList = new ConsItemList; /* The parser may be referenced. */ LangVarRef *varRef = 0; if ( objField != 0 ) { varRef = LangVarRef::cons( objField->loc, curNspace(), curStruct(), curScope(), objField->name ); } /* The typeref for the parser. */ TypeRef *parserTypeRef = TypeRef::cons( loc, TypeRef::Parser, 0, typeRef, 0 ); if ( objField != 0 ) used = true; ParserText *parserText = ParserText::cons( loc, curNspace(), list, used, reduce, read, reducer ); pd->parserTextList.append( parserText ); LangTerm::Type langTermType = stop ? LangTerm::ParseStopType : ( tree ? LangTerm::ParseTreeType : LangTerm::ParseType ); expr = LangExpr::cons( LangTerm::cons( loc, langTermType, varRef, objField, parserTypeRef, fieldInitVect, consItemList, parserText ) ); /* Check for redeclaration. */ if ( objField != 0 ) { if ( curScope()->checkRedecl( objField->name ) != 0 ) { error( objField->loc ) << "variable " << objField->name << " redeclared" << endp; } /* Insert it into the field map. */ objField->typeRef = typeRef; curScope()->insertField( objField->name, objField ); } return expr; } PatternItemList *BaseParser::consPatternEl( LangVarRef *varRef, PatternItemList *list ) { /* Store the variable reference in the pattern itemm. */ list->head->varRef = varRef; if ( varRef != 0 ) { if ( curScope()->checkRedecl( varRef->name ) != 0 ) { error( varRef->loc ) << "variable " << varRef->name << " redeclared" << endp; } TypeRef *typeRef = list->head->prodEl->typeRef; ObjectField *objField = ObjectField::cons( InputLoc(), ObjectField::UserLocalType, typeRef, varRef->name ); /* Insert it into the field map. */ curScope()->insertField( varRef->name, objField ); } return list; } PatternItemList *BaseParser::patternElNamed( const InputLoc &loc, LangVarRef *parsedVarRef, NamespaceQual *nspaceQual, const String &data, RepeatType repeatType ) { TypeRef *typeRef = TypeRef::cons( loc, parsedVarRef, nspaceQual, data, repeatType ); ProdEl *prodEl = new ProdEl( ProdEl::ReferenceType, loc, 0, false, typeRef, 0 ); PatternItem *patternItem = PatternItem::cons( PatternItem::TypeRefForm, loc, prodEl ); return PatternItemList::cons( patternItem ); } PatternItemList *BaseParser::patternElType( const InputLoc &loc, LangVarRef *parsedVarRef, NamespaceQual *nspaceQual, const String &data, RepeatType repeatType ) { PdaLiteral *literal = new PdaLiteral( loc, data ); TypeRef *typeRef = TypeRef::cons( loc, parsedVarRef, nspaceQual, literal, repeatType ); ProdEl *prodEl = new ProdEl( ProdEl::ReferenceType, loc, 0, false, typeRef, 0 ); PatternItem *patternItem = PatternItem::cons( PatternItem::TypeRefForm, loc, prodEl ); return PatternItemList::cons( patternItem ); } ProdElList *BaseParser::appendProdEl( ProdElList *prodElList, ProdEl *prodEl ) { prodEl->pos = prodElList->length(); prodElList->append( prodEl ); return prodElList; } PatternItemList *BaseParser::patListConcat( PatternItemList *list1, PatternItemList *list2 ) { if ( list1 == 0 ) list1 = new PatternItemList(); list1->append( *list2 ); delete list2; return list1; } ConsItemList *BaseParser::consListConcat( ConsItemList *list1, ConsItemList *list2 ) { if ( list1 == 0 ) list1 = new ConsItemList(); list1->append( *list2 ); delete list2; return list1; } LangStmt *BaseParser::forScope( const InputLoc &loc, const String &data, NameScope *scope, TypeRef *typeRef, IterCall *iterCall, StmtList *stmtList ) { /* Check for redeclaration. */ if ( curScope()->checkRedecl( data ) != 0 ) error( loc ) << "variable " << data << " redeclared" << endp; /* Note that we pass in a null type reference. This type is dependent on * the result of the iter_call lookup since it must contain a reference to * the iterator that is called. This lookup is done at compile time. */ ObjectField *iterField = ObjectField::cons( loc, ObjectField::UserLocalType, (TypeRef*)0, data ); curScope()->insertField( data, iterField ); LangStmt *stmt = LangStmt::cons( loc, LangStmt::ForIterType, iterField, typeRef, iterCall, stmtList, curStruct(), scope ); return stmt; } void BaseParser::preEof( const InputLoc &loc, StmtList *stmtList, ObjectDef *localFrame ) { if ( !insideRegion() ) error(loc) << "preeof must be used inside an existing region" << endl; CodeBlock *codeBlock = CodeBlock::cons( stmtList, localFrame ); codeBlock->context = curStruct(); RegionSet *regionSet = regionStack.top(); regionSet->tokenIgnore->preEofBlock = codeBlock; } ProdEl *BaseParser::prodElName( const InputLoc &loc, const String &data, NamespaceQual *nspaceQual, ObjectField *objField, RepeatType repeatType, bool commit ) { TypeRef *typeRef = TypeRef::cons( loc, nspaceQual, data, repeatType ); ProdEl *prodEl = new ProdEl( ProdEl::ReferenceType, loc, objField, commit, typeRef, 0 ); return prodEl; } ProdEl *BaseParser::prodElLiteral( const InputLoc &loc, const String &data, NamespaceQual *nspaceQual, ObjectField *objField, RepeatType repeatType, bool commit ) { /* Create a new prodEl node going to a concat literal. */ PdaLiteral *literal = new PdaLiteral( loc, data ); TypeRef *typeRef = TypeRef::cons( loc, nspaceQual, literal, repeatType ); ProdEl *prodEl = new ProdEl( ProdEl::LiteralType, loc, objField, commit, typeRef, 0 ); return prodEl; } ConsItemList *BaseParser::consElLiteral( const InputLoc &loc, TypeRef *consTypeRef, const String &data, NamespaceQual *nspaceQual ) { PdaLiteral *literal = new PdaLiteral( loc, data ); TypeRef *typeRef = TypeRef::cons( loc, consTypeRef, nspaceQual, literal ); ProdEl *prodEl = new ProdEl( ProdEl::LiteralType, loc, 0, false, typeRef, 0 ); ConsItem *consItem = ConsItem::cons( loc, ConsItem::LiteralType, prodEl ); ConsItemList *list = ConsItemList::cons( consItem ); return list; } Production *BaseParser::production( const InputLoc &loc, ProdElList *prodElList, String name, bool commit, CodeBlock *codeBlock, LangEl *predOf ) { Production *prod = Production::cons( loc, 0, prodElList, name, commit, codeBlock, pd->prodList.length(), 0 ); prod->predOf = predOf; /* Link the production elements back to the production. */ for ( ProdEl *prodEl = prodElList->head; prodEl != 0; prodEl = prodEl->next ) prodEl->production = prod; pd->prodList.append( prod ); return prod; } void BaseParser::objVarDef( ObjectDef *objectDef, ObjectField *objField ) { if ( objectDef->rootScope->checkRedecl( objField->name ) != 0 ) error() << "object field renamed" << endp; objectDef->rootScope->insertField( objField->name, objField ); } LelProdList *BaseParser::prodAppend( LelProdList *prodList, Production *definition ) { definition->prodNum = prodList->length(); prodList->append( definition ); return prodList; } LangExpr *BaseParser::construct( const InputLoc &loc, ObjectField *objField, ConsItemList *list, TypeRef *typeRef, FieldInitVect *fieldInitVect ) { Constructor *constructor = Constructor::cons( loc, curNspace(), list, pd->nextPatConsId++ ); pd->replList.append( constructor ); LangVarRef *varRef = 0; if ( objField != 0 ) { varRef = LangVarRef::cons( objField->loc, curNspace(), curStruct(), curScope(), objField->name ); } LangExpr *expr = LangExpr::cons( LangTerm::cons( loc, LangTerm::ConstructType, varRef, objField, typeRef, fieldInitVect, constructor ) ); /* Check for redeclaration. */ if ( objField != 0 ) { if ( curScope()->checkRedecl( objField->name ) != 0 ) { error( objField->loc ) << "variable " << objField->name << " redeclared" << endp; } /* Insert it into the field map. */ objField->typeRef = typeRef; curScope()->insertField( objField->name, objField ); } return expr; } LangExpr *BaseParser::match( const InputLoc &loc, LangVarRef *varRef, PatternItemList *list ) { Pattern *pattern = Pattern::cons( loc, curNspace(), list, pd->nextPatConsId++ ); pd->patternList.append( pattern ); LangExpr *expr = LangExpr::cons( LangTerm::consMatch( InputLoc(), varRef, pattern ) ); return expr; } LangExpr *BaseParser::prodCompare( const InputLoc &loc, LangVarRef *varRef, const String &prod, LangExpr *matchExpr ) { LangExpr *expr = LangExpr::cons( LangTerm::consProdCompare( InputLoc(), varRef, prod, matchExpr ) ); return expr; } LangStmt *BaseParser::varDef( ObjectField *objField, LangExpr *expr, LangStmt::Type assignType ) { LangStmt *stmt = 0; /* Check for redeclaration. */ if ( curScope()->checkRedecl( objField->name ) != 0 ) { error( objField->loc ) << "variable " << objField->name << " redeclared" << endp; } /* Insert it into the field map. */ curScope()->insertField( objField->name, objField ); //cout << "var def " << $1->objField->name << endl; if ( expr != 0 ) { LangVarRef *varRef = LangVarRef::cons( objField->loc, curNspace(), curStruct(), curScope(), objField->name ); stmt = LangStmt::cons( objField->loc, assignType, varRef, expr ); } return stmt; } LangExpr *BaseParser::require( const InputLoc &loc, LangVarRef *varRef, PatternItemList *list ) { Pattern *pattern = Pattern::cons( loc, curNspace(), list, pd->nextPatConsId++ ); pd->patternList.append( pattern ); LangExpr *expr = LangExpr::cons( LangTerm::consMatch( InputLoc(), varRef, pattern ) ); return expr; } void BaseParser::structVarDef( const InputLoc &loc, ObjectField *objField ) { ObjectDef *object; if ( curStruct() == 0 ) error(loc) << "internal error: no context stack items found" << endp; StructDef *structDef = curStruct(); object = structDef->objectDef; if ( object->rootScope->checkRedecl( objField->name ) != 0 ) error(objField->loc) << "object field renamed" << endp; object->rootScope->insertField( objField->name, objField ); } void BaseParser::structHead( const InputLoc &loc, Namespace *inNspace, const String &data, ObjectDef::Type objectType ) { ObjectDef *objectDef = ObjectDef::cons( objectType, data, pd->nextObjectId++ ); StructDef *context = new StructDef( loc, data, objectDef ); structStack.push( context ); inNspace->structDefList.append( context ); /* Make the namespace for the struct. */ createNamespace( loc, data ); } StmtList *BaseParser::appendStatement( StmtList *stmtList, LangStmt *stmt ) { if ( stmt != 0 ) stmtList->append( stmt ); return stmtList; } ParameterList *BaseParser::appendParam( ParameterList *paramList, ObjectField *objField ) { paramList->append( objField ); return paramList; } ObjectField *BaseParser::addParam( const InputLoc &loc, ObjectField::Type type, TypeRef *typeRef, const String &name ) { ObjectField *objField = ObjectField::cons( loc, type, typeRef, name ); return objField; } PredDecl *BaseParser::predTokenName( const InputLoc &loc, NamespaceQual *qual, const String &data ) { TypeRef *typeRef = TypeRef::cons( loc, qual, data ); PredDecl *predDecl = new PredDecl( typeRef, pd->predValue ); return predDecl; } PredDecl *BaseParser::predTokenLit( const InputLoc &loc, const String &data, NamespaceQual *nspaceQual ) { PdaLiteral *literal = new PdaLiteral( loc, data ); TypeRef *typeRef = TypeRef::cons( loc, nspaceQual, literal ); PredDecl *predDecl = new PredDecl( typeRef, pd->predValue ); return predDecl; } void BaseParser::alias( const InputLoc &loc, const String &data, TypeRef *typeRef ) { Namespace *nspace = curNspace(); TypeAlias *typeAlias = new TypeAlias( loc, nspace, data, typeRef ); nspace->typeAliasList.append( typeAlias ); } void BaseParser::precedenceStmt( PredType predType, PredDeclList *predDeclList ) { while ( predDeclList->length() > 0 ) { PredDecl *predDecl = predDeclList->detachFirst(); predDecl->predType = predType; pd->predDeclList.append( predDecl ); } pd->predValue++; } void BaseParser::pushScope() { scopeTop = curLocalFrame()->pushScope( curScope() ); } void BaseParser::popScope() { scopeTop = curScope()->parentScope; }