From 8b1810c9fd897d8d2840a0713ced1dfcfb71d109 Mon Sep 17 00:00:00 2001 From: Adrian Thurston Date: Sun, 12 Apr 2020 11:48:15 +0000 Subject: first cut of a redefine statement Redefine happens during declaration. The existing langEl is removed from the map and a newly-declared lel replaces it. If the new list of productions references [...] the productions from the previous lel are moved into the new one, in its place. A copy would be preferrable, as move may require some fixup, but move gives an initial functional implementation. refs #112 --- src/colm.lm | 38 +++++++++++++++++++----------- src/compiler.h | 11 ++++++++- src/declare.cc | 30 +++++++++++++++++++++++- src/loadfinal.cc | 71 ++++++++++++++++++++++++++++++++++++++++++-------------- src/parser.cc | 32 +++++++++++++------------ src/parsetree.h | 3 +++ 6 files changed, 136 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/colm.lm b/src/colm.lm index c95d0c41..16a9eeb5 100644 --- a/src/colm.lm +++ b/src/colm.lm @@ -1,6 +1,7 @@ # Main region. lex token DEF / 'def' / + token REDEF / 'redef' / token LEX / 'lex' / token END / 'end' / token TOKEN / 'token' / @@ -108,13 +109,13 @@ lex token STAR /'*'/ token QUESTION /'?'/ token EQUALS /'='/ - token EQEQ /'=='/ - token NEQ /'!='/ + token EQ_EQ /'=='/ + token BANG_EQ /'!='/ token COMMA /','/ token LT /'<'/ token GT /'>'/ - token LTEQ /'<='/ - token GTEQ /'>='/ + token LT_EQ /'<='/ + token GT_EQ /'>='/ token BANG /'!'/ token DOLLAR /'$'/ token CARET /'^'/ @@ -122,8 +123,9 @@ lex token PERCENT /'%'/ token PLUS /'+'/ token MINUS /'-'/ - token AMPAMP /'&&'/ - token BARBAR /'||'/ + token AMP_AMP /'&&'/ + token BAR_BAR /'||'/ + token DOT_DOT_DOT /'...'/ ignore / ( '\n' | '\t' | ' ' )+ / ignore / '#' . ( ^'\n' )* . '\n' / @@ -214,7 +216,8 @@ def root_item | [token_def] :Token commit | [ic_def] :IgnoreCollector commit | [ignore_def] :Ignore commit -| [cfl_def] :Cfl commit +| [cfl_def] :CflDef commit +| [cfl_redef] :CflRedef commit | [region_def] :Region commit | [struct_def] :Struct commit | [namespace_def] :Namespace commit @@ -441,6 +444,12 @@ def cfl_def opt_reduce_first prod_list] +def cfl_redef + [REDEF id + VarDefList: var_def<* + opt_reduce_first + prod_list] + def region_def [LEX RootItemList: root_item<* END] @@ -501,7 +510,8 @@ def prod [SQOPEN prod_el_list SQCLOSE opt_prod_name opt_commit - opt_reduce] + opt_reduce] :Prod +| [SQOPEN DOT_DOT_DOT SQCLOSE] :DotDotDot def opt_reduce [COPEN lang_stmt_list CCLOSE] :Reduce @@ -601,17 +611,17 @@ def expr_stmt [code_expr] def code_expr - [code_expr AMPAMP code_relational] :AmpAmp -| [code_expr BARBAR code_relational] :BarBar + [code_expr AMP_AMP code_relational] :AmpAmp +| [code_expr BAR_BAR code_relational] :BarBar | [code_relational] :Base def code_relational - [code_relational EQEQ code_additive] :EqEq -| [code_relational NEQ code_additive] :Neq + [code_relational EQ_EQ code_additive] :EqEq +| [code_relational BANG_EQ code_additive] :Neq | [code_relational LT code_additive] :Lt | [code_relational GT code_additive] :Gt -| [code_relational LTEQ code_additive] :LtEq -| [code_relational GTEQ code_additive] :GtEq +| [code_relational LT_EQ code_additive] :LtEq +| [code_relational GT_EQ code_additive] :GtEq | [code_additive] :Base def code_additive diff --git a/src/compiler.h b/src/compiler.h index 67d5b40e..d5732b6e 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -152,7 +152,7 @@ struct Production : prodName(0), prodElList(0), prodCommit(false), redBlock(0), prodId(0), prodNum(0), fsm(0), fsmLength(0), uniqueEmptyLeader(0), - isLeftRec(false), localFrame(0), lhsField(0), predOf(0) + isLeftRec(false), localFrame(0), lhsField(0), predOf(0), dotDotDot(false) {} static Production* cons( const InputLoc &loc, LangEl *prodName, ProdElList *prodElList, @@ -170,6 +170,14 @@ struct Production return p; } + static Production *cons( const InputLoc &loc ) + { + Production *p = new Production; + p->loc = loc; + p->dotDotDot = true; + return p; + } + InputLoc loc; LangEl *prodName; ProdElList *prodElList; @@ -198,6 +206,7 @@ struct Production LangEl *predOf; UnsignedCharVect copy; + bool dotDotDot; }; struct CmpDefById diff --git a/src/declare.cc b/src/declare.cc index b96092e2..74037666 100644 --- a/src/declare.cc +++ b/src/declare.cc @@ -471,8 +471,36 @@ void Namespace::declare( Compiler *pd ) for ( NtDefList::Iter n = ntDefList; n.lte(); n++ ) { /* Get the language element. */ + if ( n->isRedef ) { + TypeMapEl *inDict = this->typeMap.find( n->name ); + if ( inDict == 0 ) { + error() << "redef not found '" << n->name << endp; + } + + LangEl *langEl = inDict->value; + this->typeMap.remove( n->name ); + + /* Traverse the list of productions, moving to combined and taking + * the original language element's productions when we enounter + * [...]. Afterwards move the newly combined productions + * to the nonterminal-definition and proceed with the declaration. */ + LelDefList combined; + while ( n->defList->length() > 0 ) { + Production *prod = n->defList->detachFirst(); + if ( prod->dotDotDot ) { + prod->prodNum = combined.length(); + combined.append( langEl->defList ); + } + else { + combined.append( prod ); + } + } + + /* Move bak to non-term def and proceed with rest of declaration. */ + n->defList->transfer( combined ); + } + LangEl *langEl = declareLangEl( pd, this, n->name, LangEl::NonTerm ); - //$$->langEl = langEl; /* Get the language element. */ langEl->objectDef = n->objectDef; diff --git a/src/loadfinal.cc b/src/loadfinal.cc index 0fddd360..0f9acaa4 100644 --- a/src/loadfinal.cc +++ b/src/loadfinal.cc @@ -211,7 +211,7 @@ struct LoadColm LangExpr *relational = walkCodeRelational( codeExpr.code_relational() ); LangExpr *left = walkCodeExpr( codeExpr._code_expr() ); - InputLoc loc = codeExpr.AMPAMP().loc(); + InputLoc loc = codeExpr.AMP_AMP().loc(); expr = LangExpr::cons( loc, left, OP_LogicalAnd, relational ); break; } @@ -219,7 +219,7 @@ struct LoadColm LangExpr *relational = walkCodeRelational( codeExpr.code_relational() ); LangExpr *left = walkCodeExpr( codeExpr._code_expr() ); - InputLoc loc = codeExpr.BARBAR().loc(); + InputLoc loc = codeExpr.BAR_BAR().loc(); expr = LangExpr::cons( loc, left, OP_LogicalOr, relational ); break; } @@ -1091,30 +1091,44 @@ struct LoadColm return block; } - void walkProdudction( const String &defName, LelDefList *lelDefList, prod Prod ) + void walkProdudction( const String &defName, + LelDefList *lelDefList, prod Prod, bool inRedef ) { - ProdElList *list = new ProdElList; + 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() ); + 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(); + 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; + 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 ); + Production *prod = BaseParser::production( Prod.SQOPEN().loc(), + list, name, commit, codeBlock, 0 ); + prodAppend( lelDefList, prod ); + } } - void walkProdList( const String &name, LelDefList *lelDefList, prod_list ProdList ) + void walkProdList( const String &name, LelDefList *lelDefList, + prod_list ProdList, bool inRedef ) { if ( ProdList.prodName() == prod_list::List ) - walkProdList( name, lelDefList, ProdList._prod_list() ); + walkProdList( name, lelDefList, ProdList._prod_list(), inRedef ); - walkProdudction( name, lelDefList, ProdList.prod() ); + walkProdudction( name, lelDefList, ProdList.prod(), inRedef ); } ReOrItem *walkRegOrChar( reg_or_char regOrChar ) @@ -1320,7 +1334,7 @@ struct LoadColm objectDef->name = name; LelDefList *defList = new LelDefList; - walkProdList( name, defList, cflDef.prod_list() ); + walkProdList( name, defList, cflDef.prod_list(), false ); bool reduceFirst = cflDef.opt_reduce_first().REDUCEFIRST() != 0; @@ -1330,6 +1344,24 @@ struct LoadColm BaseParser::cflDef( ntDef, objectDef, defList ); } + void walkCflRedef( cfl_redef cflRedef ) + { + String name = cflRedef.id().data(); + ObjectDef *objectDef = walkVarDefList( cflRedef.VarDefList() ); + objectDef->name = name; + + LelDefList *defList = new LelDefList; + walkProdList( name, defList, 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, defList ); + } + CallArgVect *walkCallArgSeq( call_arg_seq callArgSeq ) { CallArgVect *callArgVect = new CallArgVect; @@ -2748,9 +2780,12 @@ struct LoadColm case root_item::Literal: walkLiteralDef( rootItem.literal_def() ); break; - case root_item::Cfl: + 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; diff --git a/src/parser.cc b/src/parser.cc index a41288b1..9a711088 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -574,22 +574,24 @@ void BaseParser::cflDef( NtDef *ntDef, ObjectDef *objectDef, LelDefList *defList /* Declare the captures in the object. */ for ( LelDefList::Iter prod = *defList; prod.lte(); prod++ ) { - for ( ProdElList::Iter pel = *prod->prodElList; pel.lte(); pel++ ) { - /* If there is a capture, create the field. */ - if ( pel->captureField != 0 ) { - /* Might already exist. */ - ObjectField *newOf = objectDef->rootScope->checkRedecl( - pel->captureField->name ); - if ( newOf != 0 ) { - /* FIXME: check the types are the same. */ + if ( prod->prodElList != 0 ) { + for ( ProdElList::Iter pel = *prod->prodElList; pel.lte(); pel++ ) { + /* If there is a capture, create the field. */ + if ( pel->captureField != 0 ) { + /* Might already exist. */ + ObjectField *newOf = objectDef->rootScope->checkRedecl( + pel->captureField->name ); + if ( newOf != 0 ) { + /* FIXME: check the types are the same. */ + } + else { + newOf = pel->captureField; + newOf->typeRef = pel->typeRef; + objectDef->rootScope->insertField( newOf->name, newOf ); + } + + newOf->rhsVal.append( RhsVal( pel ) ); } - else { - newOf = pel->captureField; - newOf->typeRef = pel->typeRef; - objectDef->rootScope->insertField( newOf->name, newOf ); - } - - newOf->rhsVal.append( RhsVal( pel ) ); } } } diff --git a/src/parsetree.h b/src/parsetree.h index f2d94226..2f0a8660 100644 --- a/src/parsetree.h +++ b/src/parsetree.h @@ -508,6 +508,7 @@ struct NtDef nt->objectDef = objectDef; nt->contextIn = contextIn; nt->reduceFirst = reduceFirst; + nt->isRedef = false; return nt; } @@ -523,6 +524,7 @@ struct NtDef nt->objectDef = 0; nt->contextIn = contextIn; nt->reduceFirst = reduceFirst; + nt->isRedef = false; return nt; } @@ -533,6 +535,7 @@ struct NtDef ObjectDef *objectDef; StructDef *contextIn; bool reduceFirst; + bool isRedef; NtDef *prev, *next; }; -- cgit v1.2.1