summaryrefslogtreecommitdiff
path: root/src/loadinit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/loadinit.cc')
-rw-r--r--src/loadinit.cc386
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 );
+}