diff options
Diffstat (limited to 'src/loadinit.cc')
-rw-r--r-- | src/loadinit.cc | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/src/loadinit.cc b/src/loadinit.cc new file mode 100644 index 0000000..6cc76b0 --- /dev/null +++ b/src/loadinit.cc @@ -0,0 +1,386 @@ +/* + * Copyright 2006-2012 Adrian Thurston <thurston@complang.org> + */ + +/* This file is part of Colm. + * + * Colm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Colm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Colm; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <iostream> +#include <string> +#include <errno.h> + +#include "parser.h" +#include "config.h" +#include "avltree.h" +#include "parsedata.h" +#include "parser.h" +#include "global.h" +#include "input.h" +#include "loadinit.h" +#include "if1.h" +#include "colm/colm.h" + +using std::string; + +extern RuntimeData colm_object; + +void LoadInit::walkProdElList( String defName, ProdElList *list, prod_el_list &prodElList ) +{ + if ( prodElList.ProdElList() != 0 ) { + prod_el_list RightProdElList = prodElList.ProdElList(); + walkProdElList( defName, list, RightProdElList ); + } + + if ( prodElList.ProdEl() != 0 ) { + prod_el El = prodElList.ProdEl(); + String typeName = El.Id().text().c_str(); + + ObjectField *captureField = 0; + if ( El.OptName().Name() != 0 ) { + /* Has a capture. */ + String fieldName = El.OptName().Name().text().c_str(); + captureField = ObjectField::cons( internal, 0, fieldName ); + } + else { + /* Default the capture to the name of the type. */ + String fieldName = typeName; + if ( strcmp( fieldName, defName ) == 0 ) + fieldName = "_" + defName; + captureField = ObjectField::cons( internal, 0, fieldName ); + } + + RepeatType repeatType = RepeatNone; + if ( El.OptRepeat().Star() != 0 ) + repeatType = RepeatRepeat; + + ProdEl *prodEl = prodElName( internal, typeName, + NamespaceQual::cons( curNspace() ), + captureField, repeatType, false ); + + appendProdEl( list, prodEl ); + } +} + +void LoadInit::walkProdList( String defName, LelDefList *outProdList, prod_list &prodList ) +{ + if ( prodList.ProdList() != 0 ) { + prod_list RightProdList = prodList.ProdList(); + walkProdList( defName, outProdList, RightProdList ); + } + + ProdElList *outElList = new ProdElList; + prod_el_list prodElList = prodList.Prod().ProdElList(); + walkProdElList( defName, outElList, prodElList ); + + String name; + if ( prodList.Prod().OptName().Name() != 0 ) + name = prodList.Prod().OptName().Name().text().c_str(); + + bool commit = prodList.Prod().OptCommit().Commit() != 0; + + Production *prod = BaseParser::production( internal, outElList, name, commit, 0, 0 ); + prodAppend( outProdList, prod ); +} + +LexFactor *LoadInit::walkLexFactor( lex_factor &lexFactor ) +{ + LexFactor *factor = 0; + if ( lexFactor.Literal() != 0 ) { + String litString = lexFactor.Literal().text().c_str(); + Literal *literal = Literal::cons( internal, litString, Literal::LitString ); + factor = LexFactor::cons( literal ); + } + if ( lexFactor.Id() != 0 ) { + String id = lexFactor.Id().text().c_str(); + factor = lexRlFactorName( id, internal ); + } + else if ( lexFactor.Expr() != 0 ) { + lex_expr LexExpr = lexFactor.Expr(); + LexExpression *expr = walkLexExpr( LexExpr ); + LexJoin *join = LexJoin::cons( expr ); + factor = LexFactor::cons( join ); + } + else if ( lexFactor.Low() != 0 ) { + String low = lexFactor.Low().text().c_str(); + Literal *lowLit = Literal::cons( internal, low, Literal::LitString ); + + String high = lexFactor.High().text().c_str(); + Literal *highLit = Literal::cons( internal, high, Literal::LitString ); + + Range *range = Range::cons( lowLit, highLit ); + factor = LexFactor::cons( range ); + } + return factor; +} + +LexFactorNeg *LoadInit::walkLexFactorNeg( lex_factor_neg &lexFactorNeg ) +{ + if ( lexFactorNeg.FactorNeg() != 0 ) { + lex_factor_neg Rec = lexFactorNeg.FactorNeg(); + LexFactorNeg *recNeg = walkLexFactorNeg( Rec ); + LexFactorNeg *factorNeg = LexFactorNeg::cons( recNeg, LexFactorNeg::CharNegateType ); + return factorNeg; + } + else { + lex_factor LexFactorTree = lexFactorNeg.Factor(); + LexFactor *factor = walkLexFactor( LexFactorTree ); + LexFactorNeg *factorNeg = LexFactorNeg::cons( factor ); + return factorNeg; + } +} + +LexFactorRep *LoadInit::walkLexFactorRep( lex_factor_rep &lexFactorRep ) +{ + LexFactorRep *factorRep = 0; + if ( lexFactorRep.Star() != 0 ) { + lex_factor_rep Rec = lexFactorRep.FactorRep(); + LexFactorRep *recRep = walkLexFactorRep( Rec ); + factorRep = LexFactorRep::cons( internal, recRep, 0, 0, LexFactorRep::StarType ); + } + else if ( lexFactorRep.Plus() != 0 ) { + lex_factor_rep Rec = lexFactorRep.FactorRep(); + LexFactorRep *recRep = walkLexFactorRep( Rec ); + factorRep = LexFactorRep::cons( internal, recRep, 0, 0, LexFactorRep::PlusType ); + } + else { + lex_factor_neg LexFactorNegTree = lexFactorRep.FactorNeg(); + LexFactorNeg *factorNeg = walkLexFactorNeg( LexFactorNegTree ); + factorRep = LexFactorRep::cons( factorNeg ); + } + return factorRep; +} + +LexFactorAug *LoadInit::walkLexFactorAug( lex_factor_rep &lexFactorRep ) +{ + LexFactorRep *factorRep = walkLexFactorRep( lexFactorRep ); + return LexFactorAug::cons( factorRep ); +} + +LexTerm *LoadInit::walkLexTerm( lex_term &lexTerm ) +{ + if ( lexTerm.Term() != 0 ) { + lex_term Rec = lexTerm.Term(); + LexTerm *leftTerm = walkLexTerm( Rec ); + + lex_factor_rep LexFactorRepTree = lexTerm.FactorRep(); + LexFactorAug *factorAug = walkLexFactorAug( LexFactorRepTree ); + LexTerm *term = LexTerm::cons( leftTerm, factorAug, LexTerm::ConcatType ); + return term; + } + else { + lex_factor_rep LexFactorRepTree = lexTerm.FactorRep(); + LexFactorAug *factorAug = walkLexFactorAug( LexFactorRepTree ); + LexTerm *term = LexTerm::cons( factorAug ); + return term; + } +} + +LexExpression *LoadInit::walkLexExpr( lex_expr &LexExprTree ) +{ + if ( LexExprTree.Expr() != 0 ) { + lex_expr Rec = LexExprTree.Expr(); + LexExpression *leftExpr = walkLexExpr( Rec ); + + lex_term lexTerm = LexExprTree.Term(); + LexTerm *term = walkLexTerm( lexTerm ); + LexExpression *expr = LexExpression::cons( leftExpr, term, LexExpression::OrType ); + + return expr; + } + else { + lex_term lexTerm = LexExprTree.Term(); + LexTerm *term = walkLexTerm( lexTerm ); + LexExpression *expr = LexExpression::cons( term ); + return expr; + } +} + +bool walkNoIgnore( opt_ni OptNi ) +{ + return OptNi.Ni() != 0; +} + +void LoadInit::walkTokenList( token_list &tokenList ) +{ + if ( tokenList.TokenList() != 0 ) { + token_list RightTokenList = tokenList.TokenList(); + walkTokenList( RightTokenList ); + } + + if ( tokenList.TokenDef() != 0 ) { + token_def tokenDef = tokenList.TokenDef(); + String name = tokenDef.Id().text().c_str(); + + ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, name, pd->nextObjectId++ ); + + lex_expr LexExpr = tokenDef.Expr(); + LexExpression *expr = walkLexExpr( LexExpr ); + LexJoin *join = LexJoin::cons( expr ); + + bool leftNi = walkNoIgnore( tokenDef.LeftNi() ); + bool rightNi = walkNoIgnore( tokenDef.RightNi() ); + + defineToken( internal, name, join, objectDef, 0, false, leftNi, rightNi ); + } + + if ( tokenList.IgnoreDef() != 0 ) { + ignore_def IgnoreDef = tokenList.IgnoreDef(); + + ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, String(), pd->nextObjectId++ ); + + lex_expr LexExpr = IgnoreDef.Expr(); + LexExpression *expr = walkLexExpr( LexExpr ); + LexJoin *join = LexJoin::cons( expr ); + + defineToken( internal, String(), join, objectDef, 0, true, false, false ); + } +} + +void LoadInit::walkLexRegion( item &LexRegion ) +{ + pushRegionSet( internal ); + + token_list tokenList = LexRegion.TokenList(); + walkTokenList( tokenList ); + + popRegionSet(); +} + +void LoadInit::walkDefinition( item &define ) +{ + prod_list ProdList = define.ProdList(); + + String name = define.DefId().text().c_str(); + + LelDefList *defList = new LelDefList; + walkProdList( name, defList, ProdList ); + + NtDef *ntDef = NtDef::cons( name, curNspace(), curContext(), false ); + ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, name, pd->nextObjectId++ ); + cflDef( ntDef, objectDef, defList ); +} + +void LoadInit::consParseStmt( StmtList *stmtList ) +{ + /* Parse the "start" def. */ + NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); + TypeRef *typeRef = TypeRef::cons( internal, nspaceQual, String("start"), RepeatNone ); + + /* Pop argv, this yields the file name . */ + CallArgVect *popArgs = new CallArgVect; + QualItemVect *popQual = new QualItemVect; + popQual->append( QualItem( QualItem::Dot, internal, String( "argv" ) ) ); + + LangVarRef *popRef = LangVarRef::cons( internal, 0, curLocalFrame->rootScope, popQual, String("pop") ); + LangExpr *pop = LangExpr::cons( LangTerm::cons( InputLoc(), popRef, popArgs ) ); + + /* Construct a literal string 'r', for second arg to open. */ + ConsItem *modeConsItem = ConsItem::cons( internal, ConsItem::InputText, String("r") ); + ConsItemList *modeCons = new ConsItemList; + modeCons->append( modeConsItem ); + LangExpr *modeExpr = LangExpr::cons( LangTerm::cons( internal, modeCons ) ); + + /* Call open. */ + QualItemVect *openQual = new QualItemVect; + LangVarRef *openRef = LangVarRef::cons( internal, + 0, curLocalFrame->rootScope, openQual, String("open") ); + CallArgVect *openArgs = new CallArgVect; + openArgs->append( new CallArg(pop) ); + openArgs->append( new CallArg(modeExpr) ); + LangExpr *open = LangExpr::cons( LangTerm::cons( InputLoc(), openRef, openArgs ) ); + + /* Construct a list containing the open stream. */ + ConsItem *consItem = ConsItem::cons( internal, ConsItem::ExprType, open ); + ConsItemList *list = ConsItemList::cons( consItem ); + + /* Will capture the parser to "P" */ + ObjectField *objField = ObjectField::cons( internal, 0, String("P") ); + + /* Parse the above list. */ + LangExpr *parseExpr = parseCmd( internal, false, objField, typeRef, 0, list ); + LangStmt *parseStmt = LangStmt::cons( internal, LangStmt::ExprType, parseExpr ); + stmtList->append( parseStmt ); +} + +void LoadInit::consExportTree( StmtList *stmtList ) +{ + QualItemVect *qual = new QualItemVect; + LangVarRef *varRef = LangVarRef::cons( internal, 0, curLocalFrame->rootScope, qual, String("P") ); + LangExpr *expr = LangExpr::cons( LangTerm::cons( internal, LangTerm::VarRefType, varRef ) ); + + NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); + TypeRef *typeRef = TypeRef::cons( internal, nspaceQual, String("start"), RepeatNone ); + ObjectField *program = ObjectField::cons( internal, typeRef, String("ColmTree") ); + LangStmt *programExport = exportStmt( program, LangStmt::AssignType, expr ); + stmtList->append( programExport ); +} + +void LoadInit::consExportError( StmtList *stmtList ) +{ + QualItemVect *qual = new QualItemVect; + LangVarRef *varRef = LangVarRef::cons( internal, 0, curLocalFrame->rootScope, qual, String("error") ); + LangExpr *expr = LangExpr::cons( LangTerm::cons( internal, LangTerm::VarRefType, varRef ) ); + + NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); + TypeRef *typeRef = TypeRef::cons( internal, nspaceQual, String("str"), RepeatNone ); + ObjectField *program = ObjectField::cons( internal, typeRef, String("ColmError") ); + LangStmt *programExport = exportStmt( program, LangStmt::AssignType, expr ); + stmtList->append( programExport ); +} + +void LoadInit::go( long activeRealm ) +{ + LoadInit::init(); + + StmtList *stmtList = new StmtList; + + const char *argv[2]; + argv[0] = inputFileName; + argv[1] = 0; + + colm_program *program = colm_new_program( &colm_object ); + colm_run_program( program, 1, argv ); + + /* Extract the parse tree. */ + start Start = ColmTree( program ); + + if ( Start == 0 ) { + gblErrorCount += 1; + std::cerr << inputFileName << ": parse error" << std::endl; + return; + } + + /* Walk the list of items. */ + _repeat_item ItemList = Start.ItemList(); + while ( !ItemList.end() ) { + + item Item = ItemList.value(); + if ( Item.DefId() != 0 ) + walkDefinition( Item ); + else if ( Item.TokenList() != 0 ) + walkLexRegion( Item ); + ItemList = ItemList.next(); + } + + colm_delete_program( program ); + + consParseStmt( stmtList ); + consExportTree( stmtList ); + consExportError( stmtList ); + + pd->rootCodeBlock = CodeBlock::cons( stmtList, 0 ); +} |