summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2018-12-17 14:10:50 +0200
committerAdrian Thurston <thurston@colm.net>2018-12-17 14:11:53 +0200
commiteccfd443ed78c614c396c542a07673c113f1ecd3 (patch)
tree297658178b1f24d53c476c9fa62f5a44b9a87d9a /src
parentfc1d61f4cab2260e90fcd468078eaa0d2046f372 (diff)
downloadcolm-eccfd443ed78c614c396c542a07673c113f1ecd3.tar.gz
allow referencing a tree in reduction actions
syntax is $*N
Diffstat (limited to 'src')
-rw-r--r--src/colm.lm4
-rw-r--r--src/compiler.h3
-rw-r--r--src/loadcolm.cc12
-rw-r--r--src/parsetree.h1
-rw-r--r--src/reduce.cc67
5 files changed, 78 insertions, 9 deletions
diff --git a/src/colm.lm b/src/colm.lm
index 2bd4497a..a8e398cf 100644
--- a/src/colm.lm
+++ b/src/colm.lm
@@ -364,9 +364,11 @@ lex
token RED_LHS / '$' . '$' /
token RED_RHS_REF / '$' . red_id /
token RED_RHS_LOC / '@' . red_id /
+ token RED_TREE_REF / '$*' . red_id /
token RED_RHS_NREF / '$' . ('1' .. '9') . ('0' .. '9')* /
token RED_RHS_NLOC / '@' . ('1' .. '9') . ('0' .. '9')* /
+ token RED_TREE_NREF / '$*' . ('1' .. '9') . ('0' .. '9')* /
token red_any / any /
end
@@ -385,8 +387,10 @@ def host_item
| [red_any]
| [RED_LHS]
| [RED_RHS_REF]
+| [RED_TREE_REF]
| [RED_RHS_LOC]
| [RED_RHS_NREF]
+| [RED_TREE_NREF]
| [RED_RHS_NLOC]
| [RED_OPEN HostItems: host_item* RED_CLOSE]
diff --git a/src/compiler.h b/src/compiler.h
index 9ad38ee2..ac4a67e6 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -1056,7 +1056,7 @@ struct Compiler
void initReductionNeeds( Reduction *reduction );
- void findRhsRefs( bool &lhsUsed, Vector<ProdEl*> &rhsUsed,
+ void findRhsRefs( bool &lhsUsed, Vector<ProdEl*> &rhsUsed, Vector<ProdEl*> &treeUsed,
Vector<ProdEl*> &locUsed, Reduction *reduction, Production *production,
const ReduceTextItemList &list );
@@ -1082,6 +1082,7 @@ struct Compiler
void writeLhsRef( Production *production, ReduceTextItem *i );
void writeRhsRef( Production *production, ReduceTextItem *i );
+ void writeTreeRef( Production *production, ReduceTextItem *i );
void writeRhsLoc( Production *production, ReduceTextItem *i );
void writeHostItemList( Production *production, const ReduceTextItemList &list );
void writeCommitStub();
diff --git a/src/loadcolm.cc b/src/loadcolm.cc
index b622f3f2..1b0dba85 100644
--- a/src/loadcolm.cc
+++ b/src/loadcolm.cc
@@ -2474,6 +2474,12 @@ struct LoadColm
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;
@@ -2486,6 +2492,12 @@ struct LoadColm
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;
diff --git a/src/parsetree.h b/src/parsetree.h
index f81bdbec..599c16b7 100644
--- a/src/parsetree.h
+++ b/src/parsetree.h
@@ -928,6 +928,7 @@ struct ReduceTextItem
enum Type {
LhsRef,
RhsRef,
+ TreeRef,
RhsLoc,
Txt
};
diff --git a/src/reduce.cc b/src/reduce.cc
index 6e010779..89a95015 100644
--- a/src/reduce.cc
+++ b/src/reduce.cc
@@ -47,13 +47,14 @@ void Compiler::writeCommitStub()
;
}
-void Compiler::findRhsRefs( bool &lhsUsed, Vector<ProdEl*> &rhsUsed,
+void Compiler::findRhsRefs( bool &lhsUsed, Vector<ProdEl*> &rhsUsed, Vector<ProdEl*> &treeUsed,
Vector<ProdEl*> &locUsed, Reduction *reduction, Production *production,
const ReduceTextItemList &list )
{
ObjectDef *objectDef = production->prodName->objectDef;
rhsUsed.setAsNew( production->prodElList->length() );
+ treeUsed.setAsNew( production->prodElList->length() );
locUsed.setAsNew( production->prodElList->length() );
for ( ReduceTextItemList::Iter i = list; i.lte(); i++ ) {
@@ -61,7 +62,10 @@ void Compiler::findRhsRefs( bool &lhsUsed, Vector<ProdEl*> &rhsUsed,
lhsUsed = true;
}
- if ( i->type == ReduceTextItem::RhsRef || i->type == ReduceTextItem::RhsLoc ) {
+ if ( i->type == ReduceTextItem::RhsRef ||
+ i->type == ReduceTextItem::RhsLoc ||
+ i->type == ReduceTextItem::TreeRef )
+ {
if ( i->n > 0 ) {
/* Numbered. */
ProdEl *prodEl = production->prodElList->head;
@@ -73,6 +77,8 @@ void Compiler::findRhsRefs( bool &lhsUsed, Vector<ProdEl*> &rhsUsed,
if ( i->type == ReduceTextItem::RhsLoc )
locUsed[i->n-1] = prodEl;
+ else if ( i->type == ReduceTextItem::TreeRef )
+ treeUsed[i->n-1] = prodEl;
else
rhsUsed[i->n-1] = prodEl;
}
@@ -100,9 +106,10 @@ void Compiler::computeNeeded( Reduction *reduction, Production *production,
{
bool lhsUsed = false;
Vector<ProdEl*> rhsUsed;
+ Vector<ProdEl*> treeUsed;
Vector<ProdEl*> locUsed;
- findRhsRefs( lhsUsed, rhsUsed, locUsed, reduction, production, list );
+ findRhsRefs( lhsUsed, rhsUsed, treeUsed, locUsed, reduction, production, list );
/* Same length, can concurrently walk with one test. */
Vector<ProdEl*>::Iter rhs = rhsUsed;
@@ -126,9 +133,10 @@ void Compiler::loadRefs( Reduction *reduction, Production *production,
{
bool lhsUsed = false;
Vector<ProdEl*> rhsUsed;
+ Vector<ProdEl*> treeUsed;
Vector<ProdEl*> locUsed;
- findRhsRefs( lhsUsed, rhsUsed, locUsed, reduction, production, list );
+ findRhsRefs( lhsUsed, rhsUsed, treeUsed, locUsed, reduction, production, list );
if ( lhsUsed ) {
*outStream << " lel_" << production->prodName->fullName << " *_lhs = ";
@@ -200,9 +208,8 @@ void Compiler::loadRefs( Reduction *reduction, Production *production,
}
}
- /* In the second pass we load using a tree cursor. This is for token data
- * and locations.
- */
+ /* In the second pass we load using a tree cursor. This is for token/tree
+ * data and locations. */
useCursor = false;
for ( Vector<ProdEl*>::Iter rhs = rhsUsed; rhs.lte(); rhs++ ) {
@@ -213,6 +220,12 @@ void Compiler::loadRefs( Reduction *reduction, Production *production,
break;
}
}
+ for ( Vector<ProdEl*>::Iter rhs = treeUsed; rhs.lte(); rhs++ ) {
+ if ( *rhs != 0 ) {
+ useCursor = true;
+ break;
+ }
+ }
for ( Vector<ProdEl*>::Iter loc = locUsed; loc.lte(); loc++ ) {
if ( *loc != 0 ) {
useCursor = true;
@@ -234,12 +247,12 @@ void Compiler::loadRefs( Reduction *reduction, Production *production,
/* Same length, can concurrently walk with one test. */
Vector<ProdEl*>::Iter rhs = rhsUsed;
+ Vector<ProdEl*>::Iter tree = treeUsed;
Vector<ProdEl*>::Iter loc = locUsed;
for ( ; rhs.lte(); rhs++, loc++ ) {
ProdEl *prodEl = *rhs;
-
if ( prodEl != 0 ) {
if ( prodEl->production == production ) {
if ( prodEl->langEl->type == LangEl::Term ) {
@@ -262,7 +275,20 @@ void Compiler::loadRefs( Reduction *reduction, Production *production,
}
}
}
+ }
+
+ ProdEl *treeEl = *tree;
+ if ( treeEl != 0 ) {
+ if ( treeEl->production == production ) {
+ while ( cursorPos < rhs.pos() ) {
+ *outStream <<
+ " _tree_cursor = _tree_cursor->next;\n";
+ cursorPos += 1;
+ }
+ *outStream << " colm_tree *_tree" << rhs.pos() << " = ";
+ *outStream << "_tree_cursor->tree;\n";
+ }
}
ProdEl *locEl = *loc;
@@ -313,6 +339,28 @@ void Compiler::writeRhsRef( Production *production, ReduceTextItem *i )
}
}
+void Compiler::writeTreeRef( Production *production, ReduceTextItem *i )
+{
+ if ( i->n > 0 ) {
+ *outStream << "_tree" << ( i->n - 1 );
+ }
+ else {
+ ObjectDef *objectDef = production->prodName->objectDef;
+ String name( i->txt.data + 1, i->txt.length() - 1 );
+
+ /* Find the field in the rhsVal using capture field. */
+ ObjectField *field = objectDef->rootScope->findField( name );
+ if ( field != 0 ) {
+ for ( Vector<RhsVal>::Iter r = field->rhsVal;
+ r.lte(); r++ )
+ {
+ if ( r->prodEl->production == production )
+ *outStream << "_tree" << r->prodEl->pos;
+ }
+ }
+ }
+}
+
void Compiler::writeRhsLoc( Production *production, ReduceTextItem *i )
{
if ( i->n > 0 ) {
@@ -351,6 +399,9 @@ void Compiler::writeHostItemList( Production *production,
case ReduceTextItem::RhsRef:
writeRhsRef( production, i );
break;
+ case ReduceTextItem::TreeRef:
+ writeTreeRef( production, i );
+ break;
case ReduceTextItem::RhsLoc:
writeRhsLoc( production, i );
break;