summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2020-04-12 11:48:15 +0000
committerAdrian Thurston <thurston@colm.net>2020-04-12 11:48:15 +0000
commit8b1810c9fd897d8d2840a0713ced1dfcfb71d109 (patch)
tree1af9de3a0d05e2a6ea507401840e75e27bfc37f6 /src
parent9760b2b3d8477ffb4228ac3db976e2ed3abb8905 (diff)
downloadcolm-8b1810c9fd897d8d2840a0713ced1dfcfb71d109.tar.gz
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
Diffstat (limited to 'src')
-rw-r--r--src/colm.lm38
-rw-r--r--src/compiler.h11
-rw-r--r--src/declare.cc30
-rw-r--r--src/loadfinal.cc71
-rw-r--r--src/parser.cc32
-rw-r--r--src/parsetree.h3
6 files changed, 136 insertions, 49 deletions
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;
};