diff options
author | Adrian Thurston <thurston@colm.net> | 2019-12-14 16:23:58 +0200 |
---|---|---|
committer | Adrian Thurston <thurston@colm.net> | 2019-12-14 16:26:14 +0200 |
commit | 732f9db9e6a2d7919e316341de06501d38aaabcc (patch) | |
tree | 72e9cc35aebe85eaf55ec80a4dc6dfd29ae318f7 /colm | |
parent | e8152c296aa6fa9cee01104a95837756f4bf90fd (diff) | |
download | colm-732f9db9e6a2d7919e316341de06501d38aaabcc.tar.gz |
testing left-recursive lists <* and <+ and sublists in productions
Using a transformation pass in prog.lm to create definitions for left-recursive
productions and sub-productions. So far just a sketch. Not all production
element forms are transformed and there can only be one sub-production in a
whole program. refs #74 refs #83 refs #84
Diffstat (limited to 'colm')
-rw-r--r-- | colm/Makefile.am | 2 | ||||
-rw-r--r-- | colm/colm.lm | 7 | ||||
-rw-r--r-- | colm/ctinput.cc | 2 | ||||
-rw-r--r-- | colm/loadcolm.cc | 15 | ||||
-rw-r--r-- | colm/prog.lm | 66 |
5 files changed, 88 insertions, 4 deletions
diff --git a/colm/Makefile.am b/colm/Makefile.am index ad2a78b2..fe594521 100644 --- a/colm/Makefile.am +++ b/colm/Makefile.am @@ -154,7 +154,7 @@ bootstrap2_LDADD = libprog.a libcolm.la endif -tar/bootstrap3.tar: $(BUILD_PARSE_3_WITH) prog.lm +tar/bootstrap3.tar: $(BUILD_PARSE_3_WITH) prog.lm colm.lm mkdir -p gen $(BUILD_PARSE_3_WITH) -c -o tar/parse3.c -e tar/if3.h -x tar/if3.cc prog.lm tar -C tar -cf tar/bootstrap3.tar parse3.c if3.h if3.cc diff --git a/colm/colm.lm b/colm/colm.lm index 1c475adc..efbd7a65 100644 --- a/colm/colm.lm +++ b/colm/colm.lm @@ -472,9 +472,14 @@ def opt_id def ignore_def [IGNORE opt_id LEX_FSLASH opt_lex_expr LEX_FSLASH] +def prod_sublist + [prod_sublist BAR prod_el_list] +| [prod_el_list] + def prod_el [opt_prod_el_name region_qual id opt_repeat] :Id | [opt_prod_el_name region_qual backtick_lit opt_repeat] :Lit +| [opt_prod_el_name POPEN prod_sublist PCLOSE opt_repeat ] :SubList def opt_prod_el_name [id COLON] :Name @@ -666,6 +671,8 @@ def opt_repeat [STAR] :Star | [PLUS] :Plus | [QUESTION] :Question +| [LT STAR] :LeftStar +| [LT PLUS] :LeftPlus | [] def opt_capture diff --git a/colm/ctinput.cc b/colm/ctinput.cc index 2adf2a94..bca2080a 100644 --- a/colm/ctinput.cc +++ b/colm/ctinput.cc @@ -459,7 +459,7 @@ int repl_undo_consume_data( struct colm_program *prg, struct input_impl_ct *ss, /* Okay to go up to the front of the buffer. */ if ( length > avail ) { - ss->cons_item= ss->cons_item->prev; + ss->cons_item = ss->cons_item->prev; ss->offset = ss->cons_item->data.length(); length -= avail; } diff --git a/colm/loadcolm.cc b/colm/loadcolm.cc index 694a88fd..ac64f668 100644 --- a/colm/loadcolm.cc +++ b/colm/loadcolm.cc @@ -844,6 +844,11 @@ struct LoadColm case opt_repeat::Question: repeatType = RepeatOpt; break; + case opt_repeat::LeftStar: + case opt_repeat::LeftPlus: + error( OptRepeat.loc() ) << "<* and <+ are implemented as a " + "colm transformation, they are not accepted at this stage" << endp; + break; } return repeatType; } @@ -972,10 +977,10 @@ struct LoadColm } RepeatType repeatType = walkOptRepeat( El.opt_repeat() ); - NamespaceQual *nspaceQual = walkRegionQual( El.region_qual() ); - 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 ); @@ -983,11 +988,17 @@ struct LoadColm 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; }} } diff --git a/colm/prog.lm b/colm/prog.lm index 43525993..e0ac8c22 100644 --- a/colm/prog.lm +++ b/colm/prog.lm @@ -7,5 +7,71 @@ A: str = argv->pop() F: stream = open( A, 'r' ) parse P: start [ F ] +def new_roots + [new_roots root_item] +| [] + +prod_list cons_prod( SLA: prod_sublist ) +{ + if match SLA [Left: prod_sublist BAR prod_el_list] + return cons prod_list[ cons_prod(Left) ' | [ ' SLA.prod_el_list ' ] ' ] + else + return cons prod_list[ '[ ' SLA.prod_el_list ' ]' ] +} + +void rewrite( P: ref<start> ) +{ + Modified: bool = false + cons Additional: new_roots [] + + for PE: prod_el in P { + if match PE + [OptName: opt_prod_el_name POPEN PS: prod_sublist PCLOSE OptRep: opt_repeat] + { + PE = cons prod_el + [OptName "_sublist_" OptRep] + + cons Def: cfl_def + "def _sublist_ [cons_prod(PS)]" + + 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]\] | \[[Id]\] + + Additional = cons new_roots [Additional Def] + } + } + + while ( Additional.root_item ) { + P = cons start [Additional.root_item P.RootItemList] + Additional = Additional._new_roots + Modified = true + } + return Modified +} + +if P { + while ( rewrite( P ) ) {} + #rewrite( P ) +} + ColmTree = P ColmError = error |