Skip to content

Commit

Permalink
NitCC LALR and LR(1) #2843
Browse files Browse the repository at this point in the history
I'ts happening!  nitcc can do LALR(1) (by default) and LR(1).

We also split the grammar.nit module into two by extracting a lrautomaton.nit module.
  • Loading branch information
privat authored Jul 22, 2024
2 parents 0dcfe3a + a3dd053 commit 1b0e342
Show file tree
Hide file tree
Showing 81 changed files with 1,899 additions and 1,007 deletions.
980 changes: 55 additions & 925 deletions contrib/nitcc/src/grammar.nit

Large diffs are not rendered by default.

1,010 changes: 1,010 additions & 0 deletions contrib/nitcc/src/lrautomaton.nit

Large diffs are not rendered by default.

12 changes: 4 additions & 8 deletions contrib/nitcc/src/nitcc.nit
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
module nitcc

import nitcc_semantic
import lrautomaton

# Load the grammar file

Expand Down Expand Up @@ -69,7 +70,9 @@ end

# Generate the LR automaton

var lr = gram.lr0
gram.prepare_for_automaton
var lr = new LALR1Automaton(gram)
lr.build

var conflitcs = new ArraySet[Production]
for s in lr.states do
Expand All @@ -80,13 +83,6 @@ if not conflitcs.is_empty then
print "Error: there is conflicts"
end

if false then loop
if conflitcs.is_empty then break
print "Inline {conflitcs.join(" ")}"
gram.inline(conflitcs)
lr=gram.lr0
end

# Output concrete grammar and LR automaton

var nbalts = 0
Expand Down
6 changes: 4 additions & 2 deletions contrib/nitcc/src/nitcc_parser_gen.nit
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#
module nitcc_parser_gen

import grammar
import lrautomaton

var g = new Gram
var p_gr = new Production("grammar")
Expand Down Expand Up @@ -195,7 +195,9 @@ p_pri.new_alt0("priority_left").phony = true
p_pri.new_alt0("priority_right").phony = true
p_pri.new_alt0("priority_unary").phony = true

var a = g.lr0
g.prepare_for_automaton
var a = new LALR1Automaton(g)
a.build

print "LR automaton: {a.states.length} states (see nitcc0.lr.dot)"
a.to_dot("nitcc0.lr.dot")
Expand Down
1 change: 1 addition & 0 deletions contrib/nitcc/tests/amb_repeat.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c x
6 changes: 6 additions & 0 deletions contrib/nitcc/tests/amb_repeat.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Grammar amb;
Parser
Ignored #10, #32;
s = a | a 'x' ;
a = b | b 'x' ;
b = 'c' ;
1 change: 1 addition & 0 deletions contrib/nitcc/tests/amb_repeat0.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/amb_repeat0.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Grammar amb;
Parser
Ignored #10, #32;
s = 'hello' | 'hello' ;
Empty file.
6 changes: 6 additions & 0 deletions contrib/nitcc/tests/amb_repeat2.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Grammar amb;
Parser
Ignored #10, #32;
s = a | Empty ;
a = b | Empty ;
b = 'c' ;
13 changes: 13 additions & 0 deletions contrib/nitcc/tests/calc1.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Grammar calc;
Lexer
n = ('0'..'9')+ ;
Parser
Ignored #10, #32;
e
= e '+' a
| e '-' a
;
a =
| '(' e ')'
| n
;
1 change: 1 addition & 0 deletions contrib/nitcc/tests/dangling_else.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
i a i a e a
9 changes: 9 additions & 0 deletions contrib/nitcc/tests/dangling_else.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Grammar dangling;
Parser
Ignored #10, #32;
ss = s*;
s
= 'i' s 'e' s
| 'i' s
| 'a'
;
1 change: 1 addition & 0 deletions contrib/nitcc/tests/dangling_else2.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
i a i a e a
14 changes: 14 additions & 0 deletions contrib/nitcc/tests/dangling_else2.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Grammar dangling;
Parser
Ignored #10, #32;
ss = s*;

s
= 'a'
| 'i' se 'e' s
| 'i' s
;
se
= 'a'
| 'i' se 'e' se
;
5 changes: 5 additions & 0 deletions contrib/nitcc/tests/dangling_end.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
a id
a id end
a a id end end
a a id end
a a id
9 changes: 9 additions & 0 deletions contrib/nitcc/tests/dangling_end.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Grammar dangling;
Parser
Ignored #10, #32;
es = e*;
e
= 'a' e 'end'
| 'a' e
| 'id'
;
1 change: 1 addition & 0 deletions contrib/nitcc/tests/dragon_4-55.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ccdd
5 changes: 5 additions & 0 deletions contrib/nitcc/tests/dragon_4-55.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Grammar dragon;
Parser
Ignored #10, #32;
s = c c ;
c = 'c' c | 'd' ;
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/oneliner.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
if id then id
if id then id end
if if id then id then id end
if id then if id then id end
34 changes: 34 additions & 0 deletions contrib/nitcc/tests/oneliner.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Grammar oneliner;
Lexer
eol = #10 | #13 ;

