Skip to content

Commit

Permalink
Merge pull request #2839 from privat/nitcc-groups
Browse files Browse the repository at this point in the history
nitcc add groups and small improvments
  • Loading branch information
privat authored Jun 28, 2024
2 parents 5069090 + a82ff72 commit 97b707e
Show file tree
Hide file tree
Showing 19 changed files with 300 additions and 45 deletions.
95 changes: 56 additions & 39 deletions contrib/nitcc/src/grammar.nit
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,23 @@ class CodeNew
redef fun to_s do return "New {alt.name}/{alt.elems.length}"
end

# Allocate a new empty AST node array for an alternative
class CodeNewNodes
super Code

# The associated alternative
var alt: Alternative

redef fun to_s do return "NewArray {alt.name}"
end

# Add an element to a Nodes array
class CodeAdd
super Code

redef fun to_s do return "Add"
end

# Get null
class CodeNull
super Code
Expand Down Expand Up @@ -835,49 +852,49 @@ private class Generator
i -= 1
end

if alt.name.has_suffix("+_more") then
add "\t\tvar prod = n0"
add "\t\tn0.children.add(n1)"
else if alt.name.has_suffix("+_one") then
add "\t\tvar prod = new {alt.prod.acname}"
add "\t\tprod.children.add(n0)"
else
alt.make_codes
var cpt = 0
i = 0
var st = new Array[String]
for c in alt.codes.as(not null) do
if c isa CodePop then
st.add "n{i}"
i += 1
else if c isa CodeNull then
st.add "null"
else if c isa CodeNew then
var calt = c.alt
cpt += 1
var from = st.length - calt.elems.length
var args = new List[String]
for j in [from..st.length[ do
args.unshift(st.pop)
end
alt.make_codes
var cpt = 0
i = 0
var st = new Array[String]
for c in alt.codes.as(not null) do
if c isa CodePop then
st.add "n{i}"
i += 1
else if c isa CodeNull then
st.add "null"
else if c isa CodeNew then
var calt = c.alt
cpt += 1
var from = st.length - calt.elems.length
var args = new List[String]
for j in [from..st.length[ do
args.unshift(st.pop)
end

if args.is_empty then
add "\t\tvar p{cpt} = new {calt.cname}"
else
add "\t\tvar p{cpt} = new {calt.cname}({args.join(", ")})"
end
#var x = 0
#for j in [from..st.length[ do
#if st[j] == "null" then continue
#add "\t\tp{cpt}.n_{calt.elemname(x)} = {st[j]}"
#x += 1
#end
st.add("p{cpt}")
if args.is_empty then
add "\t\tvar p{cpt} = new {calt.cname}"
else
add "\t\tvar p{cpt} = new {calt.cname}({args.join(", ")})"
end
#var x = 0
#for j in [from..st.length[ do
#if st[j] == "null" then continue
#add "\t\tp{cpt}.n_{calt.elemname(x)} = {st[j]}"
#x += 1
#end
st.add("p{cpt}")
else if c isa CodeNewNodes then
cpt += 1
add "\t\tvar p{cpt} = new {c.alt.prod.acname}"
st.add("p{cpt}")
else if c isa CodeAdd then
var a1 = st.pop
var a0 = st.last
add "\t\t{a0}.children.add({a1})"
end
assert st.length == 1
add "\t\tvar prod = {st.first}"
end
assert st.length == 1
add "\t\tvar prod = {st.first}"

add "\t\tparser.node_stack.push prod"
if alt.prod.accept then
Expand Down
1 change: 1 addition & 0 deletions contrib/nitcc/src/nitcc.sablecc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ elem =
{star:} elem '*' |
{ques:} elem '?' |
{plus:} elem '+' |
{par:} '(' elem+ ')' |
{empty:} 'Empty' ;

priority =
Expand Down
55 changes: 53 additions & 2 deletions contrib/nitcc/src/nitcc_semantic.nit
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,28 @@ private class CheckNameVisitor
var plusizes = new HashMap[Element, Production]

# Create a + version of an element
#
# ```
# foo = x bar+ y | z ;
# ```
#
# becomes
#
# ```
# foo = x abs0 y | z ;
# abs0 = {one:} bar | {more:} abs0 bar ;
# ```
fun plusize(e: Element): Production
do
if plusizes.has_key(e) then return plusizes[e]
var name = "{e}+"
var prod = new Production(name)
prod.acname = "Nodes[{e.acname}]"
v1.gram.prods.add(prod)
prod.new_alt("{name}_one", e)
prod.new_alt("{name}_more", prod, e)
var alt1 = prod.new_alt("{name}_one", e)
alt1.codes = [new CodeNewNodes(alt1), new CodePop, new CodeAdd: Code]
var alt2 = prod.new_alt("{name}_more", prod, e)
alt2.codes = [new CodePop, new CodePop, new CodeAdd: Code]
plusizes[e] = prod
return prod
end
Expand All @@ -140,6 +153,17 @@ private class CheckNameVisitor
var quesizes = new HashMap[Element, Production]

# Create a ? version of an element
#
# ```
# foo = x bar? y | z ;
# ```
#
# becomes
#
# ```
# foo = x abs0 y | z ;
# abs0 = {one:} bar | {none} Empty ;
# ```
fun quesize(e: Element): Production
do
if quesizes.has_key(e) then return quesizes[e]
Expand All @@ -155,6 +179,22 @@ private class CheckNameVisitor
return prod
end

# Pool for anoymous grouped production (reuse them!)
var groupizes = new HashMap[Array[Element], Production]

# Create an anonymous production that groups some elements.
# Note: an anonymous production is always returned, even if `es` is empty or single.
fun groupize(es: Array[Element]): Production
do
if groupizes.has_key(es) then return groupizes[es]
var name = "_group{groupizes.length}"
var prod = new Production(name)
v1.gram.prods.add(prod)
var a1 = prod.new_alt2("{name}_single", es)
groupizes[es] = prod
return prod
end

# The current nexpr, used to track dependency on named expressions (see `Nexpr::precs`)
var nexpr: nullable Nexpr = null

Expand Down Expand Up @@ -701,6 +741,17 @@ redef class Nelem_plus
end
end

redef class Nelem_par
redef fun accept_check_name_visitor(v) do
var old = v.elems
v.elems = new Array[Element]
super
var elem = v.groupize(v.elems)
v.elems = old
set_elem(v, null, elem)
end
end

redef class Ntree_part
redef fun accept_collect_prod(v) do
print "NOT YET IMPLEMENTED: `Tree` part; it is ignored"
Expand Down
9 changes: 9 additions & 0 deletions contrib/nitcc/tests/parser-groupize.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
sa
sab
sac
s
sad
sadad
t
tae
taeae
12 changes: 12 additions & 0 deletions contrib/nitcc/tests/parser-groupize.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Grammar gram;
Lexer
blank = #10 | #13 | #32;
Parser
Ignored blank;
s =
s 's' ('a' 'b') |
s 's' ('a') |
s 's' ('a' 'c')? |
s 's' ('a' 'd')+ |
s 't' ('a' 'e')* |
Empty;
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/parser-plusize.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
s ab
s abab
s abb
8 changes: 8 additions & 0 deletions contrib/nitcc/tests/parser-plusize.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Grammar gram;
Lexer
blank = #10 | #13 | #32;
Parser
Ignored blank;
s = s 's' t | Empty;
t = ab+ ;
ab = 'a' 'b' ;
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/parser-questize.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
sabc
sac
sabbc
7 changes: 7 additions & 0 deletions contrib/nitcc/tests/parser-questize.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Grammar gram;
Lexer
blank = #10 | #13 | #32;
Parser
Ignored blank;
s = s 's' t | Empty;
t = 'a' 'b'? 'c';
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/parser-starize.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
s
sab
sabab
saba
8 changes: 8 additions & 0 deletions contrib/nitcc/tests/parser-starize.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Grammar gram;
Lexer
blank = #10 | #13 | #32;
Parser
Ignored blank;
s = s 's' t | Empty;
t = ab* ;
ab = 'a' 'b';
Original file line number Diff line number Diff line change
@@ -1 +1 @@
11:15-11:16 Syntax Error: Unexpected '('; is acceptable instead: priority+, priority
11:20-11:29 Syntax Error: Unexpected unknown_keyword 'Separator'; is acceptable instead: elem, text
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20:8-20:9 Syntax Error: Unexpected '('; is acceptable instead: priority+, priority
20:14-20:23 Syntax Error: Unexpected unknown_keyword 'Separator'; is acceptable instead: elem, text
2 changes: 1 addition & 1 deletion contrib/nitcc/tests/sav/inf5000-06-grammaire2-polygone.res
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8:18-8:19 Syntax Error: Unexpected '('; is acceptable instead: priority+, priority
8:25-8:34 Syntax Error: Unexpected unknown_keyword 'Separator'; is acceptable instead: elem, text
51 changes: 51 additions & 0 deletions contrib/nitcc/tests/sav/parser-groupize.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Start
s_4
s_4
s_4
s_3
s_3
s_2
s_2
s_0
s_1
s_5
's'@(1:1-1:2)
_group1_single
'a'@(1:2-1:3)
's'@(2:1-2:2)
_group0_single
'a'@(2:2-2:3)
'b'@(2:3-2:4)
's'@(3:1-3:2)
_group2_single
'a'@(3:2-3:3)
'c'@(3:3-3:4)
's'@(4:1-4:2)
's'@(5:1-5:2)
Nodes[N_group3]
_group3_single
'a'@(5:2-5:3)
'd'@(5:3-5:4)
's'@(6:1-6:2)
Nodes[N_group3]
_group3_single
'a'@(6:2-6:3)
'd'@(6:3-6:4)
_group3_single
'a'@(6:4-6:5)
'd'@(6:5-6:6)
't'@(7:1-7:2)
't'@(8:1-8:2)
Nodes[N_group4]
_group4_single
'a'@(8:2-8:3)
'e'@(8:3-8:4)
't'@(9:1-9:2)
Nodes[N_group4]
_group4_single
'a'@(9:2-9:3)
'e'@(9:3-9:4)
_group4_single
'a'@(9:4-9:5)
'e'@(9:5-9:6)
Eof@(10:1-10:1)=''
28 changes: 28 additions & 0 deletions contrib/nitcc/tests/sav/parser-plusize.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
NParserError@(3:5-3:6)='b'
Nodes[Node]
s_0
s_0
s_0
s_1
's'@(1:1-1:2)
t
Nodes[Nab]
ab
'a'@(1:3-1:4)
'b'@(1:4-1:5)
's'@(2:1-2:2)
t
Nodes[Nab]
ab
'a'@(2:3-2:4)
'b'@(2:4-2:5)
ab
'a'@(2:5-2:6)
'b'@(2:6-2:7)
's'@(3:1-3:2)
t
Nodes[Nab]
ab
'a'@(3:3-3:4)
'b'@(3:4-3:5)
'b'@(3:5-3:6)
18 changes: 18 additions & 0 deletions contrib/nitcc/tests/sav/parser-questize.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
NParserError@(3:4-3:5)='b'
Nodes[Node]
s_0
s_0
s_1
's'@(1:1-1:2)
t
'a'@(1:2-1:3)
'b'@(1:3-1:4)
'c'@(1:4-1:5)
's'@(2:1-2:2)
t
'a'@(2:2-2:3)
'c'@(2:3-2:4)
's'@(3:1-3:2)
'a'@(3:2-3:3)
'b'@(3:3-3:4)
'b'@(3:4-3:5)
Loading

0 comments on commit 97b707e

Please sign in to comment.