summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2019-12-22 21:25:26 +0200
committerAdrian Thurston <thurston@colm.net>2019-12-22 21:25:26 +0200
commitbab5d696ff8edffd48530ab11d677b57c66c4887 (patch)
treedec2edc8a0161e97a0cf58876d7923309ec2f019
parentcdaa1ab24a06ccbf71987b1516a96028a9c61b67 (diff)
downloadcolm-bab5d696ff8edffd48530ab11d677b57c66c4887.tar.gz
use left-recursing in the colm grammar
Also moved the implementation to C++ because for the time being we need to generate an appropriate iterator in the export interface. Need a genereric repeat iterator to avoid this situation.
-rw-r--r--colm/colm.h2
-rw-r--r--colm/colm.lm76
-rw-r--r--colm/compiler.cc15
-rw-r--r--colm/compiler.h5
-rw-r--r--colm/consinit.cc12
-rw-r--r--colm/exports.cc39
-rw-r--r--colm/loadfinal.cc2
-rw-r--r--colm/loadinit.cc2
-rw-r--r--colm/parsetree.h3
-rw-r--r--colm/pdabuild.cc1
-rw-r--r--colm/prog.lm22
-rw-r--r--colm/resolve.cc9
-rw-r--r--colm/tree.c24
13 files changed, 142 insertions, 70 deletions
diff --git a/colm/colm.h b/colm/colm.h
index 55368840..5091d27e 100644
--- a/colm/colm.h
+++ b/colm/colm.h
@@ -95,6 +95,8 @@ struct colm_tree *colm_get_attr( struct colm_tree *tree, long pos );
struct colm_tree *colm_get_global( struct colm_program *prg, long pos );
struct colm_tree *colm_get_repeat_next( struct colm_tree *tree );
struct colm_tree *colm_get_repeat_val( struct colm_tree *tree );
+struct colm_tree *colm_get_left_repeat_next( struct colm_tree *tree );
+struct colm_tree *colm_get_left_repeat_val( struct colm_tree *tree );
struct colm_location *colm_find_location( struct colm_program *prg, struct colm_tree *tree );
/* Debug realms. To turn on, pass to colm_set_debug before invocation. */
diff --git a/colm/colm.lm b/colm/colm.lm
index efbd7a65..4ebe11b8 100644
--- a/colm/colm.lm
+++ b/colm/colm.lm
@@ -206,7 +206,7 @@ lex
end
def start
- [RootItemList: root_item*]
+ [RootItemList: root_item<*]
def root_item
[rl_def] :Rl commit
@@ -231,7 +231,7 @@ def root_item
| [reduction_def] :Reduction commit
def _include
- [INCLUDE SQ SqConsDataList: sq_cons_data* sq_lit_term]
+ [INCLUDE SQ SqConsDataList: sq_cons_data<* sq_lit_term]
def precedence_def
[pred_type pred_token_list]
@@ -319,7 +319,7 @@ def struct_key
[STRUCT] | [CONTEXT]
def struct_def
- [struct_key id ItemList: struct_item* END]
+ [struct_key id ItemList: struct_item<* END]
def literal_keyword
[LITERAL]
@@ -344,7 +344,7 @@ def no_ignore_right
| []
def reduction_def
- [REDUCTION id ItemList: reduction_item* END]
+ [REDUCTION id ItemList: reduction_item<* END]
lex
token RED_OPEN / '{' /
@@ -382,10 +382,10 @@ lex
end
def red_nonterm
- [type_ref RED_OPEN HostItems: host_item* RED_CLOSE]
+ [type_ref RED_OPEN HostItems: host_item<* RED_CLOSE]
def red_action
- [type_ref COLON id RED_OPEN HostItems: host_item* RED_CLOSE]
+ [type_ref COLON id RED_OPEN HostItems: host_item<* RED_CLOSE]
def host_item
[red_id]
@@ -400,14 +400,14 @@ def host_item
| [RED_RHS_NREF]
| [RED_TREE_NREF]
| [RED_RHS_NLOC]
-| [RED_OPEN HostItems: host_item* RED_CLOSE]
+| [RED_OPEN HostItems: host_item<* RED_CLOSE]
def reduction_item
[red_nonterm] :NonTerm commit
| [red_action] :Action commit
def namespace_def
- [NAMESPACE id ItemList: namespace_item* END]
+ [NAMESPACE id ItemList: namespace_item<* END]
def namespace_item
[rl_def] :Rl commit
@@ -437,12 +437,12 @@ def opt_reduce_first
def cfl_def
[DEF id
- VarDefList: var_def*
+ VarDefList: var_def<*
opt_reduce_first
prod_list]
def region_def
- [LEX RootItemList: root_item* END]
+ [LEX RootItemList: root_item<* END]
def rl_def
[RL id LEX_FSLASH lex_expr LEX_FSLASH]
@@ -452,7 +452,7 @@ def opt_lex_expr
| []
def token_def
- [TOKEN id VarDefList: var_def*
+ [TOKEN id VarDefList: var_def<*
no_ignore_left
LEX_FSLASH opt_lex_expr LEX_FSLASH
no_ignore_right
@@ -583,7 +583,7 @@ def opt_require_stmt
| [] :Base
def lang_stmt_list
- [StmtList: statement* opt_require_stmt]
+ [StmtList: statement<* opt_require_stmt]
def opt_def_init
[EQUALS code_expr] :Init
@@ -680,7 +680,7 @@ def opt_capture
| []
def opt_field_init
- [POPEN FieldInitList: field_init* PCLOSE] :Init
+ [POPEN FieldInitList: field_init<* PCLOSE] :Init
| [] :Base
def field_init
@@ -698,7 +698,7 @@ def stmt_or_factor
| [MAKE_TOKEN POPEN call_arg_list PCLOSE] :MakeToken
| [CONS opt_capture type_ref opt_field_init constructor] :Cons
| [MATCH var_ref pattern] :Match
-| [NEW opt_capture type_ref POPEN FieldInitList: field_init* PCLOSE] :New
+| [NEW opt_capture type_ref POPEN FieldInitList: field_init<* PCLOSE] :New
#
# Pattern
@@ -724,19 +724,19 @@ def pattern_el_lel
def pattern_el
[opt_label pattern_el_lel] :PatternEl
-| [DQ LitpatElList: litpat_el* dq_lit_term] :Dq
-| [SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+| [DQ LitpatElList: litpat_el<* dq_lit_term] :Dq
+| [SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [TILDE opt_tilde_data TILDE_NL] :Tilde
def litpat_el
[lit_dq_data] :ConsData
-| [LIT_SQOPEN PatternElList: pattern_el* LIT_SQCLOSE] :SubList
+| [LIT_SQOPEN PatternElList: pattern_el<* LIT_SQCLOSE] :SubList
def pattern_top_el
- [DQ LitpatElList: litpat_el* dq_lit_term] :Dq
-| [SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+ [DQ LitpatElList: litpat_el<* dq_lit_term] :Dq
+| [SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [TILDE opt_tilde_data TILDE_NL] :Tilde
-| [SQOPEN PatternElList: pattern_el* SQCLOSE] :SubList
+| [SQOPEN PatternElList: pattern_el<* SQCLOSE] :SubList
def pattern_list
[pattern_top_el] :Base
@@ -755,20 +755,20 @@ def E4 []
def cons_el
[E1 region_qual backtick_lit] :Lit
-| [E1 DQ LitConsElList: lit_cons_el* dq_lit_term] :Dq
-| [E1 SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+| [E1 DQ LitConsElList: lit_cons_el<* dq_lit_term] :Dq
+| [E1 SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [E1 TILDE opt_tilde_data TILDE_NL] :Tilde
| [E2 code_expr] :CodeExpr
def lit_cons_el
[lit_dq_data] :ConsData
-| [LIT_SQOPEN ConsElList: cons_el* LIT_SQCLOSE] :SubList
+| [LIT_SQOPEN ConsElList: cons_el<* LIT_SQCLOSE] :SubList
def cons_top_el
- [DQ LitConsElList: lit_cons_el* dq_lit_term] :Dq
-| [SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+ [DQ LitConsElList: lit_cons_el<* dq_lit_term] :Dq
+| [SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [TILDE opt_tilde_data TILDE_NL] :Tilde
-| [SQOPEN ConsElList: cons_el* SQCLOSE] :SubList
+| [SQOPEN ConsElList: cons_el<* SQCLOSE] :SubList
def cons_list
[cons_top_el] :Base
@@ -781,20 +781,20 @@ def constructor
#
def accum_el
- [E1 DQ LitAccumElList: lit_accum_el* dq_lit_term] :Dq
-| [E1 SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+ [E1 DQ LitAccumElList: lit_accum_el<* dq_lit_term] :Dq
+| [E1 SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [E1 TILDE opt_tilde_data TILDE_NL] :Tilde
| [E2 code_expr] :CodeExpr
def lit_accum_el
[lit_dq_data] :ConsData
-| [LIT_SQOPEN AccumElList: accum_el* LIT_SQCLOSE] :SubList
+| [LIT_SQOPEN AccumElList: accum_el<* LIT_SQCLOSE] :SubList
def accum_top_el
- [DQ LitAccumElList: lit_accum_el* dq_lit_term] :Dq
-| [SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+ [DQ LitAccumElList: lit_accum_el<* dq_lit_term] :Dq
+| [SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [TILDE opt_tilde_data TILDE_NL] :Tilde
-| [SQOPEN AccumElList: accum_el* SQCLOSE] :SubList
+| [SQOPEN AccumElList: accum_el<* SQCLOSE] :SubList
def accum_list
[accum_top_el accum_list] :List
@@ -808,20 +808,20 @@ def accumulate
#
def string_el
- [E1 DQ LitStringElList: lit_string_el* dq_lit_term] :Dq
-| [E1 SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+ [E1 DQ LitStringElList: lit_string_el<* dq_lit_term] :Dq
+| [E1 SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [E1 TILDE opt_tilde_data TILDE_NL] :Tilde
| [E2 code_expr] :CodeExpr
def lit_string_el
[lit_dq_data] :ConsData
-| [LIT_SQOPEN StringElList: string_el* LIT_SQCLOSE] :SubList
+| [LIT_SQOPEN StringElList: string_el<* LIT_SQCLOSE] :SubList
def string_top_el
- [DQ LitStringElList: lit_string_el* dq_lit_term] :Dq
-| [SQ SqConsDataList: sq_cons_data* sq_lit_term] :Sq
+ [DQ LitStringElList: lit_string_el<* dq_lit_term] :Dq
+| [SQ SqConsDataList: sq_cons_data<* sq_lit_term] :Sq
| [TILDE opt_tilde_data TILDE_NL] :Tilde
-| [SQOPEN StringElList: string_el* SQCLOSE] :SubList
+| [SQOPEN StringElList: string_el<* SQCLOSE] :SubList
def string_list
[string_top_el] :Base
diff --git a/colm/compiler.cc b/colm/compiler.cc
index 72cf99fa..f6276e9d 100644
--- a/colm/compiler.cc
+++ b/colm/compiler.cc
@@ -760,10 +760,11 @@ FsmGraph *Compiler::makeScanner()
}
LangEl *Compiler::makeRepeatProd( const InputLoc &loc, Namespace *nspace,
- const String &repeatName, UniqueType *ut )
+ const String &repeatName, UniqueType *ut, bool left )
{
LangEl *prodName = addLangEl( this, nspace, repeatName, LangEl::NonTerm );
prodName->isRepeat = true;
+ prodName->leftRecursive = left;
ProdElList *prodElList1 = new ProdElList;
@@ -777,8 +778,14 @@ LangEl *Compiler::makeRepeatProd( const InputLoc &loc, Namespace *nspace,
ProdEl *factor2 = new ProdEl( ProdEl::ReferenceType,
InputLoc(), 0, false, typeRef2, 0 );
- prodElList1->append( factor1 );
- prodElList1->append( factor2 );
+ if ( left ) {
+ prodElList1->append( factor2 );
+ prodElList1->append( factor1 );
+ }
+ else {
+ prodElList1->append( factor1 );
+ prodElList1->append( factor2 );
+ }
Production *newDef1 = Production::cons( InputLoc(),
prodName, prodElList1, String(), false, 0,
@@ -815,8 +822,8 @@ LangEl *Compiler::makeListProd( const InputLoc &loc, Namespace *nspace,
ProdEl *factor2 = new ProdEl( ProdEl::ReferenceType, loc, 0, false, typeRef2, 0 );
ProdElList *prodElList1 = new ProdElList;
- prodElList1->append( factor1 );
prodElList1->append( factor2 );
+ prodElList1->append( factor1 );
Production *newDef1 = Production::cons( loc,
prodName, prodElList1, String(), false, 0,
diff --git a/colm/compiler.h b/colm/compiler.h
index 1b03504f..bf465dc6 100644
--- a/colm/compiler.h
+++ b/colm/compiler.h
@@ -281,6 +281,9 @@ struct LangEl : public DListEl<LangEl>
bool parseStop;
bool isEOF;
+ /* For a list or a repeat. Defaults to right recursive. */
+ bool leftRecursive;
+
LangEl *repeatOf;
/* Productions from the language element if it is a non-terminal. */
@@ -739,7 +742,7 @@ struct Compiler
void printFirstSets();
LangEl *makeRepeatProd( const InputLoc &loc, Namespace *nspace,
- const String &repeatName, UniqueType *ut );
+ const String &repeatName, UniqueType *ut, bool left );
LangEl *makeListProd( const InputLoc &loc, Namespace *nspace,
const String &listName, UniqueType *ut );
LangEl *makeOptProd( const InputLoc &loc, Namespace *nspace,
diff --git a/colm/consinit.cc b/colm/consinit.cc
index a2af94fd..4bd6e1c6 100644
--- a/colm/consinit.cc
+++ b/colm/consinit.cc
@@ -347,7 +347,7 @@ ProdEl *ConsInit::prodRefNameRepeat( const String &name )
{
ProdEl *prodEl = prodElName( internal, name,
NamespaceQual::cons( curNspace() ), 0,
- RepeatRepeat, false );
+ RepeatLeft, false );
return prodEl;
}
@@ -357,7 +357,7 @@ ProdEl *ConsInit::prodRefNameRepeat( const String &capture, const String &name )
ObjectField::RhsNameType, 0, capture );
ProdEl *prodEl = prodElName( internal, name,
NamespaceQual::cons( curNspace() ), captureField,
- RepeatRepeat, false );
+ RepeatLeft, false );
return prodEl;
}
@@ -645,9 +645,12 @@ void ConsInit::optRepeat()
ProdEl *prodEl1 = prodRefName( "Star", "STAR" );
Production *prod1 = production( prodEl1 );
- Production *prod2 = production();
+ ProdEl *prodEl2 = prodRefName( "LeftStar", "LEFT_STAR" );
+ Production *prod2 = production( prodEl2 );
+
+ Production *prod3 = production();
- definition( "opt_prod_repeat", prod1, prod2 );
+ definition( "opt_prod_repeat", prod1, prod2, prod3 );
}
void ConsInit::prodEl()
@@ -848,6 +851,7 @@ void ConsInit::go( long activeRealm )
keyword( "STAR", "'*'");
keyword( "PLUS", "'+'");
+ keyword( "LEFT_STAR", "'<*'");
keyword( "'['" );
keyword( "']'" );
keyword( "'|'" );
diff --git a/colm/exports.cc b/colm/exports.cc
index 49228eff..2259c3c6 100644
--- a/colm/exports.cc
+++ b/colm/exports.cc
@@ -60,6 +60,7 @@ void Compiler::generateExports()
"\n"
"#include <colm/colm.h>\n"
"#include <string>\n"
+ "#include <vector>\n"
"\n";
out <<
@@ -112,11 +113,22 @@ void Compiler::generateExports()
if ( mainReturnUT != 0 && mainReturnUT->langEl == lel ) {
out << " " << lel->fullName <<
- "( colm_program *prg ) : __prg(prg), __tree(returnVal(prg)) {}\n";
+ "( colm_program *prg ) : __prg(prg), __tree(returnVal(prg)) {\n";
+ out << " }\n";
}
out << " " << lel->fullName <<
- "( colm_program *prg, colm_tree *tree ) : __prg(prg), __tree(tree) {}\n";
+ "( colm_program *prg, colm_tree *tree ) : __prg(prg), __tree(tree) {\n";
+
+ if ( lel->isRepeat && lel->leftRecursive ) {
+ out <<
+ " while ( ! colm_repeat_end( __tree ) ) {\n"
+ " stack.push_back( colm_get_left_repeat_val( __tree ) );\n"
+ " __tree = colm_get_left_repeat_next( __tree );\n"
+ " }\n";
+ }
+
+ out << "}\n";
if ( lel->objectDef != 0 ) {
FieldList &fieldList = lel->objectDef->fieldList;
@@ -148,11 +160,19 @@ void Compiler::generateExports()
"{ return (enum prod_name)__tree->prod_num; }\n";
}
-
if ( lel->isRepeat ) {
- out << " " << "int end() { return colm_repeat_end( __tree ); }\n";
- out << " " << lel->refName << " next();\n";
- out << " " << lel->repeatOf->refName << " value();\n";
+ if ( lel->leftRecursive ) {
+ out << " " << "std::vector<colm_tree*> stack;\n";
+ out << " " << "int end() { return stack.size() == 0; }\n";
+ out << " " << lel->refName << " next() { stack.pop_back(); return *this; }\n";
+ out << " " << lel->repeatOf->refName << " value() { return " <<
+ lel->repeatOf->refName << "( __prg, stack[stack.size()-1] ); }\n";
+ }
+ else {
+ out << " " << "int end() { return colm_repeat_end( __tree ); }\n";
+ out << " " << lel->refName << " next();\n";
+ out << " " << lel->repeatOf->refName << " value();\n";
+ }
}
if ( lel->isList ) {
@@ -161,7 +181,6 @@ void Compiler::generateExports()
out << " " << lel->repeatOf->refName << " value();\n";
}
-
out << "};";
closeNameSpace( out, lel->nspace );
out << "\n";
@@ -242,8 +261,8 @@ void Compiler::generateExportsImpl()
}
}
- if ( lel->isRepeat ) {
- out << lel->refName << " " << lel->declName << "::" << " next"
+ if ( lel->isRepeat && !lel->leftRecursive ) {
+ out << lel->refName << " " << lel->declName << "::" << "next"
"() { return " << lel->refName <<
"( __prg, colm_get_repeat_next( __tree ) ); }\n";
@@ -253,7 +272,7 @@ void Compiler::generateExportsImpl()
}
if ( lel->isList ) {
- out << lel->refName << " " << lel->declName << "::" << " next"
+ out << lel->refName << " " << lel->declName << "::" << "next"
"() { return " << lel->refName <<
"( __prg, colm_get_repeat_next( __tree ) ); }\n";
diff --git a/colm/loadfinal.cc b/colm/loadfinal.cc
index f05a99e1..54f2c6ab 100644
--- a/colm/loadfinal.cc
+++ b/colm/loadfinal.cc
@@ -849,6 +849,8 @@ struct LoadColm
repeatType = RepeatOpt;
break;
case opt_repeat::LeftStar:
+ repeatType = RepeatLeft;
+ break;
case opt_repeat::LeftPlus:
error( OptRepeat.loc() ) << "<* and <+ are implemented as a "
"colm transformation, they are not accepted at this stage" << endp;
diff --git a/colm/loadinit.cc b/colm/loadinit.cc
index fc75906c..ea5e7f00 100644
--- a/colm/loadinit.cc
+++ b/colm/loadinit.cc
@@ -62,6 +62,8 @@ void LoadInit::walkProdElList( String defName, ProdElList *list, prod_el_list &p
RepeatType repeatType = RepeatNone;
if ( El.OptRepeat().Star() != 0 )
repeatType = RepeatRepeat;
+ if ( El.OptRepeat().LeftStar() != 0 )
+ repeatType = RepeatLeft;
ProdEl *prodEl = prodElName( internal, typeName,
NamespaceQual::cons( curNspace() ),
diff --git a/colm/parsetree.h b/colm/parsetree.h
index eea94454..6981880d 100644
--- a/colm/parsetree.h
+++ b/colm/parsetree.h
@@ -2110,7 +2110,8 @@ enum RepeatType {
RepeatNone = 1,
RepeatRepeat,
RepeatList,
- RepeatOpt
+ RepeatOpt,
+ RepeatLeft,
};
/*
diff --git a/colm/pdabuild.cc b/colm/pdabuild.cc
index f61b45f9..64f7323d 100644
--- a/colm/pdabuild.cc
+++ b/colm/pdabuild.cc
@@ -99,6 +99,7 @@ LangEl::LangEl( Namespace *nspace, const String &name, Type type )
isRepeat(false),
isList(false),
isOpt(false),
+ leftRecursive(false),
parseStop(false),
isEOF(false),
repeatOf(0),
diff --git a/colm/prog.lm b/colm/prog.lm
index e0ac8c22..635f0d92 100644
--- a/colm/prog.lm
+++ b/colm/prog.lm
@@ -37,16 +37,16 @@ void rewrite( P: ref<start> )
Additional = cons new_roots
[Additional Def]
}
- else if match PE
- [OptName: opt_prod_el_name Qual: region_qual Id: id "<*"]
- {
- parse LeftRepId: id "_lrep_[Id]"
- PE = cons prod_el [OptName Qual LeftRepId]
-
- cons Def: cfl_def "def [LeftRepId] \[[LeftRepId] [Id]\] | \[\]
-
- Additional = cons new_roots [Additional Def]
- }
+# else if match PE
+# [OptName: opt_prod_el_name Qual: region_qual Id: id "<*"]
+# {
+# parse LeftRepId: id "_lrep_[Id]"
+# PE = cons prod_el [OptName Qual LeftRepId]
+#
+# cons Def: cfl_def "def [LeftRepId] \[[LeftRepId] [Id]\] | \[\]
+#
+# Additional = cons new_roots [Additional Def]
+# }
else if match PE
[OptName: opt_prod_el_name Qual: region_qual Id: id "<+"]
{
@@ -61,7 +61,7 @@ void rewrite( P: ref<start> )
}
while ( Additional.root_item ) {
- P = cons start [Additional.root_item P.RootItemList]
+ P = cons start [P.RootItemList Additional.root_item]
Additional = Additional._new_roots
Modified = true
}
diff --git a/colm/resolve.cc b/colm/resolve.cc
index 3202f197..a8c3df2a 100644
--- a/colm/resolve.cc
+++ b/colm/resolve.cc
@@ -361,11 +361,18 @@ void TypeRef::resolveRepeat( Compiler *pd )
LangEl *declLangEl = 0;
switch ( repeatType ) {
+ case RepeatLeft: {
+ /* If the factor is a repeat, create the repeat element and link the
+ * factor to it. */
+ String repeatName( 128, "_repeat_%s", typeName.data );
+ declLangEl = pd->makeRepeatProd( loc, nspace, repeatName, uniqueType, true );
+ break;
+ }
case RepeatRepeat: {
/* If the factor is a repeat, create the repeat element and link the
* factor to it. */
String repeatName( 128, "_repeat_%s", typeName.data );
- declLangEl = pd->makeRepeatProd( loc, nspace, repeatName, uniqueType );
+ declLangEl = pd->makeRepeatProd( loc, nspace, repeatName, uniqueType, false );
break;
}
case RepeatList: {
diff --git a/colm/tree.c b/colm/tree.c
index 4bd8db40..9e59c464 100644
--- a/colm/tree.c
+++ b/colm/tree.c
@@ -118,6 +118,30 @@ tree_t *colm_get_repeat_val( tree_t *tree )
return kid->tree;
}
+tree_t *colm_get_left_repeat_next( tree_t *tree )
+{
+ kid_t *kid = tree->child;
+
+ if ( tree->flags & AF_LEFT_IGNORE )
+ kid = kid->next;
+ if ( tree->flags & AF_RIGHT_IGNORE )
+ kid = kid->next;
+
+ return kid->tree;
+}
+
+tree_t *colm_get_left_repeat_val( tree_t *tree )
+{
+ kid_t *kid = tree->child;
+
+ if ( tree->flags & AF_LEFT_IGNORE )
+ kid = kid->next;
+ if ( tree->flags & AF_RIGHT_IGNORE )
+ kid = kid->next;
+
+ return kid->next->tree;
+}
+
int colm_repeat_end( tree_t *tree )
{
kid_t *kid = tree->child;