From fd6009308c554cfaa5a7635676f2784299e04dc1 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Sun, 23 Jun 2024 16:00:10 -0400 Subject: [PATCH] nitcc: add Separator and Tail keyword Signed-off-by: Jean Privat --- contrib/nitcc/src/nitcc.sablecc | 9 +++ contrib/nitcc/src/nitcc_semantic.nit | 98 ++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/contrib/nitcc/src/nitcc.sablecc b/contrib/nitcc/src/nitcc.sablecc index bf50f2a53e..7e6dd19a2c 100644 --- a/contrib/nitcc/src/nitcc.sablecc +++ b/contrib/nitcc/src/nitcc.sablecc @@ -112,8 +112,17 @@ elem = {ques:} elem '?' | {plus:} elem '+' | {group:} '(' elem+ ')' | + {groupsep:} '(' elem+ separator [sep:]elem+ ')' mult | {empty:} 'Empty' ; +separator = + {sep:} 'Separator' | + {tail:} 'Tail' ; + +mult = + {star:} '*' | + {plus:} '+' ; + priority = {left:} 'Left' alts | {right:} 'Right' alts | diff --git a/contrib/nitcc/src/nitcc_semantic.nit b/contrib/nitcc/src/nitcc_semantic.nit index 0c31ee944a..a4fc538a1c 100644 --- a/contrib/nitcc/src/nitcc_semantic.nit +++ b/contrib/nitcc/src/nitcc_semantic.nit @@ -149,6 +149,81 @@ private class CheckNameVisitor return prod end + # Pool of elements that are modified with Separator + var separatizes = new HashMap[Array[Element], Production] + + # Create a separated version of an element `e1` where the last element is `e2`. + # This is used to implement `Separator` and `Tail` keywords. + # + # ``` + # foo = x (bar Separator baz)+ y | z ; + # ``` + # + # becomes + # + # ``` + # foo = x abs1 y | z ; + # abs0 = bar baz ; + # abs1 = (one:) bar | {more:} abs0+ bar ; + # ``` + fun separatize(e1, e2: Element): Production + do + var es = [e1, e2] + if separatizes.has_key(es) then return separatizes[es] + var name = "_sep{separatizes.length}" + var prod = new Production(name) + v1.gram.prods.add(prod) + var p = plusize(e1) + prod.spe = p + var alt1 = prod.new_alt("{name}_more", p, e2) + alt1.codes = [new CodePop, new CodePop, new CodeAdd: Code] + alt1.trans = true + var alt2 = prod.new_alt("{name}_one", e2) + alt2.codes = [new CodeNewNodes(alt1), new CodePop, new CodeAdd: Code] + alt2.trans = true + separatizes[es] = prod + return prod + end + + # Pool of elements that are modified with Tail + var tailizes = new HashMap[Array[Element], Production] + + # Create a separated version of an element `e1` where the last `e2` can be present. + # This is used to implement `Separator` and `Tail` keywords. + # + # ``` + # foo = x (bar Separator baz)+ y | z ; + # ``` + # + # becomes + # + # ``` + # foo = x abs1 y | z ; + # abs0 = bar baz ; + # abs1 = (one:) bar | {more:} abs0+ bar | {tail:} abs0+; + # ``` + fun tailize(e1, e2: Element): Production + do + var es = [e1, e2] + if tailizes.has_key(es) then return tailizes[es] + var name = "_tail{tailizes.length}" + var prod = new Production(name) + v1.gram.prods.add(prod) + var p = plusize(e1) + prod.spe = p + var alt1 = prod.new_alt("{name}_more", p, e2) + alt1.codes = [new CodePop, new CodePop, new CodeAdd: Code] + alt1.trans = true + var alt2 = prod.new_alt("{name}_one", e2) + alt2.codes = [new CodeNewNodes(alt1), new CodePop, new CodeAdd: Code] + alt2.trans = true + var alt3 = prod.new_alt("{name}_tail", p) + alt3.codes = [new CodePop] + alt3.trans = true + tailizes[es] = prod + return prod + end + # Pool of elements that are modified with ? (reuse them!) var quesizes = new HashMap[Element, Production] @@ -752,6 +827,29 @@ redef class Nelem_group end end +redef class Nelem_groupsep + redef fun accept_check_name_visitor(v) do + var old = v.elems + v.elems = new Array[Element] + n_elem.accept_check_name_visitor(v) + var prod1 = v.groupize(v.elems.clone) + n_sep.accept_check_name_visitor(v) + var prod2 = v.groupize(v.elems) + prod1.spe = prod2 + v.elems = old + var prod + if n_separator isa Nseparator_sep then + prod = v.separatize(prod2, prod1) + else + prod = v.tailize(prod2, prod1) + end + if n_mult isa Nmult_star then + prod = v.quesize(prod) + end + set_elem(v, null, prod) + end +end + redef class Ntree_part redef fun accept_collect_prod(v) do print "NOT YET IMPLEMENTED: `Tree` part; it is ignored"