Parser
Ignored #32;

prog
= stmts
;
stmt
= if_block stmt_or_end
| if_block stmt_else stmt_or_end
| 'id'
;
if_block
= 'if' n? stmt no 'then'
;
stmt_or_end
= stmt 'end'?
| n stmts no 'end'
| no 'end'
;
stmt_else
= stmt 'else'
| n stmts no 'else'
| 'else'
;
stmts
= stmts n stmt
| stmt
;
no = n?;
n = eol+;
42 changes: 42 additions & 0 deletions contrib/nitcc/tests/oneliner2.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Grammar oneliner;
Lexer
eol = #10 | #13 ;

Parser
Ignored #32;

prog
= stmts
;
stmt
= if_block stmt_or_end
| if_block stmt_else stmt_or_end
| 'id'
;
stmt_with_else
= if_block stmt_else stmt_or_end
| 'id'
;
if_block
= 'if' n? stmt no 'then'
;
stmt_or_end
= stmt 'end'?
| n stmts no 'end'
| no 'end'
;
stmt_end
= stmt 'else'
| n stmts no 'else'
| 'else'
;
stmts_with_else
= stmts_with_else n stmt_with_else
| stmt_with_else
;
stmts
= stmts n stmt
| stmt
;
no = n?;
n = eol+;
1 change: 1 addition & 0 deletions contrib/nitcc/tests/regex0.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aa|aa*
5 changes: 5 additions & 0 deletions contrib/nitcc/tests/regex0.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Grammar regex;
Parser
Ignored #10, #32;
e = a | e '|' e | e e | e '*' ;
a = 'a' ;
1 change: 1 addition & 0 deletions contrib/nitcc/tests/regex1.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aa|aa*
13 changes: 13 additions & 0 deletions contrib/nitcc/tests/regex1.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Grammar regex;
Parser
Ignored #10, #32;
e
= a
Unary
e '*'
Left
e e
Left
e '|' e
;
a = 'a' ;
1 change: 1 addition & 0 deletions contrib/nitcc/tests/regex2.input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aa|aa*
7 changes: 7 additions & 0 deletions contrib/nitcc/tests/regex2.sablecc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Grammar regex;
Parser
Ignored #10, #32;
e = e '|' e2 | e2;
e2 = e2 e3 | e3 ;
e3 = e4 '*' | e4 ;
e4 = 'a' ;
6 changes: 6 additions & 0 deletions contrib/nitcc/tests/sav/amb.res
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
REDUCE/REDUCE Conflict on state 1 e for token Eof:
REDUCE on item: e→ e·, Eof
REDUCE on item: e→ e·, Eof
SHIFT/REDUCE Conflict on state 1 e for token Eof:
SHIFT on item: _start→ e·Eof
REDUCE on item: e→ e·, Eof
Error: there is conflicts
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/amb2.res
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
REDUCE/REDUCE Conflict on state 7 '-' e for token '+':
REDUCE on item: a→ e·, Eof/'+'
REDUCE on item: b→ e·, '+'
Error: there is conflicts
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/amb3.res
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
SHIFT/REDUCE Conflict on state 3 'a' for token 'b':
SHIFT on item: x→·'b', Eof
REDUCE on item: x→ 'a'·, 'b'
Error: there is conflicts
7 changes: 7 additions & 0 deletions contrib/nitcc/tests/sav/amb_repeat.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Start
s_0
a_1
b
'c'@(1:1-1:2)
'x'@(1:3-1:4)
Eof@(2:1-2:1)=''
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/sav/amb_repeat.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SHIFT/REDUCE Conflict on state 3 b for token 'x':
SHIFT on item: a→ b·'x', Eof/'x'
REDUCE on item: a→ b·, Eof/'x'
Error: there is conflicts
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/sav/amb_repeat0.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Start
s_0
'hello'@(1:1-1:6)
Eof@(2:1-2:1)=''
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/sav/amb_repeat0.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REDUCE/REDUCE Conflict on state 2 'hello' for token Eof:
REDUCE on item: s→ 'hello'·, Eof
REDUCE on item: s→ 'hello'·, Eof
Error: there is conflicts
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/sav/amb_repeat2.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Start
s_0
a_1
Eof@(1:1-1:1)=''
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/sav/amb_repeat2.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REDUCE/REDUCE Conflict on state 0 for token Eof:
REDUCE on item: a→·, Eof
REDUCE on item: s→·, Eof
Error: there is conflicts
12 changes: 12 additions & 0 deletions contrib/nitcc/tests/sav/calc0.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Automatic Dangling SHIFT/REDUCE on state 8 e '+' e for token '+':
reduce: e→ e '+' e·, Eof/'+'/'*'/')'
shift: e→ e·'+' e
Automatic Dangling SHIFT/REDUCE on state 8 e '+' e for token '*':
reduce: e→ e '+' e·, Eof/'+'/'*'/')'
shift: e→ e·'*' e
Automatic Dangling SHIFT/REDUCE on state 9 e '*' e for token '+':
reduce: e→ e '*' e·, '+'/'*'/Eof/')'
shift: e→ e·'+' e
Automatic Dangling SHIFT/REDUCE on state 9 e '*' e for token '*':
reduce: e→ e '*' e·, '+'/'*'/Eof/')'
shift: e→ e·'*' e
1 change: 1 addition & 0 deletions contrib/nitcc/tests/sav/calc1.res
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Runtime error: Aborted (./lrautomaton.nit:507)
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/conflict-bracket.res
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
SHIFT/REDUCE Conflict on state 8 '[' e '[' for token '[':
SHIFT on item: e→·'[' e '[', ']'/'['
REDUCE on item: e→ '[' e '['·, Eof/'['/']'
Error: there is conflicts
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/conflict-dangling.1alt1.alt1.res
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
SHIFT/REDUCE Conflict on state 7 '1' e for token '2':
SHIFT on item: x→·'2', Eof/'2'
REDUCE on item: e→ '1' e·, Eof/'2'
Error: there is conflicts
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/conflict-dangling.1alt1.alt2.res
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
SHIFT/REDUCE Conflict on state 7 '1' e for token '2':
SHIFT on item: x→·'2', Eof/'2'
REDUCE on item: y→·, Eof/'2'
Error: there is conflicts
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/conflict-dangling.1alt1.res
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
SHIFT/REDUCE Conflict on state 7 '1' e for token '2':
SHIFT on item: e→ '1' e·'2', Eof/'2'
REDUCE on item: e→ '1' e·, Eof/'2'
Error: there is conflicts
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/sav/conflict-dangling.alt1.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Automatic Dangling SHIFT/REDUCE on state 6 '1' e for token '2':
reduce: e→ '1' e·, Eof/'2'
shift: x→·'2'
core shift: e→ '1' e·x, Eof/'2'
4 changes: 4 additions & 0 deletions contrib/nitcc/tests/sav/conflict-dangling.alt2.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Automatic Dangling SHIFT/REDUCE on state 6 '1' e for token '2':
reduce: y→·, Eof/'2'
shift: x→·'2'
core shift: y→·x, Eof/'2'
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/conflict-dangling.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Automatic Dangling SHIFT/REDUCE on state 6 '1' e for token '2':
reduce: e→ '1' e·, Eof/'2'
shift: e→ '1' e·'2'
15 changes: 15 additions & 0 deletions contrib/nitcc/tests/sav/dangling_else.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Start
ss
Nodes[Ns]
s_1
'i'@(1:1-1:2)
s_2
'a'@(1:3-1:4)
s_0
'i'@(1:5-1:6)
s_2
'a'@(1:7-1:8)
'e'@(1:9-1:10)
s_2
'a'@(1:11-1:12)
Eof@(2:1-2:1)=''
3 changes: 3 additions & 0 deletions contrib/nitcc/tests/sav/dangling_else.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Automatic Dangling SHIFT/REDUCE on state 8 'i' s for token 'e':
reduce: s→ 'i' s·, Eof/'i'/'a'/'e'
shift: s→ 'i' s·'e' s
15 changes: 15 additions & 0 deletions contrib/nitcc/tests/sav/dangling_else2.input.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Start
ss
Nodes[Ns]
s_2
'i'@(1:1-1:2)
s_0
'a'@(1:3-1:4)
s_1
'i'@(1:5-1:6)
se_0
'a'@(1:7-1:8)
'e'@(1:9-1:10)
s_0
'a'@(1:11-1:12)
Eof@(2:1-2:1)=''
Loading

0 comments on commit 1b0e342

Please sign in to comment.