/* * 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. */ /* This file is not compiled directly, but rather included in sources. It is * used for both bootstrap2 and colm, but these programs each use separate * gen/if[23].h headers, so this file is included by distinct source files that * each bring in the appropriate dependency, then include this file. */ #include #include #include #include "loadfinal.h" extern colm_sections colm_object; InputLoc::InputLoc( colm_location *pcloc ) { if ( pcloc != 0 ) { fileName = pcloc->name; line = pcloc->line; col = pcloc->column; } else { fileName = 0; line = -1; col = -1; } } String unescape( const String &s ) { String out( String::Fresh(), s.length() ); char *d = out.data; for ( int i = 0; i < s.length(); ) { if ( s[i] == '\\' ) { switch ( s[i+1] ) { case '0': *d++ = '\0'; break; case 'a': *d++ = '\a'; break; case 'b': *d++ = '\b'; break; case 't': *d++ = '\t'; break; case 'n': *d++ = '\n'; break; case 'v': *d++ = '\v'; break; case 'f': *d++ = '\f'; break; case 'r': *d++ = '\r'; break; default: *d++ = s[i+1]; break; } i += 2; } else { *d++ = s[i]; i += 1; } } out.chop( d - out.data ); return out; } struct LoadColm : public BaseParser { LoadColm( Compiler *pd, const char *inputFileName ) : BaseParser( pd ), inputFileName( inputFileName ) {} const char *inputFileName; struct Alignment { Alignment() : firstLine(0), lastLine(0), firstColumn(0) {} int firstLine; int lastLine; int firstColumn; void check( const char *type, colm_location *loc ) { if ( firstLine == 0 ) { firstLine = lastLine = loc->line; firstColumn = loc->column; } else { /* Checking if we are outdented. Indents and are ok. So is * outdenting back to the first. */ if ( loc->column < firstColumn ) { // warning( loc ) << type << " literal outdented beyond first at " << // firstLine << ":" << firstColumn << // ", possible unintended concatenation" << std::endl; } lastLine = loc->line; } } }; Literal *walkLexRangeLit( lex_range_lit lexRangeLit ) { Literal *literal = 0; switch ( lexRangeLit.prodName() ) { case lex_range_lit::Lit: { String lit = lexRangeLit.lex_lit().data(); literal = Literal::cons( lexRangeLit.lex_lit().loc(), lit, Literal::LitString ); break; } case lex_range_lit::Number: { String num = lexRangeLit.lex_num().text().c_str(); literal = Literal::cons( lexRangeLit.lex_num().loc(), num, Literal::Number ); break; }} return literal; } LexFactor *walkLexFactor( lex_factor lexFactor ) { LexFactor *factor = 0; switch ( lexFactor.prodName() ) { case lex_factor::Literal: { String litString = lexFactor.lex_lit().data(); Literal *literal = Literal::cons( lexFactor.lex_lit().loc(), litString, Literal::LitString ); factor = LexFactor::cons( literal ); break; } case lex_factor::Id: { String id = lexFactor.lex_id().data(); factor = lexRlFactorName( id, lexFactor.lex_id().loc() ); break; } case lex_factor::Range: { Literal *low = walkLexRangeLit( lexFactor.Low() ); Literal *high = walkLexRangeLit( lexFactor.High() ); Range *range = Range::cons( low, high ); factor = LexFactor::cons( range ); break; } case lex_factor::PosOrBlock: { ReOrBlock *block = walkRegOrData( lexFactor.reg_or_data() ); factor = LexFactor::cons( ReItem::cons( block, ReItem::OrBlock ) ); break; } case lex_factor::NegOrBlock: { ReOrBlock *block = walkRegOrData( lexFactor.reg_or_data() ); factor = LexFactor::cons( ReItem::cons( block, ReItem::NegOrBlock ) ); break; } case lex_factor::Number: { String number = lexFactor.lex_uint().text().c_str(); factor = LexFactor::cons( Literal::cons( lexFactor.lex_uint().loc(), number, Literal::Number ) ); break; } case lex_factor::Hex: { String number = lexFactor.lex_hex().text().c_str(); factor = LexFactor::cons( Literal::cons( lexFactor.lex_hex().loc(), number, Literal::Number ) ); break; } case lex_factor::Paren: { lex_expr LexExpr = lexFactor.lex_expr(); LexExpression *expr = walkLexExpr( LexExpr ); LexJoin *join = LexJoin::cons( expr ); factor = LexFactor::cons( join ); break; }} return factor; } LexFactorAug *walkLexFactorAug( lex_factor_rep LexFactorRepTree ) { LexFactorRep *factorRep = walkLexFactorRep( LexFactorRepTree ); return LexFactorAug::cons( factorRep ); } LangExpr *walkCodeExpr( code_expr codeExpr, bool used = true ) { LangExpr *expr = 0; switch ( codeExpr.prodName() ) { case code_expr::AmpAmp: { LangExpr *relational = walkCodeRelational( codeExpr.code_relational() ); LangExpr *left = walkCodeExpr( codeExpr._code_expr() ); InputLoc loc = codeExpr.AMP_AMP().loc(); expr = LangExpr::cons( loc, left, OP_LogicalAnd, relational ); break; } case code_expr::BarBar: { LangExpr *relational = walkCodeRelational( codeExpr.code_relational() ); LangExpr *left = walkCodeExpr( codeExpr._code_expr() ); InputLoc loc = codeExpr.BAR_BAR().loc(); expr = LangExpr::cons( loc, left, OP_LogicalOr, relational ); break; } case code_expr::Base: { LangExpr *relational = walkCodeRelational( codeExpr.code_relational(), used ); expr = relational; break; }} return expr; } LangStmt *walkStatement( statement Statement ) { LangStmt *stmt = 0; switch ( Statement.prodName() ) { case statement::Print: { print_stmt printStmt = Statement.print_stmt(); stmt = walkPrintStmt( printStmt ); break; } case statement::VarDef: { ObjectField *objField = walkVarDef( Statement.var_def(), ObjectField::UserLocalType ); LangExpr *expr = walkOptDefInit( Statement.opt_def_init() ); stmt = varDef( objField, expr, LangStmt::AssignType ); break; } case statement::For: { pushScope(); String forDecl = Statement.id().text().c_str(); TypeRef *typeRef = walkTypeRef( Statement.type_ref() ); StmtList *stmtList = walkBlockOrSingle( Statement.block_or_single() ); IterCall *iterCall = walkIterCall( Statement.iter_call() ); stmt = forScope( Statement.id().loc(), forDecl, curScope(), typeRef, iterCall, stmtList ); popScope(); break; } case statement::If: { pushScope(); LangExpr *expr = walkCodeExpr( Statement.code_expr() ); StmtList *stmtList = walkBlockOrSingle( Statement.block_or_single() ); popScope(); LangStmt *elsifList = walkElsifList( Statement.elsif_list() ); stmt = LangStmt::cons( LangStmt::IfType, expr, stmtList, elsifList ); break; } case statement::SwitchUnder: case statement::SwitchBlock: { pushScope(); stmt = walkCaseClauseList( Statement.case_clause_list(), Statement.var_ref() ); popScope(); break; } case statement::While: { pushScope(); LangExpr *expr = walkCodeExpr( Statement.code_expr() ); StmtList *stmtList = walkBlockOrSingle( Statement.block_or_single() ); stmt = LangStmt::cons( LangStmt::WhileType, expr, stmtList ); popScope(); break; } case statement::LhsVarRef: { LangVarRef *varRef = walkVarRef( Statement.var_ref() ); LangExpr *expr = walkCodeExpr( Statement.code_expr() ); stmt = LangStmt::cons( varRef->loc, LangStmt::AssignType, varRef, expr ); break; } case statement::Yield: { LangVarRef *varRef = walkVarRef( Statement.var_ref() ); stmt = LangStmt::cons( LangStmt::YieldType, varRef ); break; } case statement::Return: { LangExpr *expr = walkCodeExpr( Statement.code_expr() ); stmt = LangStmt::cons( Statement.loc(), LangStmt::ReturnType, expr ); break; } case statement::Break: { stmt = LangStmt::cons( LangStmt::BreakType ); break; } case statement::Reject: { stmt = LangStmt::cons( Statement.REJECT().loc(), LangStmt::RejectType ); break; } case statement::Call: { LangVarRef *langVarRef = walkVarRef( Statement.var_ref() ); CallArgVect *exprVect = walkCallArgList( Statement.call_arg_list() ); LangTerm *term = LangTerm::cons( langVarRef->loc, langVarRef, exprVect ); LangExpr *expr = LangExpr::cons( term ); stmt = LangStmt::cons( expr->loc, LangStmt::ExprType, expr ); break; } case statement::StmtOrFactor: { LangExpr *expr = walkStmtOrFactor( Statement.stmt_or_factor() ); stmt = LangStmt::cons( expr->loc, LangStmt::ExprType, expr ); break; } case statement::BareSend: { NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); QualItemVect *qualItemVect = new QualItemVect; LangVarRef *varRef = LangVarRef::cons( InputLoc(), curNspace(), curStruct(), curScope(), nspaceQual, qualItemVect, String("_") ); ConsItemList *list = walkAccumulate( Statement.accumulate() ); bool eof = walkOptEos( Statement.opt_eos() ); LangExpr *expr = send( InputLoc(), varRef, list, eof ); stmt = LangStmt::cons( expr->loc, LangStmt::ExprType, expr ); break; } } return stmt; } StmtList *walkLangStmtList( lang_stmt_list langStmtList ) { StmtList *retList = new StmtList; /* Walk the list of statements. */ RepeatIter ri( langStmtList.StmtList() ); while ( !ri.end() ) { statement Statement = ri.value(); LangStmt *stmt = walkStatement( Statement ); if ( stmt != 0 ) retList->append( stmt ); ri.next(); } require_pattern require = langStmtList.opt_require_stmt().require_pattern(); if ( require != 0 ) { pushScope(); LangVarRef *varRef = walkVarRef( require.var_ref() ); PatternItemList *list = walkPattern( require.pattern(), varRef ); LangExpr *expr = match( require.REQUIRE().loc(), varRef, list ); StmtList *reqList = walkLangStmtList( langStmtList.opt_require_stmt().lang_stmt_list() ); LangStmt *stmt = LangStmt::cons( LangStmt::IfType, expr, reqList, 0 ); popScope(); retList->append( stmt ); } return retList; } void walkTokenDef( token_def TokenDef ) { String name = TokenDef.id().data(); bool niLeft = walkNoIgnoreLeft( TokenDef.no_ignore_left() ); bool niRight = walkNoIgnoreRight( TokenDef.no_ignore_right() ); ObjectDef *objectDef = walkVarDefList( TokenDef.VarDefList() ); objectDef->name = name; LexJoin *join = 0; if ( TokenDef.opt_lex_expr().lex_expr() != 0 ) { LexExpression *expr = walkLexExpr( TokenDef.opt_lex_expr().lex_expr() ); join = LexJoin::cons( expr ); } CodeBlock *translate = walkOptTranslate( TokenDef.opt_translate() ); defineToken( TokenDef.id().loc(), name, join, objectDef, translate, false, niLeft, niRight ); } void walkIgnoreCollector( ic_def IgnoreCollector ) { String id = IgnoreCollector.id().data(); zeroDef( IgnoreCollector.id().loc(), id ); } String walkOptId( opt_id optId ) { String name; if ( optId.prodName() == opt_id::Id ) name = optId.id().data(); return name; } ObjectDef *walkVarDefList( _lrepeat_var_def varDefList ) { ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, String(), pd->nextObjectId++ ); RepeatIter varDefIter( varDefList ); while ( !varDefIter.end() ) { ObjectField *varDef = walkVarDef( varDefIter.value(), ObjectField::UserFieldType ); objVarDef( objectDef, varDef ); varDefIter.next(); } return objectDef; } void walkPreEof( pre_eof_def PreEofDef ) { ObjectDef *localFrame = blockOpen(); StmtList *stmtList = walkLangStmtList( PreEofDef.lang_stmt_list() ); preEof( PreEofDef.PREEOF().loc(), stmtList, localFrame ); blockClose(); } void walkIgnoreDef( ignore_def IgnoreDef ) { String name = walkOptId( IgnoreDef.opt_id() ); ObjectDef *objectDef = ObjectDef::cons( ObjectDef::UserType, name, pd->nextObjectId++ ); LexJoin *join = 0; if ( IgnoreDef.opt_lex_expr().lex_expr() != 0 ) { LexExpression *expr = walkLexExpr( IgnoreDef.opt_lex_expr().lex_expr() ); join = LexJoin::cons( expr ); } defineToken( IgnoreDef.IGNORE().loc(), name, join, objectDef, 0, true, false, false ); } LangExpr *walkCodeMultiplicitive( code_multiplicitive mult, bool used = true ) { LangExpr *expr = 0; switch ( mult.prodName() ) { case code_multiplicitive::Star: { LangExpr *right = walkCodeUnary( mult.code_unary() ); LangExpr *left = walkCodeMultiplicitive( mult._code_multiplicitive() ); expr = LangExpr::cons( mult.STAR().loc(), left, '*', right ); break; } case code_multiplicitive::Fslash: { LangExpr *right = walkCodeUnary( mult.code_unary() ); LangExpr *left = walkCodeMultiplicitive( mult._code_multiplicitive() ); expr = LangExpr::cons( mult.FSLASH().loc(), left, '/', right ); break; } case code_multiplicitive::Base: { LangExpr *right = walkCodeUnary( mult.code_unary(), used ); expr = right; break; }} return expr; } PatternItemList *walkPatternElTypeOrLit( pattern_el_lel typeOrLit, LangVarRef *patternVarRef ) { NamespaceQual *nspaceQual = walkRegionQual( typeOrLit.region_qual() ); RepeatType repeatType = walkOptRepeat( typeOrLit.opt_repeat() ); PatternItemList *list = 0; switch ( typeOrLit.prodName() ) { case pattern_el_lel::Id: { String id = typeOrLit.id().data(); list = patternElNamed( typeOrLit.id().loc(), patternVarRef, nspaceQual, id, repeatType ); break; } case pattern_el_lel::Lit: { String lit = typeOrLit.backtick_lit().data(); list = patternElType( typeOrLit.backtick_lit().loc(), patternVarRef, nspaceQual, lit, repeatType ); break; }} return list; } LangVarRef *walkOptLabel( opt_label optLabel ) { LangVarRef *varRef = 0; if ( optLabel.prodName() == opt_label::Id ) { String id = optLabel.id().data(); varRef = LangVarRef::cons( optLabel.id().loc(), curNspace(), curStruct(), curScope(), id ); } return varRef; } PatternItemList *walkPatternEl( pattern_el patternEl, LangVarRef *patternVarRef ) { PatternItemList *list = 0; switch ( patternEl.prodName() ) { case pattern_el::Dq: { list = walkLitpatElList( patternEl.LitpatElList(), patternEl.dq_lit_term().LIT_DQ_NL(), patternVarRef ); break; } case pattern_el::Sq: { list = walkPatSqConsDataList( patternEl.SqConsDataList(), patternEl.sq_lit_term().CONS_SQ_NL() ); break; } case pattern_el::Tilde: { String patternData = patternEl.opt_tilde_data().text().c_str(); patternData += '\n'; PatternItem *patternItem = PatternItem::cons( PatternItem::InputTextForm, patternEl.opt_tilde_data().loc(), patternData ); list = PatternItemList::cons( patternItem ); break; } case pattern_el::PatternEl: { PatternItemList *typeOrLitList = walkPatternElTypeOrLit( patternEl.pattern_el_lel(), patternVarRef ); LangVarRef *varRef = walkOptLabel( patternEl.opt_label() ); list = consPatternEl( varRef, typeOrLitList ); break; }} return list; } PatternItemList *walkLitpatEl( litpat_el litpatEl, LangVarRef *patternVarRef ) { PatternItemList *list = 0; switch ( litpatEl.prodName() ) { case litpat_el::ConsData: { String consData = unescape( litpatEl.lit_dq_data().text().c_str() ); PatternItem *patternItem = PatternItem::cons( PatternItem::InputTextForm, litpatEl.lit_dq_data().loc(), consData ); list = PatternItemList::cons( patternItem ); break; } case litpat_el::SubList: { list = walkPatternElList( litpatEl.PatternElList(), patternVarRef ); break; }} return list; } PatternItemList *walkPatSqConsDataList( _lrepeat_sq_cons_data sqConsDataList, CONS_SQ_NL Nl ) { PatternItemList *list = new PatternItemList; RepeatIter sqConsDataIter( sqConsDataList ); while ( !sqConsDataIter.end() ) { String consData = unescape( sqConsDataIter.value().text().c_str() ); PatternItem *patternItem = PatternItem::cons( PatternItem::InputTextForm, sqConsDataIter.value().loc(), consData ); PatternItemList *tail = PatternItemList::cons( patternItem ); list = patListConcat( list, tail ); sqConsDataIter.next(); } if ( Nl != 0 ) { String nl = unescape( Nl.data() ); PatternItem *patternItem = PatternItem::cons( PatternItem::InputTextForm, Nl.loc(), nl ); PatternItemList *tail = PatternItemList::cons( patternItem ); list = patListConcat( list, tail ); } return list; } ConsItemList *walkConsSqConsDataList( _lrepeat_sq_cons_data sqConsDataList, CONS_SQ_NL Nl ) { ConsItemList *list = new ConsItemList; RepeatIter sqConsDataIter( sqConsDataList ); while ( !sqConsDataIter.end() ) { String consData = unescape( sqConsDataIter.value().text().c_str() ); ConsItem *consItem = ConsItem::cons( sqConsDataIter.value().loc(), ConsItem::InputText, consData ); ConsItemList *tail = ConsItemList::cons( consItem ); list = consListConcat( list, tail ); sqConsDataIter.next(); } if ( Nl != 0 ) { String nl = unescape( Nl.data() ); ConsItem *consItem = ConsItem::cons( Nl.loc(), ConsItem::InputText, nl ); ConsItemList *tail = ConsItemList::cons( consItem ); list = consListConcat( list, tail ); } return list; } PatternItemList *walkLitpatElList( _lrepeat_litpat_el litpatElList, LIT_DQ_NL Nl, LangVarRef *patternVarRef ) { PatternItemList *list = new PatternItemList; RepeatIter litpatElIter( litpatElList ); while ( !litpatElIter.end() ) { PatternItemList *tail = walkLitpatEl( litpatElIter.value(), patternVarRef ); list = patListConcat( list, tail ); litpatElIter.next(); } if ( Nl != 0 ) { String nl = unescape( Nl.data() ); PatternItem *patternItem = PatternItem::cons( PatternItem::InputTextForm, Nl.loc(), nl ); PatternItemList *tail = PatternItemList::cons( patternItem ); list = patListConcat( list, tail ); } return list; } PatternItemList *walkPatternElList( _lrepeat_pattern_el patternElList, LangVarRef *patternVarRef ) { PatternItemList *list = new PatternItemList; RepeatIter patternElIter( patternElList ); while ( !patternElIter.end() ) { PatternItemList *tail = walkPatternEl( patternElIter.value(), patternVarRef ); list = patListConcat( list, tail ); patternElIter.next(); } return list; } PatternItemList *walkPattternTopEl( pattern_top_el patternTopEl, LangVarRef *patternVarRef ) { PatternItemList *list = 0; switch ( patternTopEl.prodName() ) { case pattern_top_el::Dq: { list = walkLitpatElList( patternTopEl.LitpatElList(), patternTopEl.dq_lit_term().LIT_DQ_NL(), patternVarRef ); break; } case pattern_top_el::Sq: { list = walkPatSqConsDataList( patternTopEl.SqConsDataList(), patternTopEl.sq_lit_term().CONS_SQ_NL() ); break; } case pattern_top_el::Tilde: { String patternData = patternTopEl.opt_tilde_data().text().c_str(); patternData += '\n'; PatternItem *patternItem = PatternItem::cons( PatternItem::InputTextForm, patternTopEl.opt_tilde_data().loc(), patternData ); list = PatternItemList::cons( patternItem ); break; }} return list; } PatternItemList *walkPatternList( pattern_list patternList, LangVarRef *patternVarRef ) { Alignment alignment; PatternItemList *list = new PatternItemList; RepeatIter patternTopElIter ( patternList ); while ( !patternTopElIter.end() ) { pattern_top_el topEl = patternTopElIter.value(); alignment.check( "pattern", topEl.loc() ); PatternItemList *tail = walkPattternTopEl( topEl, patternVarRef ); list = patListConcat( list, tail ); patternTopElIter.next(); } return list; } PatternItemList *walkPattern( pattern Pattern, LangVarRef *patternVarRef ) { if ( Pattern.prodName() == pattern::TopList ) return walkPatternList( Pattern.pattern_list(), patternVarRef ); else return walkPatternElList( Pattern.PatternElList(), patternVarRef ); } LangExpr *walkOptDefInit( opt_def_init optDefInit ) { LangExpr *expr = 0; if ( optDefInit.prodName() == opt_def_init::Init ) expr = walkCodeExpr( optDefInit.code_expr() ); return expr; } LangStmt *walkExportDef( export_def exportDef ) { ObjectField *objField = walkVarDef( exportDef.var_def(), ObjectField::StructFieldType ); LangExpr *expr = walkOptDefInit( exportDef.opt_def_init() ); return exportStmt( objField, LangStmt::AssignType, expr ); } LangStmt *walkGlobalDef( global_def GlobalDef ) { ObjectField *objField = walkVarDef( GlobalDef.var_def(), ObjectField::StructFieldType ); LangExpr *expr = walkOptDefInit( GlobalDef.opt_def_init() ); return globalDef( objField, expr, LangStmt::AssignType ); } void walkAliasDef( alias_def aliasDef ) { String id = aliasDef.id().data(); TypeRef *typeRef = walkTypeRef( aliasDef.type_ref() ); alias( aliasDef.id().loc(), id, typeRef ); } CodeBlock *walkOptTranslate( opt_translate optTranslate ) { CodeBlock *block = 0; if ( optTranslate.prodName() == opt_translate::Translate ) { ObjectDef *localFrame = blockOpen(); StmtList *stmtList = walkLangStmtList( optTranslate.lang_stmt_list() ); block = CodeBlock::cons( stmtList, localFrame ); block->context = curStruct(); blockClose(); } return block; } PredDecl *walkPredToken( pred_token predToken ) { NamespaceQual *nspaceQual = walkRegionQual( predToken.region_qual() ); PredDecl *predDecl = 0; switch ( predToken.prodName() ) { case pred_token::Id: { String id = predToken.id().data(); predDecl = predTokenName( predToken.id().loc(), nspaceQual, id ); break; } case pred_token::Lit: { String lit = predToken.backtick_lit().data(); predDecl = predTokenLit( predToken.backtick_lit().loc(), lit, nspaceQual ); break; }} return predDecl; } PredDeclList *walkPredTokenList( pred_token_list predTokenList ) { PredDeclList *list = 0; switch ( predTokenList.prodName() ) { case pred_token_list::List: { list = walkPredTokenList( predTokenList._pred_token_list() ); PredDecl *predDecl = walkPredToken( predTokenList.pred_token() ); list->append( predDecl ); break; } case pred_token_list::Base: { PredDecl *predDecl = walkPredToken( predTokenList.pred_token() ); list = new PredDeclList; list->append( predDecl ); break; }} return list; } PredType walkPredType( pred_type predType ) { PredType pt = PredLeft; switch ( predType.prodName() ) { case pred_type::Left: pt = PredLeft; break; case pred_type::Right: pt = PredRight; break; case pred_type::NonAssoc: pt = PredNonassoc; break; } return pt; } void walkPrecedenceDef( precedence_def precedenceDef ) { PredType predType = walkPredType( precedenceDef.pred_type() ); PredDeclList *predDeclList = walkPredTokenList( precedenceDef.pred_token_list() ); precedenceStmt( predType, predDeclList ); } StmtList *walkInclude( _include Include ) { String lit = ""; _lrepeat_sq_cons_data sqConsDataList = Include.SqConsDataList(); RepeatIter sqConsDataIter( sqConsDataList ); while ( !sqConsDataIter.end() ) { colm_data *data = sqConsDataIter.value().data(); lit.append( data->data, data->length ); sqConsDataIter.next(); } String file = unescape( lit ); /* Check if we can open the input file for reading. */ if ( ! readCheck( file.data ) ) { bool found = false; for ( ArgsVector::Iter av = includePaths; av.lte(); av++ ) { String path = String( *av ) + "/" + file; if ( readCheck( path.data ) ) { found = true; file = path; break; } } if ( !found ) error() << "could not open " << file.data << " for reading" << endp; } const char *argv[3]; argv[0] = "load-include"; argv[1] = file.data; argv[2] = 0; colm_program *program = colm_new_program( &colm_object ); colm_run_program( program, 2, argv ); /* Extract the parse tree. */ start Start = ColmTree( program ); str Error = ColmError( program ); if ( Start == 0 ) { gblErrorCount += 1; InputLoc loc = Error.loc(); error(loc) << file.data << ": parse error: " << Error.text() << std::endl; return 0; } StmtList *stmtList = walkRootItemList( Start.RootItemList() ); pd->streamFileNames.append( colm_extract_fns( program ) ); colm_delete_program( program ); return stmtList; } NamespaceQual *walkRegionQual( region_qual regionQual ) { NamespaceQual *qual = 0; switch ( regionQual.prodName() ) { case region_qual::Qual: { qual = walkRegionQual( regionQual._region_qual() ); qual->qualNames.append( String( regionQual.id().data() ) ); break; } case region_qual::Base: { qual = NamespaceQual::cons( curNspace() ); break; }} return qual; } RepeatType walkOptRepeat( opt_repeat OptRepeat ) { RepeatType repeatType = RepeatNone; switch ( OptRepeat.prodName() ) { case opt_repeat::Star: repeatType = RepeatRepeat; break; case opt_repeat::Plus: repeatType = RepeatList; break; case opt_repeat::Question: repeatType = RepeatOpt; break; case opt_repeat::LeftStar: repeatType = RepeatLeftRepeat; break; case opt_repeat::LeftPlus: repeatType = RepeatLeftList; break; } return repeatType; } TypeRef *walkValueList( type_ref typeRef ) { TypeRef *valType = walkTypeRef( typeRef._type_ref() ); TypeRef *elType = TypeRef::cons( typeRef.loc(), TypeRef::ListEl, valType ); return TypeRef::cons( typeRef.loc(), TypeRef::List, 0, elType, valType ); } TypeRef *walkListEl( type_ref typeRef ) { TypeRef *valType = walkTypeRef( typeRef._type_ref() ); return TypeRef::cons( typeRef.loc(), TypeRef::ListEl, valType ); } TypeRef *walkValueMap( type_ref typeRef ) { TypeRef *keyType = walkTypeRef( typeRef.KeyType() ); TypeRef *valType = walkTypeRef( typeRef.ValType() ); TypeRef *elType = TypeRef::cons( typeRef.loc(), TypeRef::MapEl, 0, keyType, valType ); return TypeRef::cons( typeRef.loc(), TypeRef::Map, 0, keyType, elType, valType ); } TypeRef *walkMapEl( type_ref typeRef ) { TypeRef *keyType = walkTypeRef( typeRef.KeyType() ); TypeRef *valType = walkTypeRef( typeRef.ValType() ); return TypeRef::cons( typeRef.loc(), TypeRef::MapEl, 0, keyType, valType ); } TypeRef *walkTypeRef( type_ref typeRef ) { TypeRef *tr = 0; switch ( typeRef.prodName() ) { case type_ref::Id: { NamespaceQual *nspaceQual = walkRegionQual( typeRef.region_qual() ); String id = typeRef.id().data(); RepeatType repeatType = walkOptRepeat( typeRef.opt_repeat() ); tr = TypeRef::cons( typeRef.id().loc(), nspaceQual, id, repeatType ); break; } case type_ref::Int: { tr = TypeRef::cons( internal, pd->uniqueTypeInt ); break; } case type_ref::Bool: { tr = TypeRef::cons( internal, pd->uniqueTypeBool ); break; } case type_ref::Void: { tr = TypeRef::cons( internal, pd->uniqueTypeVoid ); break; } case type_ref::Parser: { TypeRef *type = walkTypeRef( typeRef._type_ref() ); tr = TypeRef::cons( typeRef.loc(), TypeRef::Parser, 0, type, 0 ); break; } case type_ref::List: { tr = walkValueList( typeRef ); break; } case type_ref::Map: { tr = walkValueMap( typeRef ); break; } case type_ref::ListEl: { tr = walkListEl( typeRef ); break; } case type_ref::MapEl: { tr = walkMapEl( typeRef ); break; }} return tr; } StmtList *walkBlockOrSingle( block_or_single blockOrSingle ) { StmtList *stmtList = 0; switch ( blockOrSingle.prodName() ) { case block_or_single::Single: { stmtList = new StmtList; LangStmt *stmt = walkStatement( blockOrSingle.statement() ); stmtList->append( stmt ); break; } case block_or_single::Block: { stmtList = walkLangStmtList( blockOrSingle.lang_stmt_list() ); break; }} return stmtList; } void walkProdEl( const String &defName, ProdElList *list, prod_el El ) { ObjectField *captureField = 0; if ( El.opt_prod_el_name().prodName() == opt_prod_el_name::Name ) { String fieldName = El.opt_prod_el_name().id().data(); captureField = ObjectField::cons( El.opt_prod_el_name().id().loc(), ObjectField::RhsNameType, 0, fieldName ); } else { /* default the prod name. */ if ( El.prodName() == prod_el::Id ) { String fieldName = El.id().data(); opt_repeat::prod_name orpn = El.opt_repeat().prodName(); if ( orpn == opt_repeat::Star ) fieldName = "_repeat_" + fieldName; else if ( orpn == opt_repeat::LeftStar ) fieldName = "_lrepeat_" + fieldName; else if ( orpn == opt_repeat::Plus ) fieldName = "_list_" + fieldName; else if ( orpn == opt_repeat::LeftPlus ) fieldName = "_llist_" + fieldName; else if ( orpn == opt_repeat::Question ) fieldName = "_opt_" + fieldName; else if ( strcmp( fieldName, defName ) == 0 ) fieldName = "_" + fieldName; captureField = ObjectField::cons( El.id().loc(), ObjectField::RhsNameType, 0, fieldName ); } } RepeatType repeatType = walkOptRepeat( El.opt_repeat() ); switch ( El.prodName() ) { case prod_el::Id: { NamespaceQual *nspaceQual = walkRegionQual( El.region_qual() ); String typeName = El.id().data(); ProdEl *prodEl = prodElName( El.id().loc(), typeName, nspaceQual, captureField, repeatType, false ); appendProdEl( list, prodEl ); break; } case prod_el::Lit: { NamespaceQual *nspaceQual = walkRegionQual( El.region_qual() ); String lit = El.backtick_lit().data(); ProdEl *prodEl = prodElLiteral( El.backtick_lit().loc(), lit, nspaceQual, captureField, repeatType, false ); appendProdEl( list, prodEl ); break; } case prod_el::SubList: { error( El.POPEN().loc() ) << "production sublist is implemented as a " "colm transformation, it is not accepted at this stage" << endp; }} } void walkProdElList( const String &defName, ProdElList *list, prod_el_list ProdElList ) { if ( ProdElList.prodName() == prod_el_list::List ) { prod_el_list RightProdElList = ProdElList._prod_el_list(); walkProdElList( defName, list, RightProdElList ); walkProdEl( defName, list, ProdElList.prod_el() ); } } CodeBlock *walkOptReduce( opt_reduce OptReduce ) { CodeBlock *block = 0; if ( OptReduce.prodName() == opt_reduce::Reduce ) { ObjectDef *localFrame = blockOpen(); StmtList *stmtList = walkLangStmtList( OptReduce.lang_stmt_list() ); block = CodeBlock::cons( stmtList, localFrame ); block->context = curStruct(); blockClose(); } return block; } void walkProdudction( const String &defName, LelProdList *lelDefList, prod Prod, bool inRedef ) { if ( Prod.prodName() == prod::DotDotDot ) { if ( !inRedef ) { error( Prod.SQOPEN().loc() ) << "the [...] production to reference a " "redef's original productions cannot be used outside of a redef" << endp; } else { Production *dotDotDot = Production::cons( Prod.SQOPEN().loc() ); prodAppend( lelDefList, dotDotDot ); } } else { ProdElList *list = new ProdElList; walkProdElList( defName, list, Prod.prod_el_list() ); String name; if ( Prod.opt_prod_name().prodName() == opt_prod_name::Name ) name = Prod.opt_prod_name().id().data(); CodeBlock *codeBlock = walkOptReduce( Prod.opt_reduce() ); bool commit = Prod.opt_commit().prodName() == opt_commit::Commit; Production *prod = BaseParser::production( Prod.SQOPEN().loc(), list, name, commit, codeBlock, 0 ); prodAppend( lelDefList, prod ); } } void walkProdList( const String &name, LelProdList *lelDefList, prod_list ProdList, bool inRedef ) { if ( ProdList.prodName() == prod_list::List ) walkProdList( name, lelDefList, ProdList._prod_list(), inRedef ); walkProdudction( name, lelDefList, ProdList.prod(), inRedef ); } ReOrItem *walkRegOrChar( reg_or_char regOrChar ) { ReOrItem *orItem = 0; switch ( regOrChar.prodName() ) { case reg_or_char::Char: { String c = unescape( regOrChar.RE_CHAR().data() ); orItem = ReOrItem::cons( regOrChar.RE_CHAR().loc(), c ); break; } case reg_or_char::Range: { String low = unescape( regOrChar.Low().data() ); String high = unescape( regOrChar.High().data() ); orItem = ReOrItem::cons( regOrChar.Low().loc(), low[0], high[0] ); break; }} return orItem; } ReOrBlock *walkRegOrData( reg_or_data regOrData ) { ReOrBlock *block = 0; switch ( regOrData.prodName() ) { case reg_or_data::Data: { ReOrBlock *left = walkRegOrData( regOrData._reg_or_data() ); ReOrItem *right = walkRegOrChar( regOrData.reg_or_char() ); block = lexRegularExprData( left, right ); break; } case reg_or_data::Base: { block = ReOrBlock::cons(); break; }} return block; } LexFactorNeg *walkLexFactorNeg( lex_factor_neg lexFactorNeg ) { LexFactorNeg *factorNeg = 0; switch ( lexFactorNeg.prodName() ) { case lex_factor_neg::Caret: { LexFactorNeg *recNeg = walkLexFactorNeg( lexFactorNeg._lex_factor_neg() ); factorNeg = LexFactorNeg::cons( recNeg, LexFactorNeg::CharNegateType ); break; } case lex_factor_neg::Base: { LexFactor *factor = walkLexFactor( lexFactorNeg.lex_factor() ); factorNeg = LexFactorNeg::cons( factor ); break; }} return factorNeg; } LexFactorRep *walkLexFactorRep( lex_factor_rep lexFactorRep ) { LexFactorRep *factorRep = 0; LexFactorRep *recRep = 0; lex_factor_rep::prod_name pn = lexFactorRep.prodName(); if ( pn != lex_factor_rep::Base ) recRep = walkLexFactorRep( lexFactorRep._lex_factor_rep() ); switch ( pn ) { case lex_factor_rep::Star: { factorRep = LexFactorRep::cons( lexFactorRep.LEX_STAR().loc(), recRep, 0, 0, LexFactorRep::StarType ); break; } case lex_factor_rep::StarStar: { factorRep = LexFactorRep::cons( lexFactorRep.LEX_STARSTAR().loc(), recRep, 0, 0, LexFactorRep::StarStarType ); break; } case lex_factor_rep::Plus: { factorRep = LexFactorRep::cons( lexFactorRep.LEX_PLUS().loc(), recRep, 0, 0, LexFactorRep::PlusType ); break; } case lex_factor_rep::Question: { factorRep = LexFactorRep::cons( lexFactorRep.LEX_QUESTION().loc(), recRep, 0, 0, LexFactorRep::OptionalType ); break; } case lex_factor_rep::Exact: { int low = atoi( lexFactorRep.lex_uint().data()->data ); factorRep = LexFactorRep::cons( lexFactorRep.lex_uint().loc(), recRep, low, 0, LexFactorRep::ExactType ); break; } case lex_factor_rep::Max: { int high = atoi( lexFactorRep.lex_uint().data()->data ); factorRep = LexFactorRep::cons( lexFactorRep.lex_uint().loc(), recRep, 0, high, LexFactorRep::MaxType ); break; } case lex_factor_rep::Min: { int low = atoi( lexFactorRep.lex_uint().data()->data ); factorRep = LexFactorRep::cons( lexFactorRep.lex_uint().loc(), recRep, low, 0, LexFactorRep::MinType ); break; } case lex_factor_rep::Range: { int low = atoi( lexFactorRep.Low().data()->data ); int high = atoi( lexFactorRep.High().data()->data ); factorRep = LexFactorRep::cons( lexFactorRep.Low().loc(), recRep, low, high, LexFactorRep::RangeType ); break; } case lex_factor_rep::Base: { LexFactorNeg *factorNeg = walkLexFactorNeg( lexFactorRep.lex_factor_neg() ); factorRep = LexFactorRep::cons( factorNeg ); }} return factorRep; } LexTerm *walkLexTerm( lex_term lexTerm ) { LexTerm *term = 0; lex_term::prod_name pn = lexTerm.prodName(); LexTerm *leftTerm = 0; if ( pn != lex_term::Base ) leftTerm = walkLexTerm( lexTerm._lex_term() ); LexFactorAug *factorAug = walkLexFactorAug( lexTerm.lex_factor_rep() ); switch ( pn ) { case lex_term::Dot: term = LexTerm::cons( leftTerm, factorAug, LexTerm::ConcatType ); break; case lex_term::ColonGt: term = LexTerm::cons( leftTerm, factorAug, LexTerm::RightStartType ); break; case lex_term::ColonGtGt: term = LexTerm::cons( leftTerm, factorAug, LexTerm::RightFinishType ); break; case lex_term::LtColon: term = LexTerm::cons( leftTerm, factorAug, LexTerm::LeftType ); break; default: term = LexTerm::cons( factorAug ); break; } return term; } LexExpression *walkLexExpr( lex_expr lexExpr ) { LexExpression *expr = 0; lex_expr::prod_name pn = lexExpr.prodName(); LexExpression *leftExpr = 0; if ( pn != lex_expr::Base ) leftExpr = walkLexExpr( lexExpr._lex_expr() ); LexTerm *term = walkLexTerm( lexExpr.lex_term() ); switch ( pn ) { case lex_expr::Bar: expr = LexExpression::cons( leftExpr, term, LexExpression::OrType ); break; case lex_expr::Amp: expr = LexExpression::cons( leftExpr, term, LexExpression::IntersectType ); break; case lex_expr::Dash: expr = LexExpression::cons( leftExpr, term, LexExpression::SubtractType ); break; case lex_expr::DashDash: expr = LexExpression::cons( leftExpr, term, LexExpression::StrongSubtractType ); break; case lex_expr::Base: expr = LexExpression::cons( term ); } return expr; } void walkRlDef( rl_def rlDef ) { String id = rlDef.id().data(); lex_expr LexExpr = rlDef.lex_expr(); LexExpression *expr = walkLexExpr( LexExpr ); LexJoin *join = LexJoin::cons( expr ); addRegularDef( rlDef.id().loc(), curNspace(), id, join ); } void walkLexRegion( region_def regionDef ) { pushRegionSet( regionDef.loc() ); walkRootItemList( regionDef.RootItemList() ); popRegionSet(); } void walkCflDef( cfl_def cflDef ) { String name = cflDef.id().data(); ObjectDef *objectDef = walkVarDefList( cflDef.VarDefList() ); objectDef->name = name; LelProdList *prodList = new LelProdList; walkProdList( name, prodList, cflDef.prod_list(), false ); bool reduceFirst = cflDef.opt_reduce_first().REDUCEFIRST() != 0; NtDef *ntDef = NtDef::cons( name, curNspace(), curStruct(), reduceFirst ); BaseParser::cflDef( ntDef, objectDef, prodList ); } void walkCflRedef( cfl_redef cflRedef ) { String name = cflRedef.id().data(); ObjectDef *objectDef = walkVarDefList( cflRedef.VarDefList() ); objectDef->name = name; LelProdList *prodList = new LelProdList; walkProdList( name, prodList, cflRedef.prod_list(), true ); bool reduceFirst = cflRedef.opt_reduce_first().REDUCEFIRST() != 0; NtDef *ntDef = NtDef::cons( name, curNspace(), curStruct(), reduceFirst ); ntDef->isRedef = true; BaseParser::cflDef( ntDef, objectDef, prodList ); } CallArgVect *walkCallArgSeq( call_arg_seq callArgSeq ) { CallArgVect *callArgVect = new CallArgVect; while ( callArgSeq != 0 ) { code_expr codeExpr = callArgSeq.code_expr(); LangExpr *expr = walkCodeExpr( codeExpr ); callArgVect->append( new CallArg(expr) ); callArgSeq = callArgSeq._call_arg_seq(); } return callArgVect; } CallArgVect *walkCallArgList( call_arg_list callArgList ) { CallArgVect *callArgVect = walkCallArgSeq( callArgList.call_arg_seq() ); return callArgVect; } LangExpr *liftTrim( LangExpr *expr, ConsItem::Trim &trim ) { if ( expr->type == LangExpr::UnaryType ) { if ( expr->op == '^' ) { trim = ConsItem::TrimYes; expr = expr->right; } else if ( expr->op == '@' ) { trim = ConsItem::TrimNo; expr = expr->right; } } return expr; } ConsItemList *walkCallArgSeqAccum( call_arg_seq callArgSeq ) { ConsItemList *consItemList = new ConsItemList; while ( callArgSeq != 0 ) { code_expr codeExpr = callArgSeq.code_expr(); // LangExpr *expr = walkCodeExpr( codeExpr ); // callArgVect->append( new CallArg(expr) ); ConsItem::Trim trim = ConsItem::TrimDefault; LangExpr *consExpr = walkCodeExpr( codeExpr ); ConsItem *consItem = ConsItem::cons( consExpr->loc, ConsItem::ExprType, consExpr, trim ); consItemList->append( consItem ); callArgSeq = callArgSeq._call_arg_seq(); } return consItemList; } ConsItemList *walkCallArgListAccum( call_arg_list callArgList ) { return walkCallArgSeqAccum( callArgList.call_arg_seq() ); } LangStmt *walkPrintStmt( print_stmt &printStmt ) { LangStmt *stmt = 0; switch ( printStmt.prodName() ) { case print_stmt::Accum: { InputLoc loc = printStmt.PRINT().loc(); NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); QualItemVect *qualItemVect = new QualItemVect; LangVarRef *varRef = LangVarRef::cons( loc, curNspace(), curStruct(), curScope(), nspaceQual, qualItemVect, String("stdout") ); ConsItemList *list = walkAccumulate( printStmt.accumulate() ); bool eof = false; //walkOptEos( StmtOrFactor.opt_eos() ); LangExpr *expr = send( loc, varRef, list, eof ); stmt = LangStmt::cons( loc, LangStmt::ExprType, expr ); break; } case print_stmt::Tree: { InputLoc loc = printStmt.PRINT().loc(); NamespaceQual *nspaceQual = NamespaceQual::cons( curNspace() ); QualItemVect *qualItemVect = new QualItemVect; LangVarRef *varRef = LangVarRef::cons( loc, curNspace(), curStruct(), curScope(), nspaceQual, qualItemVect, String("stdout") ); ConsItemList *list = walkCallArgListAccum( printStmt.call_arg_list() ); bool eof = false; //walkOptEos( StmtOrFactor.opt_eos() ); LangExpr *expr = send( loc, varRef, list, eof ); stmt = LangStmt::cons( loc, LangStmt::ExprType, expr ); break; } case print_stmt::PrintStream: { LangVarRef *varRef = walkVarRef( printStmt.var_ref() ); ConsItemList *list = walkCallArgListAccum( printStmt.call_arg_list() ); InputLoc loc = printStmt.PRINTS().loc(); bool eof = false; //walkOptEos( StmtOrFactor.opt_eos() ); LangExpr *expr = send( loc, varRef, list, eof ); stmt = LangStmt::cons( loc, LangStmt::ExprType, expr ); break; }} return stmt; } QualItemVect *walkQual( qual &Qual ) { QualItemVect *qualItemVect = 0; qual RecQual = Qual._qual(); switch ( Qual.prodName() ) { case qual::Dot: case qual::Arrow: { qualItemVect = walkQual( RecQual ); String id = Qual.id().data(); QualItem::Form form = Qual.DOT() != 0 ? QualItem::Dot : QualItem::Arrow; qualItemVect->append( QualItem( form, Qual.id().loc(), id ) ); break; } case qual::Base: { qualItemVect = new QualItemVect; break; }} return qualItemVect; } LangVarRef *walkVarRef( var_ref varRef ) { NamespaceQual *nspaceQual = walkRegionQual( varRef.region_qual() ); qual Qual = varRef.qual(); QualItemVect *qualItemVect = walkQual( Qual ); String id = varRef.id().data(); LangVarRef *langVarRef = LangVarRef::cons( varRef.id().loc(), curNspace(), curStruct(), curScope(), nspaceQual, qualItemVect, id ); return langVarRef; } ObjectField *walkOptCapture( opt_capture optCapture ) { ObjectField *objField = 0; if ( optCapture.prodName() == opt_capture::Id ) { String id = optCapture.id().data(); objField = ObjectField::cons( optCapture.id().loc(), ObjectField::UserLocalType, 0, id ); } return objField; } /* * Constructor */ ConsItemList *walkLitConsEl( lit_cons_el litConsEl, TypeRef *consTypeRef ) { ConsItemList *list = 0; switch ( litConsEl.prodName() ) { case lit_cons_el::ConsData: { String consData = unescape( litConsEl.lit_dq_data().text().c_str() ); ConsItem *consItem = ConsItem::cons( litConsEl.lit_dq_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; } case lit_cons_el::SubList: { list = walkConsElList( litConsEl.ConsElList(), consTypeRef ); break; }} return list; } ConsItemList *walkLitConsElList( _lrepeat_lit_cons_el litConsElList, LIT_DQ_NL Nl, TypeRef *consTypeRef ) { ConsItemList *list = new ConsItemList; RepeatIter litConsElIter( litConsElList ); while ( !litConsElIter.end() ) { ConsItemList *tail = walkLitConsEl( litConsElIter.value(), consTypeRef ); list = consListConcat( list, tail ); litConsElIter.next(); } if ( Nl != 0 ) { String consData = unescape( Nl.data() ); ConsItem *consItem = ConsItem::cons( Nl.loc(), ConsItem::InputText, consData ); ConsItemList *tail = ConsItemList::cons( consItem ); list = consListConcat( list, tail ); } return list; } ConsItemList *walkConsEl( cons_el consEl, TypeRef *consTypeRef ) { ConsItemList *list = 0; switch ( consEl.prodName() ) { case cons_el::Lit: { NamespaceQual *nspaceQual = walkRegionQual( consEl.region_qual() ); String lit = consEl.backtick_lit().data(); list = consElLiteral( consEl.backtick_lit().loc(), consTypeRef, lit, nspaceQual ); break; } case cons_el::Tilde: { String consData = consEl.opt_tilde_data().text().c_str(); consData += '\n'; ConsItem *consItem = ConsItem::cons( consEl.opt_tilde_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; } case cons_el::Sq: { list = walkConsSqConsDataList( consEl.SqConsDataList(), consEl.sq_lit_term().CONS_SQ_NL() ); break; } case cons_el::CodeExpr: { ConsItem::Trim trim = ConsItem::TrimDefault; LangExpr *consExpr = walkCodeExpr( consEl.code_expr() ); ConsItem *consItem = ConsItem::cons( consExpr->loc, ConsItem::ExprType, consExpr, trim ); list = ConsItemList::cons( consItem ); break; } case cons_el::Dq: { list = walkLitConsElList( consEl.LitConsElList(), consEl.dq_lit_term().LIT_DQ_NL(), consTypeRef ); break; }} return list; } ConsItemList *walkConsElList( _lrepeat_cons_el consElList, TypeRef *consTypeRef ) { ConsItemList *list = new ConsItemList; RepeatIter consElIter( consElList ); while ( !consElIter.end() ) { ConsItemList *tail = walkConsEl( consElIter.value(), consTypeRef ); list = consListConcat( list, tail ); consElIter.next(); } return list; } ConsItemList *walkConsTopEl( cons_top_el consTopEl, TypeRef *consTypeRef ) { ConsItemList *list = 0; switch ( consTopEl.prodName() ) { case cons_top_el::Dq: { list = walkLitConsElList( consTopEl.LitConsElList(), consTopEl.dq_lit_term().LIT_DQ_NL(), consTypeRef ); break; } case cons_top_el::Sq: { list = walkConsSqConsDataList( consTopEl.SqConsDataList(), consTopEl.sq_lit_term().CONS_SQ_NL() ); break; } case cons_top_el::Tilde: { String consData = consTopEl.opt_tilde_data().text().c_str(); consData += '\n'; ConsItem *consItem = ConsItem::cons( consTopEl.opt_tilde_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; }} return list; } ConsItemList *walkConsList( cons_list consList, TypeRef *consTypeRef ) { Alignment alignment; ConsItemList *list = new ConsItemList; RepeatIter consTopElIter ( consList ); while ( !consTopElIter.end() ) { cons_top_el topEl = consTopElIter.value(); alignment.check( "constructor", topEl.loc() ); ConsItemList *tail = walkConsTopEl( topEl, consTypeRef ); list = consListConcat( list, tail ); consTopElIter.next(); } return list; } ConsItemList *walkConstructor( constructor Constructor, TypeRef *consTypeRef ) { if ( Constructor.prodName() == constructor::TopList ) return walkConsList( Constructor.cons_list(), consTypeRef ); else return walkConsElList( Constructor.ConsElList(), consTypeRef ); } /* * String */ ConsItemList *walkLitStringEl( lit_string_el litStringEl ) { ConsItemList *list = 0; switch ( litStringEl.prodName() ) { case lit_string_el::ConsData: { String consData = unescape( litStringEl.lit_dq_data().text().c_str() ); ConsItem *stringItem = ConsItem::cons( litStringEl.lit_dq_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( stringItem ); break; } case lit_string_el::SubList: { list = walkStringElList( litStringEl.StringElList() ); break; }} return list; } ConsItemList *walkLitStringElList( _lrepeat_lit_string_el litStringElList, LIT_DQ_NL Nl ) { ConsItemList *list = new ConsItemList; RepeatIter litStringElIter( litStringElList ); while ( !litStringElIter.end() ) { ConsItemList *tail = walkLitStringEl( litStringElIter.value() ); list = consListConcat( list, tail ); litStringElIter.next(); } if ( Nl != 0 ) { String consData = unescape( Nl.data() ); ConsItem *consItem = ConsItem::cons( Nl.loc(), ConsItem::InputText, consData ); ConsItemList *tail = ConsItemList::cons( consItem ); list = consListConcat( list, tail ); } return list; } ConsItemList *walkStringEl( string_el stringEl ) { ConsItemList *list = 0; switch ( stringEl.prodName() ) { case string_el::Dq: { list = walkLitStringElList( stringEl.LitStringElList(), stringEl.dq_lit_term().LIT_DQ_NL() ); break; } case string_el::Sq: { list = walkConsSqConsDataList( stringEl.SqConsDataList(), stringEl.sq_lit_term().CONS_SQ_NL() ); break; } case string_el::Tilde: { String consData = stringEl.opt_tilde_data().text().c_str(); consData += '\n'; ConsItem *consItem = ConsItem::cons( stringEl.opt_tilde_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; } case string_el::CodeExpr: { ConsItem::Trim trim = ConsItem::TrimDefault; LangExpr *consExpr = walkCodeExpr( stringEl.code_expr() ); consExpr = liftTrim( consExpr, trim ); ConsItem *consItem = ConsItem::cons( consExpr->loc, ConsItem::ExprType, consExpr, trim ); list = ConsItemList::cons( consItem ); break; }} return list; } ConsItemList *walkStringElList( _lrepeat_string_el stringElList ) { ConsItemList *list = new ConsItemList; RepeatIter stringElIter( stringElList ); while ( !stringElIter.end() ) { ConsItemList *tail = walkStringEl( stringElIter.value() ); list = consListConcat( list, tail ); stringElIter.next(); } return list; } ConsItemList *walkStringTopEl( string_top_el stringTopEl ) { ConsItemList *list = 0; switch ( stringTopEl.prodName() ) { case string_top_el::Dq: { list = walkLitStringElList( stringTopEl.LitStringElList(), stringTopEl.dq_lit_term().LIT_DQ_NL() ); break; } case string_top_el::Sq: { list = walkConsSqConsDataList( stringTopEl.SqConsDataList(), stringTopEl.sq_lit_term().CONS_SQ_NL() ); break; } case string_top_el::Tilde: { String consData = stringTopEl.opt_tilde_data().text().c_str(); consData += '\n'; ConsItem *consItem = ConsItem::cons( stringTopEl.opt_tilde_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; }} return list; } ConsItemList *walkStringList( string_list stringList ) { Alignment alignment; ConsItemList *list = new ConsItemList; RepeatIter stringTopElIter( stringList ); while ( !stringTopElIter.end() ) { string_top_el topEl = stringTopElIter.value(); alignment.check( "string", topEl.loc() ); ConsItemList *tail = walkStringTopEl( topEl ); list = consListConcat( list, tail ); stringTopElIter.next(); } return list; } ConsItemList *walkString( string String ) { if ( String.prodName() == string::TopList ) return walkStringList( String.string_list() ); else return walkStringElList( String.StringElList() ); } /* * Accum */ ConsItemList *walkLitAccumEl( lit_accum_el litAccumEl ) { ConsItemList *list = 0; switch ( litAccumEl.prodName() ) { case lit_accum_el::ConsData: { String consData = unescape( litAccumEl.lit_dq_data().text().c_str() ); ConsItem *consItem = ConsItem::cons( litAccumEl.lit_dq_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; } case lit_accum_el::SubList: { list = walkAccumElList( litAccumEl.AccumElList() ); break; }} return list; } ConsItemList *walkLitAccumElList( _lrepeat_lit_accum_el litAccumElList, LIT_DQ_NL Nl ) { ConsItemList *list = new ConsItemList; RepeatIter litAccumElIter( litAccumElList ); while ( !litAccumElIter.end() ) { ConsItemList *tail = walkLitAccumEl( litAccumElIter.value() ); list = consListConcat( list, tail ); litAccumElIter.next(); } if ( Nl != 0 ) { String consData = unescape( Nl.data() ); ConsItem *consItem = ConsItem::cons( Nl.loc(), ConsItem::InputText, consData ); ConsItemList *tail = ConsItemList::cons( consItem ); list = consListConcat( list, tail ); } return list; } ConsItemList *walkAccumEl( accum_el accumEl ) { ConsItemList *list = 0; switch ( accumEl.prodName() ) { case accum_el::Dq: { list = walkLitAccumElList( accumEl.LitAccumElList(), accumEl.dq_lit_term().LIT_DQ_NL() ); break; } case accum_el::Sq: { list = walkConsSqConsDataList( accumEl.SqConsDataList(), accumEl.sq_lit_term().CONS_SQ_NL() ); break; } case accum_el::Tilde: { String consData = accumEl.opt_tilde_data().text().c_str(); consData += '\n'; ConsItem *consItem = ConsItem::cons( accumEl.opt_tilde_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; } case accum_el::CodeExpr: { ConsItem::Trim trim = ConsItem::TrimDefault; LangExpr *accumExpr = walkCodeExpr( accumEl.code_expr() ); accumExpr = liftTrim( accumExpr, trim ); ConsItem *consItem = ConsItem::cons( accumExpr->loc, ConsItem::ExprType, accumExpr, trim ); list = ConsItemList::cons( consItem ); break; }} return list; } ConsItemList *walkAccumElList( _lrepeat_accum_el accumElList ) { ConsItemList *list = new ConsItemList; RepeatIter accumElIter( accumElList ); while ( !accumElIter.end() ) { ConsItemList *tail = walkAccumEl( accumElIter.value() ); list = consListConcat( list, tail ); accumElIter.next(); } return list; } ConsItemList *walkAccumTopEl( accum_top_el accumTopEl ) { ConsItemList *list = 0; switch ( accumTopEl.prodName() ) { case accum_top_el::Dq: { list = walkLitAccumElList( accumTopEl.LitAccumElList(), accumTopEl.dq_lit_term().LIT_DQ_NL() ); break; } case accum_top_el::Sq: { list = walkConsSqConsDataList( accumTopEl.SqConsDataList(), accumTopEl.sq_lit_term().CONS_SQ_NL() ); break; } case accum_top_el::Tilde: { String consData = accumTopEl.opt_tilde_data().text().c_str(); consData += '\n'; ConsItem *consItem = ConsItem::cons( accumTopEl.opt_tilde_data().loc(), ConsItem::InputText, consData ); list = ConsItemList::cons( consItem ); break; } case accum_top_el::SubList: { list = walkAccumElList( accumTopEl.AccumElList() ); break; }} return list; } ConsItemList *walkAccumList( Alignment &alignment, accum_list accumList ) { accum_top_el topEl = accumList.accum_top_el(); alignment.check( "accumulator", topEl.loc() ); ConsItemList *list = walkAccumTopEl( topEl ); if ( accumList.prodName() == accum_list::List ) { ConsItemList *tail = walkAccumList( alignment, accumList._accum_list() ); list = consListConcat( list, tail ); } return list; } ConsItemList *walkAccumulate( accumulate Accumulate ) { Alignment alignment; ConsItemList *list = walkAccumList( alignment, Accumulate.accum_list() ); return list; } void walkFieldInit( FieldInitVect *list, field_init fieldInit ) { LangExpr *expr = walkCodeExpr( fieldInit.code_expr() ); FieldInit *init = FieldInit::cons( expr->loc, "_name", expr ); list->append( init ); } FieldInitVect *walkFieldInit( _lrepeat_field_init fieldInitList ) { FieldInitVect *list = new FieldInitVect; RepeatIter fieldInitIter( fieldInitList ); while ( !fieldInitIter.end() ) { walkFieldInit( list, fieldInitIter.value() ); fieldInitIter.next(); } return list; } FieldInitVect *walkOptFieldInit( opt_field_init optFieldInit ) { FieldInitVect *list = 0; if ( optFieldInit.prodName() == opt_field_init::Init ) list = walkFieldInit( optFieldInit.FieldInitList() ); return list; } LangExpr *walkStmtOrFactor( stmt_or_factor StmtOrFactor ) { LangExpr *expr = 0; switch ( StmtOrFactor.prodName() ) { case stmt_or_factor::Parse: { /* The type we are parsing. */ type_ref typeRefTree = StmtOrFactor.type_ref(); TypeRef *typeRef = walkTypeRef( typeRefTree ); ObjectField *objField = walkOptCapture( StmtOrFactor.opt_capture() ); FieldInitVect *init = walkOptFieldInit( StmtOrFactor.opt_field_init() ); ConsItemList *list = walkAccumulate( StmtOrFactor.accumulate() ); expr = parseCmd( StmtOrFactor.PARSE().loc(), false, false, objField, typeRef, init, list, true, false, false, "" ); break; } case stmt_or_factor::ParseTree: { /* The type we are parsing. */ type_ref typeRefTree = StmtOrFactor.type_ref(); TypeRef *typeRef = walkTypeRef( typeRefTree ); ObjectField *objField = walkOptCapture( StmtOrFactor.opt_capture() ); FieldInitVect *init = walkOptFieldInit( StmtOrFactor.opt_field_init() ); ConsItemList *list = walkAccumulate( StmtOrFactor.accumulate() ); expr = parseCmd( StmtOrFactor.PARSE_TREE().loc(), true, false, objField, typeRef, init, list, true, false, false, "" ); break; } case stmt_or_factor::ParseStop: { /* The type we are parsing. */ type_ref typeRefTree = StmtOrFactor.type_ref(); TypeRef *typeRef = walkTypeRef( typeRefTree ); ObjectField *objField = walkOptCapture( StmtOrFactor.opt_capture() ); FieldInitVect *init = walkOptFieldInit( StmtOrFactor.opt_field_init() ); ConsItemList *list = walkAccumulate( StmtOrFactor.accumulate() ); expr = parseCmd( StmtOrFactor.PARSE_STOP().loc(), false, true, objField, typeRef, init, list, true, false, false, "" ); break; } case stmt_or_factor::Reduce: { /* The reducer name. */ String reducer = StmtOrFactor.id().data(); /* The type we are parsing. */ type_ref typeRefTree = StmtOrFactor.type_ref(); TypeRef *typeRef = walkTypeRef( typeRefTree ); FieldInitVect *init = walkOptFieldInit( StmtOrFactor.opt_field_init() ); ConsItemList *list = walkAccumulate( StmtOrFactor.accumulate() ); expr = parseCmd( StmtOrFactor.REDUCE().loc(), false, false, 0, typeRef, init, list, true, true, false, reducer ); break; } case stmt_or_factor::ReadReduce: { /* The reducer name. */ String reducer = StmtOrFactor.id().data(); /* The type we are parsing. */ type_ref typeRefTree = StmtOrFactor.type_ref(); TypeRef *typeRef = walkTypeRef( typeRefTree ); FieldInitVect *init = walkOptFieldInit( StmtOrFactor.opt_field_init() ); ConsItemList *list = walkAccumulate( StmtOrFactor.accumulate() ); expr = parseCmd( StmtOrFactor.READ_REDUCE().loc(), false, false, 0, typeRef, init, list, true, true, true, reducer ); break; } case stmt_or_factor::Send: { LangVarRef *varRef = walkVarRef( StmtOrFactor.var_ref() ); ConsItemList *list = walkAccumulate( StmtOrFactor.accumulate() ); bool eof = walkOptEos( StmtOrFactor.opt_eos() ); expr = send( StmtOrFactor.SEND().loc(), varRef, list, eof ); break; } case stmt_or_factor::SendTree: { LangVarRef *varRef = walkVarRef( StmtOrFactor.var_ref() ); ConsItemList *list = walkAccumulate( StmtOrFactor.accumulate() ); bool eof = walkOptEos( StmtOrFactor.opt_eos() ); expr = sendTree( StmtOrFactor.SEND_TREE().loc(), varRef, list, eof ); break; } case stmt_or_factor::MakeTree: { CallArgVect *exprList = walkCallArgList( StmtOrFactor.call_arg_list() ); expr = LangExpr::cons( LangTerm::cons( StmtOrFactor.loc(), LangTerm::MakeTreeType, exprList ) ); break; } case stmt_or_factor::MakeToken: { CallArgVect *exprList = walkCallArgList( StmtOrFactor.call_arg_list() ); expr = LangExpr::cons( LangTerm::cons( StmtOrFactor.loc(), LangTerm::MakeTokenType, exprList ) ); break; } case stmt_or_factor::Cons: { /* The type we are parsing. */ type_ref typeRefTree = StmtOrFactor.type_ref(); TypeRef *typeRef = walkTypeRef( typeRefTree ); ObjectField *objField = walkOptCapture( StmtOrFactor.opt_capture() ); ConsItemList *list = walkConstructor( StmtOrFactor.constructor(), typeRef ); FieldInitVect *init = walkOptFieldInit( StmtOrFactor.opt_field_init() ); expr = construct( StmtOrFactor.CONS().loc(), objField, list, typeRef, init ); break; } case stmt_or_factor::Match: { LangVarRef *varRef = walkVarRef( StmtOrFactor.var_ref() ); PatternItemList *list = walkPattern( StmtOrFactor.pattern(), varRef ); expr = match( StmtOrFactor.loc(), varRef, list ); break; } case stmt_or_factor::New: { TypeRef *typeRef = walkTypeRef( StmtOrFactor.type_ref() ); ObjectField *captureField = walkOptCapture( StmtOrFactor.opt_capture() ); FieldInitVect *init = walkFieldInit( StmtOrFactor.FieldInitList() ); LangVarRef *captureVarRef = 0; if ( captureField != 0 ) { captureVarRef = LangVarRef::cons( captureField->loc, curNspace(), curStruct(), curScope(), captureField->name ); } expr = LangExpr::cons( LangTerm::consNew( StmtOrFactor.loc(), typeRef, captureVarRef, init ) ); /* Check for redeclaration. */ if ( captureField != 0 ) { if ( curScope()->checkRedecl( captureField->name ) != 0 ) { error( captureField->loc ) << "variable " << captureField->name << " redeclared" << endp; } /* Insert it into the field map. */ captureField->typeRef = typeRef; curScope()->insertField( captureField->name, captureField ); } break; }} return expr; } LangExpr *walkCodeFactor( code_factor codeFactor, bool used = true ) { LangExpr *expr = 0; switch ( codeFactor.prodName() ) { case code_factor::VarRef: { LangVarRef *langVarRef = walkVarRef( codeFactor.var_ref() ); LangTerm *term = LangTerm::cons( langVarRef->loc, LangTerm::VarRefType, langVarRef ); expr = LangExpr::cons( term ); break; } case code_factor::Call: { LangVarRef *langVarRef = walkVarRef( codeFactor.var_ref() ); CallArgVect *exprVect = walkCallArgList( codeFactor.call_arg_list() ); LangTerm *term = LangTerm::cons( langVarRef->loc, langVarRef, exprVect ); expr = LangExpr::cons( term ); break; } case code_factor::Number: { String number = codeFactor.number().text().c_str(); LangTerm *term = LangTerm::cons( codeFactor.number().loc(), LangTerm::NumberType, number ); expr = LangExpr::cons( term ); break; } case code_factor::StmtOrFactor: { expr = walkStmtOrFactor( codeFactor.stmt_or_factor() ); break; } case code_factor::Nil: { expr = LangExpr::cons( LangTerm::cons( codeFactor.NIL().loc(), LangTerm::NilType ) ); break; } case code_factor::True: { expr = LangExpr::cons( LangTerm::cons( codeFactor.TRUE().loc(), LangTerm::TrueType ) ); break; } case code_factor::False: { expr = LangExpr::cons( LangTerm::cons( codeFactor.FALSE().loc(), LangTerm::FalseType ) ); break; } case code_factor::Paren: { expr = walkCodeExpr( codeFactor.code_expr() ); break; } case code_factor::String: { ConsItemList *list = walkString( codeFactor.string() ); expr = LangExpr::cons( LangTerm::cons( codeFactor.string().loc(), list ) ); break; } case code_factor::In: { TypeRef *typeRef = walkTypeRef( codeFactor.type_ref() ); LangVarRef *varRef = walkVarRef( codeFactor.var_ref() ); expr = LangExpr::cons( LangTerm::cons( typeRef->loc, LangTerm::SearchType, typeRef, varRef ) ); break; } case code_factor::TypeId: { TypeRef *typeRef = walkTypeRef( codeFactor.type_ref() ); expr = LangExpr::cons( LangTerm::cons( codeFactor.loc(), LangTerm::TypeIdType, typeRef ) ); break; } case code_factor::Cast: { TypeRef *typeRef = walkTypeRef( codeFactor.type_ref() ); LangExpr *castExpr = walkCodeFactor( codeFactor._code_factor() ); expr = LangExpr::cons( LangTerm::cons( codeFactor.loc(), LangTerm::CastType, typeRef, castExpr ) ); break; }} return expr; } LangExpr *walkCodeAdditive( code_additive additive, bool used = true ) { LangExpr *expr = 0; switch ( additive.prodName() ) { case code_additive::Plus: { LangExpr *left = walkCodeAdditive( additive._code_additive() ); LangExpr *right = walkCodeMultiplicitive( additive.code_multiplicitive() ); expr = LangExpr::cons( additive.PLUS().loc(), left, '+', right ); break; } case code_additive::Minus: { LangExpr *left = walkCodeAdditive( additive._code_additive() ); LangExpr *right = walkCodeMultiplicitive( additive.code_multiplicitive() ); expr = LangExpr::cons( additive.MINUS().loc(), left, '-', right ); break; } case code_additive::Base: { expr = walkCodeMultiplicitive( additive.code_multiplicitive(), used ); break; }} return expr; } LangExpr *walkCodeUnary( code_unary unary, bool used = true ) { LangExpr *expr = 0; switch ( unary.prodName() ) { case code_unary::Bang: { LangExpr *factor = walkCodeFactor( unary.code_factor() ); expr = LangExpr::cons( unary.BANG().loc(), '!', factor ); break; } case code_unary::Dollar: { LangExpr *factor = walkCodeFactor( unary.code_factor() ); expr = LangExpr::cons( unary.DOLLAR().loc(), '$', factor ); break; } case code_unary::DollarDollar: { LangExpr *factor = walkCodeFactor( unary.code_factor() ); expr = LangExpr::cons( unary.DOLLAR().loc(), 'S', factor ); break; } case code_unary::Caret: { LangExpr *factor = walkCodeFactor( unary.code_factor() ); expr = LangExpr::cons( unary.CARET().loc(), '^', factor ); break; } case code_unary::At: { LangExpr *factor = walkCodeFactor( unary.code_factor() ); expr = LangExpr::cons( unary.AT().loc(), '@', factor ); break; } case code_unary::Percent: { LangExpr *factor = walkCodeFactor( unary.code_factor() ); expr = LangExpr::cons( unary.PERCENT().loc(), '%', factor ); break; } case code_unary::Base: { LangExpr *factor = walkCodeFactor( unary.code_factor(), used ); expr = factor; }} return expr; } LangExpr *walkCodeRelational( code_relational codeRelational, bool used = true ) { LangExpr *expr = 0, *left = 0; bool base = codeRelational.prodName() == code_relational::Base; if ( ! base ) { used = true; left = walkCodeRelational( codeRelational._code_relational() ); } LangExpr *additive = walkCodeAdditive( codeRelational.code_additive(), used ); switch ( codeRelational.prodName() ) { case code_relational::EqEq: { expr = LangExpr::cons( codeRelational.loc(), left, OP_DoubleEql, additive ); break; } case code_relational::Neq: { expr = LangExpr::cons( codeRelational.loc(), left, OP_NotEql, additive ); break; } case code_relational::Lt: { expr = LangExpr::cons( codeRelational.loc(), left, '<', additive ); break; } case code_relational::Gt: { expr = LangExpr::cons( codeRelational.loc(), left, '>', additive ); break; } case code_relational::LtEq: { expr = LangExpr::cons( codeRelational.loc(), left, OP_LessEql, additive ); break; } case code_relational::GtEq: { expr = LangExpr::cons( codeRelational.loc(), left, OP_GrtrEql, additive ); break; } case code_relational::Base: { expr = additive; break; }} return expr; } LangStmt *walkExprStmt( expr_stmt exprStmt ) { LangExpr *expr = walkCodeExpr( exprStmt.code_expr(), false ); LangStmt *stmt = LangStmt::cons( expr->loc, LangStmt::ExprType, expr ); return stmt; } ObjectField *walkVarDef( var_def varDef, ObjectField::Type type ) { String id = varDef.id().data(); TypeRef *typeRef = walkTypeRef( varDef.type_ref() ); return ObjectField::cons( varDef.id().loc(), type, typeRef, id ); } IterCall *walkIterCall( iter_call Tree ) { IterCall *iterCall = 0; switch ( Tree.prodName() ) { case iter_call::Call: { LangVarRef *varRef = walkVarRef( Tree.var_ref() ); CallArgVect *exprVect = walkCallArgList( Tree.call_arg_list() ); LangTerm *langTerm = LangTerm::cons( varRef->loc, varRef, exprVect ); iterCall = IterCall::cons( IterCall::Call, langTerm ); break; } case iter_call::Id: { String tree = Tree.id().data(); LangVarRef *varRef = LangVarRef::cons( Tree.id().loc(), curNspace(), curStruct(), curScope(), tree ); LangTerm *langTerm = LangTerm::cons( Tree.id().loc(), LangTerm::VarRefType, varRef ); LangExpr *langExpr = LangExpr::cons( langTerm ); iterCall = IterCall::cons( IterCall::Expr, langExpr ); break; } case iter_call::Expr: { LangExpr *langExpr = walkCodeExpr( Tree.code_expr() ); iterCall = IterCall::cons( IterCall::Expr, langExpr ); break; }} return iterCall; } LangStmt *walkElsifClause( elsif_clause elsifClause ) { pushScope(); LangExpr *expr = walkCodeExpr( elsifClause.code_expr() ); StmtList *stmtList = walkBlockOrSingle( elsifClause.block_or_single() ); LangStmt *stmt = LangStmt::cons( LangStmt::IfType, expr, stmtList, 0 ); popScope(); return stmt; } LangStmt *walkOptionalElse( optional_else optionalElse ) { LangStmt *stmt = 0; if ( optionalElse.prodName() == optional_else::Else ) { pushScope(); StmtList *stmtList = walkBlockOrSingle( optionalElse.block_or_single() ); stmt = LangStmt::cons( LangStmt::ElseType, stmtList ); popScope(); } return stmt; } LangStmt *walkElsifList( elsif_list elsifList ) { LangStmt *stmt = 0; switch ( elsifList.prodName() ) { case elsif_list::Clause: stmt = walkElsifClause( elsifList.elsif_clause() ); stmt->elsePart = walkElsifList( elsifList._elsif_list() ); break; case elsif_list::OptElse: stmt = walkOptionalElse( elsifList.optional_else() ); break; } return stmt; } LangStmt *walkCaseClause( case_clause CaseClause, var_ref VarRef ) { pushScope(); LangVarRef *varRef = walkVarRef( VarRef ); scopeTop->caseClauseVarRef = varRef; LangExpr *expr = 0; switch ( CaseClause.prodName() ) { case case_clause::Pattern: { /* A match pattern. */ PatternItemList *list = walkPattern( CaseClause.pattern(), varRef ); expr = match( CaseClause.loc(), varRef, list ); break; } case case_clause::Id: { /* An identifier to be interpreted as a production name. */ String prod = CaseClause.id().text().c_str(); expr = prodCompare( CaseClause.loc(), varRef, prod, 0 ); break; } case case_clause::IdPat: { String prod = CaseClause.id().text().c_str(); PatternItemList *list = walkPattern( CaseClause.pattern(), varRef ); LangExpr *matchExpr = match( CaseClause.loc(), varRef, list ); expr = prodCompare( CaseClause.loc(), varRef, prod, matchExpr ); break; } } StmtList *stmtList = walkBlockOrSingle( CaseClause.block_or_single() ); popScope(); LangStmt *stmt = LangStmt::cons( LangStmt::IfType, expr, stmtList ); return stmt; } LangStmt *walkCaseClauseList( case_clause_list CaseClauseList, var_ref VarRef ) { LangStmt *stmt = 0; switch ( CaseClauseList.prodName() ) { case case_clause_list::Recursive: { stmt = walkCaseClause( CaseClauseList.case_clause(), VarRef ); LangStmt *recList = walkCaseClauseList( CaseClauseList._case_clause_list(), VarRef ); stmt->setElsePart( recList ); break; } case case_clause_list::BaseCase: { stmt = walkCaseClause( CaseClauseList.case_clause(), VarRef ); break; } case case_clause_list::BaseDefault: { pushScope(); StmtList *stmtList = walkBlockOrSingle( CaseClauseList.default_clause().block_or_single() ); popScope(); stmt = LangStmt::cons( LangStmt::ElseType, stmtList ); break; } } return stmt; } void walkStructVarDef( struct_var_def StructVarDef ) { ObjectField *objField = walkVarDef( StructVarDef.var_def(), ObjectField::StructFieldType ); structVarDef( objField->loc, objField ); } TypeRef *walkReferenceTypeRef( reference_type_ref ReferenceTypeRef ) { TypeRef *typeRef = walkTypeRef( ReferenceTypeRef.type_ref() ); return TypeRef::cons( ReferenceTypeRef.REF().loc(), TypeRef::Ref, typeRef ); } ObjectField *walkParamVarDef( param_var_def paramVarDef ) { String id = paramVarDef.id().data(); TypeRef *typeRef = 0; ObjectField::Type type; switch ( paramVarDef.prodName() ) { case param_var_def::Type: typeRef = walkTypeRef( paramVarDef.type_ref() ); type = ObjectField::ParamValType; break; case param_var_def::Ref: typeRef = walkReferenceTypeRef( paramVarDef.reference_type_ref() ); type = ObjectField::ParamRefType; break; } return addParam( paramVarDef.id().loc(), type, typeRef, id ); } ParameterList *walkParamVarDefSeq( param_var_def_seq paramVarDefSeq ) { ParameterList *paramList = new ParameterList; while ( paramVarDefSeq != 0 ) { ObjectField *param = walkParamVarDef( paramVarDefSeq.param_var_def() ); appendParam( paramList, param ); paramVarDefSeq = paramVarDefSeq._param_var_def_seq(); } return paramList; } ParameterList *walkParamVarDefList( param_var_def_list paramVarDefList ) { ParameterList *paramList = walkParamVarDefSeq( paramVarDefList.param_var_def_seq() ); return paramList; } bool walkOptExport( opt_export OptExport ) { return OptExport.prodName() == opt_export::Export; } void walkFunctionDef( function_def FunctionDef ) { ObjectDef *localFrame = blockOpen(); bool exprt = walkOptExport( FunctionDef.opt_export() ); TypeRef *typeRef = walkTypeRef( FunctionDef.type_ref() ); String id = FunctionDef.id().data(); ParameterList *paramList = walkParamVarDefList( FunctionDef.ParamVarDefList() ); StmtList *stmtList = walkLangStmtList( FunctionDef.lang_stmt_list() ); functionDef( stmtList, localFrame, paramList, typeRef, id, exprt ); blockClose(); } void walkInHostDef( in_host_def InHostDef ) { ObjectDef *localFrame = blockOpen(); TypeRef *typeRef = walkTypeRef( InHostDef.type_ref() ); String id = InHostDef.id().data(); ParameterList *paramList = walkParamVarDefList( InHostDef.ParamVarDefList() ); inHostDef( InHostDef.HostFunc().data(), localFrame, paramList, typeRef, id, false ); blockClose(); } void walkIterDef( iter_def IterDef ) { ObjectDef *localFrame = blockOpen(); String id = IterDef.id().data(); ParameterList *paramList = walkParamVarDefList( IterDef.ParamVarDefList() ); StmtList *stmtList = walkLangStmtList( IterDef.lang_stmt_list() ); iterDef( stmtList, localFrame, paramList, id ); blockClose(); } void walkStructItem( struct_item structItem ) { switch ( structItem.prodName() ) { case struct_item::Rl: walkRlDef( structItem.rl_def() ); break; case struct_item::StructVar: walkStructVarDef( structItem.struct_var_def() ); break; case struct_item::Token: walkTokenDef( structItem.token_def() ); break; case struct_item::IgnoreCollector: walkIgnoreCollector( structItem.ic_def() ); break; case struct_item::Ignore: walkIgnoreDef( structItem.ignore_def() ); break; case struct_item::Literal: walkLiteralDef( structItem.literal_def() ); break; case struct_item::Cfl: walkCflDef( structItem.cfl_def() ); break; case struct_item::Region: walkLexRegion( structItem.region_def() ); break; case struct_item::Struct: walkStructDef( structItem.struct_def() ); break; case struct_item::Function: walkFunctionDef( structItem.function_def() ); break; case struct_item::InHost: walkInHostDef( structItem.in_host_def() ); break; case struct_item::Iter: walkIterDef( structItem.iter_def() ); break; case struct_item::PreEof: walkPreEof( structItem.pre_eof_def() ); break; case struct_item::Export: walkExportDef( structItem.export_def() ); break; case struct_item::Precedence: walkPrecedenceDef( structItem.precedence_def() ); break; // case struct_item::ListEl: // listElDef( structItem.list_el_def().id().data() ); // break; // case struct_item::MapEl: { // map_el_def Def = structItem.map_el_def(); // TypeRef *keyTr = walkTypeRef( Def.type_ref() ); // mapElDef( Def.id().data(), keyTr ); // break; // } case struct_item::Alias: walkAliasDef( structItem.alias_def() ); break; } } void walkStructDef( struct_def structDef ) { String name = structDef.id().data(); structHead( structDef.id().loc(), curNspace(), name, ObjectDef::StructType ); _lrepeat_struct_item structItemList = structDef.ItemList(); RepeatIter structItemIter( structItemList ); while ( !structItemIter.end() ) { walkStructItem( structItemIter.value() ); structItemIter.next(); } structStack.pop(); namespaceStack.pop(); } void walkNamespaceDef( namespace_def NamespaceDef, StmtList *stmtList ) { String name = NamespaceDef.id().data(); createNamespace( NamespaceDef.id().loc(), name ); walkNamespaceItemList( NamespaceDef.ItemList(), stmtList ); namespaceStack.pop(); } void walkRedItem( host_item item, ReduceTextItemList &list ) { if ( item.RED_LHS() != 0 ) { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::LhsRef; list.append( rti ); } else if ( item.RED_RHS_REF() != 0 ) { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::RhsRef; rti->txt = item.RED_RHS_REF().text().c_str(); list.append( rti ); } else if ( item.RED_TREE_REF() != 0 ) { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::TreeRef; rti->txt = item.RED_TREE_REF().text().c_str(); list.append( rti ); } else if ( item.RED_RHS_LOC() != 0 ) { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::RhsLoc; rti->txt = item.RED_RHS_LOC().text().c_str(); list.append( rti ); } else if ( item.RED_RHS_NREF() != 0 ) { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::RhsRef; rti->n = atoi( item.RED_RHS_NREF().text().c_str() + 1 ); list.append( rti ); } else if ( item.RED_TREE_NREF() != 0 ) { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::TreeRef; rti->n = atoi( item.RED_TREE_NREF().text().c_str() + 2 ); list.append( rti ); } else if ( item.RED_RHS_NLOC() != 0 ) { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::RhsLoc; rti->n = atoi( item.RED_RHS_NLOC().text().c_str() + 1 ); list.append( rti ); } else if ( item.RED_OPEN() != 0 ) { ReduceTextItem *open = new ReduceTextItem; open->type = ReduceTextItem::Txt; open->txt = "{"; list.append( open ); walkRedItemList( item.HostItems(), list ); ReduceTextItem *close = new ReduceTextItem; close->type = ReduceTextItem::Txt; close->txt = "}"; list.append( close ); } else { if ( list.length() > 0 && list.tail->type == ReduceTextItem::Txt ) { std::string txt = item.text(); list.tail->txt.append( txt.c_str(), txt.size() ); } else { ReduceTextItem *rti = new ReduceTextItem; rti->type = ReduceTextItem::Txt; rti->txt = item.text().c_str(); list.append( rti ); } } } void walkRedItemList( _lrepeat_host_item itemList, ReduceTextItemList &list ) { RepeatIter itemIter( itemList ); while ( !itemIter.end() ) { walkRedItem( itemIter.value(), list ); itemIter.next(); } } void walkRedNonTerm( red_nonterm RN ) { InputLoc loc = RN.RED_OPEN().loc(); TypeRef *typeRef = walkTypeRef( RN.type_ref() ); ReduceNonTerm *rnt = new ReduceNonTerm( loc, typeRef ); walkRedItemList( RN.HostItems(), rnt->itemList ); curReduction()->reduceNonTerms.append( rnt ); } void walkRedAction( red_action RA ) { InputLoc loc = RA.RED_OPEN().loc(); String text = RA.HostItems().text().c_str(); TypeRef *typeRef = walkTypeRef( RA.type_ref() ); ReduceAction *ra = new ReduceAction( loc, typeRef, RA.id().data() ); walkRedItemList( RA.HostItems(), ra->itemList ); curReduction()->reduceActions.append( ra ); } void walkReductionItem( reduction_item reductionItem ) { switch ( reductionItem.prodName() ) { case reduction_item::NonTerm: { walkRedNonTerm( reductionItem.red_nonterm() ); break; } case reduction_item::Action: { walkRedAction( reductionItem.red_action() ); break; } } } void walkReductionList( _lrepeat_reduction_item itemList ) { RepeatIter itemIter( itemList ); while ( !itemIter.end() ) { walkReductionItem( itemIter.value() ); itemIter.next(); } } void walkRootItem( root_item rootItem, StmtList *stmtList ) { switch ( rootItem.prodName() ) { case root_item::Rl: walkRlDef( rootItem.rl_def() ); break; case root_item::Token: walkTokenDef( rootItem.token_def() ); break; case root_item::IgnoreCollector: walkIgnoreCollector( rootItem.ic_def() ); break; case root_item::Ignore: walkIgnoreDef( rootItem.ignore_def() ); break; case root_item::Literal: walkLiteralDef( rootItem.literal_def() ); break; case root_item::CflDef: walkCflDef( rootItem.cfl_def() ); break; case root_item::CflRedef: walkCflRedef( rootItem.cfl_redef() ); break; case root_item::Region: walkLexRegion( rootItem.region_def() ); break; case root_item::Statement: { LangStmt *stmt = walkStatement( rootItem.statement() ); if ( stmt != 0 ) stmtList->append( stmt ); break; } case root_item::Struct: walkStructDef( rootItem.struct_def() ); break; case root_item::Namespace: walkNamespaceDef( rootItem.namespace_def(), stmtList ); break; case root_item::Function: walkFunctionDef( rootItem.function_def() ); break; case root_item::InHost: walkInHostDef( rootItem.in_host_def() ); break; case root_item::Iter: walkIterDef( rootItem.iter_def() ); break; case root_item::PreEof: walkPreEof( rootItem.pre_eof_def() ); break; case root_item::Export: { LangStmt *stmt = walkExportDef( rootItem.export_def() ); if ( stmt != 0 ) stmtList->append( stmt ); break; } case root_item::Alias: walkAliasDef( rootItem.alias_def() ); break; case root_item::Precedence: walkPrecedenceDef( rootItem.precedence_def() ); break; case root_item::Include: { StmtList *includeList = walkInclude( rootItem._include() ); if ( includeList ) stmtList->append( *includeList ); break; } case root_item::Global: { LangStmt *stmt = walkGlobalDef( rootItem.global_def() ); if ( stmt != 0 ) stmtList->append( stmt ); break; } case root_item::Reduction: { reduction_def RD = rootItem.reduction_def(); InputLoc loc = RD.REDUCTION().loc(); String id = RD.id().data(); createReduction( loc, id ); walkReductionList( RD.ItemList() ); reductionStack.pop(); break; }} } void walkNamespaceItem( namespace_item item, StmtList *stmtList ) { switch ( item.prodName() ) { case namespace_item::Rl: walkRlDef( item.rl_def() ); break; case namespace_item::Token: walkTokenDef( item.token_def() ); break; case namespace_item::IgnoreCollector: walkIgnoreCollector( item.ic_def() ); break; case namespace_item::Ignore: walkIgnoreDef( item.ignore_def() ); break; case namespace_item::Literal: walkLiteralDef( item.literal_def() ); break; case namespace_item::Cfl: walkCflDef( item.cfl_def() ); break; case namespace_item::Region: walkLexRegion( item.region_def() ); break; case namespace_item::Struct: walkStructDef( item.struct_def() ); break; case namespace_item::Namespace: walkNamespaceDef( item.namespace_def(), stmtList ); break; case namespace_item::Function: walkFunctionDef( item.function_def() ); break; case namespace_item::InHost: walkInHostDef( item.in_host_def() ); break; case namespace_item::Iter: walkIterDef( item.iter_def() ); break; case namespace_item::PreEof: walkPreEof( item.pre_eof_def() ); break; case namespace_item::Alias: walkAliasDef( item.alias_def() ); break; case namespace_item::Precedence: walkPrecedenceDef( item.precedence_def() ); break; case namespace_item::Include: { StmtList *includeList = walkInclude( item._include() ); stmtList->append( *includeList ); break; } case namespace_item::Global: { LangStmt *stmt = walkGlobalDef( item.global_def() ); if ( stmt != 0 ) stmtList->append( stmt ); break; }} } bool walkNoIgnoreLeft( no_ignore_left OptNoIngore ) { return OptNoIngore.prodName() == no_ignore_left::Ni; } bool walkNoIgnoreRight( no_ignore_right OptNoIngore ) { return OptNoIngore.prodName() == no_ignore_right::Ni; } bool walkOptEos( opt_eos OptEos ) { opt_eos::prod_name pn = OptEos.prodName(); return pn == opt_eos::Dot || pn == opt_eos::Eos; } void walkLiteralItem( literal_item literalItem ) { bool niLeft = walkNoIgnoreLeft( literalItem.no_ignore_left() ); bool niRight = walkNoIgnoreRight( literalItem.no_ignore_right() ); String lit = literalItem.backtick_lit().data(); literalDef( literalItem.backtick_lit().loc(), lit, niLeft, niRight ); } void walkLiteralList( literal_list literalList ) { if ( literalList.prodName() == literal_list::Item ) walkLiteralList( literalList._literal_list() ); walkLiteralItem( literalList.literal_item() ); } void walkLiteralDef( literal_def literalDef ) { walkLiteralList( literalDef.literal_list() ); } void walkNamespaceItemList( _lrepeat_namespace_item itemList, StmtList *stmtList ) { /* Walk the list of items. */ RepeatIter itemIter( itemList ); while ( !itemIter.end() ) { walkNamespaceItem( itemIter.value(), stmtList ); itemIter.next(); } } StmtList *walkRootItemList( _lrepeat_root_item rootItemList ) { StmtList *stmtList = new StmtList; /* Walk the list of items. */ RepeatIter rootItemIter( rootItemList ); while ( !rootItemIter.end() ) { walkRootItem( rootItemIter.value(), stmtList ); rootItemIter.next(); } return stmtList; } virtual void go( long activeRealm ); }; void LoadColm::go( long activeRealm ) { LoadColm::init(); const char *argv[3]; argv[0] = "load-colm"; argv[1] = inputFileName; argv[2] = 0; colm_program *program = colm_new_program( &colm_object ); colm_set_debug( program, activeRealm ); colm_run_program( program, 2, argv ); /* Extract the parse tree. */ start Start = ColmTree( program ); str Error = ColmError( program ); if ( Start == 0 ) { gblErrorCount += 1; InputLoc loc = Error.loc(); error(loc) << inputFileName << ": parse error: " << Error.text() << std::endl; return; } StmtList *stmtList = walkRootItemList( Start.RootItemList() ); pd->streamFileNames.append( colm_extract_fns( program ) ); colm_delete_program( program ); pd->rootCodeBlock = CodeBlock::cons( stmtList, 0 ); } BaseParser *consLoadColm( Compiler *pd, const char *inputFileName ) { return new LoadColm( pd, inputFileName ); }