Skip to content

Commit

Permalink
nitcc: add Separator and Tail keyword
Browse files Browse the repository at this point in the history
Signed-off-by: Jean Privat <[email protected]>
  • Loading branch information
privat committed Jun 23, 2024
1 parent ca2c650 commit fd60093
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
9 changes: 9 additions & 0 deletions contrib/nitcc/src/nitcc.sablecc
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
98 changes: 98 additions & 0 deletions contrib/nitcc/src/nitcc_semantic.nit
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit fd60093

Please sign in to comment.