Skip to content

Commit 8412c68

Browse files
committed
Extract functions
1 parent dfb3d7a commit 8412c68

File tree

5 files changed

+259
-64
lines changed

5 files changed

+259
-64
lines changed

lib/lrama/grammar/parser_state.rb

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,106 @@ def initialize(state_id:, state_list:)
88
@state_list = state_list
99
end
1010

11+
def enum_definition
12+
<<~ENUM
13+
enum #{enum_name}
14+
{
15+
#{enum_body}
16+
};
17+
typedef enum #{enum_name} #{enum_type};
18+
19+
static const char *const #{enum_name_table_name}[] = {
20+
#{int_to_name.join(", ")}
21+
};
22+
23+
YY_ATTRIBUTE_UNUSED
24+
static const char *
25+
#{enum_name}_name (#{enum_type} num)
26+
{
27+
return #{enum_name_table_name}[num];
28+
}
29+
30+
# define YY_STATE_#{state_name.upcase}_NAME #{enum_name}_name (*#{stack_prefix}_p)
31+
ENUM
32+
end
33+
34+
def states_functions
35+
# TODO: Stack check for push
36+
<<~FUNC
37+
# define YYPUSH_STATE_#{state_name.upcase}(value) \\
38+
do \\
39+
{ \\
40+
YYDPRINTF ((stderr, "Push #{state_name}\\n")); \\
41+
*++#{stack_prefix}_p = value; \\
42+
} \\
43+
while (0)
44+
45+
# define YYPOP_STATE_#{state_name.upcase}() \\
46+
do \\
47+
{ \\
48+
YYDPRINTF ((stderr, "Pop #{state_name}\\n")); \\
49+
if (#{stack_prefix}_p != #{stack_prefix}) \\
50+
{ \\
51+
#{stack_prefix}_p -= 1; \\
52+
} \\
53+
else \\
54+
{ \\
55+
YYDPRINTF ((stderr, "Try to pop empty #{state_name} stack\\n")); \\
56+
} \\
57+
} \\
58+
while (0)
59+
60+
# define YYSET_STATE_#{state_name.upcase}(value) \\
61+
do \\
62+
{ \\
63+
YYDPRINTF ((stderr, "Set #{state_name}\\n")); \\
64+
*#{stack_prefix}_p = value; \\
65+
} \\
66+
while (0)
67+
68+
# define YY_STATE_#{state_name.upcase} #{stack_prefix}_p
69+
FUNC
70+
end
71+
72+
def states_stacks
73+
<<~STACKS
74+
/* The parser state stack (#{stack_prefix}): array, bottom, top. */
75+
int #{stack_prefix}_a[YYINITDEPTH];
76+
int *#{stack_prefix} = #{stack_prefix}_a;
77+
int *#{stack_prefix}_p = #{stack_prefix};
78+
STACKS
79+
end
80+
81+
def state_name
82+
state_id.s_value
83+
end
84+
1185
def enum_name
86+
"yyparser_state_#{state_name}"
1287
end
1388

1489
def enum_type
90+
"#{enum_name}_t"
91+
end
92+
93+
def enum_body
94+
state_list.map do |state|
95+
state.s_value
96+
end.join(",\n ")
97+
end
98+
99+
def int_to_name
100+
state_list.map do |state|
101+
"\"#{state.s_value}\""
102+
end << "YY_NULLPTR"
103+
end
104+
105+
def enum_name_table_name
106+
"#{enum_name}_names"
107+
end
108+
109+
def stack_prefix
110+
"yyparser_state_#{state_name}"
15111
end
16112
end
17113
end

lib/lrama/output.rb

Lines changed: 6 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -359,73 +359,20 @@ def percent_code(name)
359359
end
360360

361361
def parser_states_enums
362-
@grammar.parser_states.map do |parser_state|
363-
enum_name = "yyparser_state_#{parser_state.state_id.s_value}"
364-
365-
enum_body = parser_state.state_list.map do |state|
366-
state.s_value
367-
end.join(",\n ")
368-
369-
int_to_name = parser_state.state_list.map do |state|
370-
"\"#{state.s_value}\""
371-
end << "YY_NULLPTR"
372-
373-
<<~ENUM
374-
enum #{enum_name}
375-
{
376-
#{enum_body}
377-
};
378-
typedef enum #{enum_name} #{enum_name}_t;
379-
380-
static const char *const #{enum_name}name[] = {
381-
#{int_to_name.join(", ")}
382-
};
383-
384-
YY_ATTRIBUTE_UNUSED
385-
static const char *
386-
#{enum_name}_name (#{enum_name}_t num)
387-
{
388-
return #{enum_name}name[num];
389-
}
390-
391-
# define YY_STATE_#{parser_state.state_id.s_value.upcase}_NAME #{enum_name}_name (*yyparser_state_#{parser_state.state_id.s_value}_p)
392-
ENUM
362+
@grammar.parser_states.map do |ps|
363+
ps.enum_definition
393364
end
394365
end
395366

396367
def parser_states_stacks
397-
@grammar.parser_states.map do |parser_state|
398-
"yyparser_state_#{parser_state.state_id.s_value}"
368+
@grammar.parser_states.map do |ps|
369+
ps.states_stacks
399370
end
400371
end
401372

402373
def parser_states_functions
403-
# TODO: Stack check for push and pop
404-
@grammar.parser_states.map do |parser_state|
405-
<<~FUNC
406-
# define YYPUSH_STATE_#{parser_state.state_id.s_value.upcase}(value) \\
407-
do \\
408-
{ \\
409-
*++yyparser_state_#{parser_state.state_id.s_value}_p = value; \\
410-
} \\
411-
while (0)
412-
413-
# define YYPOP_STATE_#{parser_state.state_id.s_value.upcase}() \\
414-
do \\
415-
{ \\
416-
yyparser_state_#{parser_state.state_id.s_value}_p -= 1; \\
417-
} \\
418-
while (0)
419-
420-
# define YYSET_STATE_#{parser_state.state_id.s_value.upcase}(value) \\
421-
do \\
422-
{ \\
423-
*yyparser_state_#{parser_state.state_id.s_value}_p = value; \\
424-
} \\
425-
while (0)
426-
427-
# define YY_STATE_#{parser_state.state_id.s_value.upcase} yyparser_state_#{parser_state.state_id.s_value}_p
428-
FUNC
374+
@grammar.parser_states.map do |ps|
375+
ps.states_functions
429376
end
430377
end
431378

sig/lrama/grammar/parser_state.rbs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ module Lrama
55
attr_reader state_list: Array[Lexer::Token::Ident]
66

77
def initialize: (state_id: Lexer::Token::Ident, state_list: Array[Lexer::Token::Ident]) -> void
8+
9+
def enum_definition: () -> String
10+
def states_functions: () -> String
11+
def states_stacks: () -> String
12+
def state_name: () -> String
13+
def enum_name: () -> String
14+
def enum_type: () -> String
15+
def enum_body: () -> String
16+
def int_to_name: () -> Array[String]
17+
def enum_name_table_name: () -> String
18+
def stack_prefix: () -> String
819
end
920
end
1021
end
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
RSpec.describe Lrama::Grammar::ParserState do
2+
let(:location) { Lrama::Lexer::Location.new(first_line: 1, first_column: 0, last_line: 1, last_column: 0) }
3+
let(:state_id) { Lrama::Lexer::Token::Ident.new(s_value: "in_rescue", location: location) }
4+
let(:state_list) do
5+
[
6+
Lrama::Lexer::Token::Ident.new(s_value: "before_rescue", location: location),
7+
Lrama::Lexer::Token::Ident.new(s_value: "after_rescue", location: location),
8+
Lrama::Lexer::Token::Ident.new(s_value: "after_else", location: location),
9+
Lrama::Lexer::Token::Ident.new(s_value: "after_ensure", location: location)
10+
]
11+
end
12+
let(:parser_state) { Lrama::Grammar::ParserState.new(state_id: state_id, state_list: state_list) }
13+
14+
describe "#enum_definition" do
15+
it "returns enum definition" do
16+
expect(parser_state.enum_definition).to eq <<~ENUM
17+
enum yyparser_state_in_rescue
18+
{
19+
before_rescue,
20+
after_rescue,
21+
after_else,
22+
after_ensure
23+
};
24+
typedef enum yyparser_state_in_rescue yyparser_state_in_rescue_t;
25+
26+
static const char *const yyparser_state_in_rescue_names[] = {
27+
"before_rescue", "after_rescue", "after_else", "after_ensure", YY_NULLPTR
28+
};
29+
30+
YY_ATTRIBUTE_UNUSED
31+
static const char *
32+
yyparser_state_in_rescue_name (yyparser_state_in_rescue_t num)
33+
{
34+
return yyparser_state_in_rescue_names[num];
35+
}
36+
37+
# define YY_STATE_IN_RESCUE_NAME yyparser_state_in_rescue_name (*yyparser_state_in_rescue_p)
38+
ENUM
39+
end
40+
end
41+
42+
describe "#states_functions" do
43+
it "returns states functions" do
44+
expect(parser_state.states_functions).to eq <<~FUNC
45+
# define YYPUSH_STATE_IN_RESCUE(value) \\
46+
do \\
47+
{ \\
48+
YYDPRINTF ((stderr, "Push in_rescue\\n")); \\
49+
*++yyparser_state_in_rescue_p = value; \\
50+
} \\
51+
while (0)
52+
53+
# define YYPOP_STATE_IN_RESCUE() \\
54+
do \\
55+
{ \\
56+
YYDPRINTF ((stderr, "Pop in_rescue\\n")); \\
57+
if (yyparser_state_in_rescue_p != yyparser_state_in_rescue) \\
58+
{ \\
59+
yyparser_state_in_rescue_p -= 1; \\
60+
} \\
61+
else \\
62+
{ \\
63+
YYDPRINTF ((stderr, "Try to pop empty in_rescue stack\\n")); \\
64+
} \\
65+
} \\
66+
while (0)
67+
68+
# define YYSET_STATE_IN_RESCUE(value) \\
69+
do \\
70+
{ \\
71+
YYDPRINTF ((stderr, "Set in_rescue\\n")); \\
72+
*yyparser_state_in_rescue_p = value; \\
73+
} \\
74+
while (0)
75+
76+
# define YY_STATE_IN_RESCUE yyparser_state_in_rescue_p
77+
FUNC
78+
end
79+
end
80+
81+
describe "#states_stacks" do
82+
it "returns states stacks" do
83+
expect(parser_state.states_stacks).to eq <<~STACKS
84+
/* The parser state stack (yyparser_state_in_rescue): array, bottom, top. */
85+
int yyparser_state_in_rescue_a[YYINITDEPTH];
86+
int *yyparser_state_in_rescue = yyparser_state_in_rescue_a;
87+
int *yyparser_state_in_rescue_p = yyparser_state_in_rescue;
88+
STACKS
89+
end
90+
end
91+
92+
describe "#state_name" do
93+
it "returns state name" do
94+
expect(parser_state.state_name).to eq "in_rescue"
95+
end
96+
end
97+
98+
describe "#enum_name" do
99+
it "returns enum name" do
100+
expect(parser_state.enum_name).to eq "yyparser_state_in_rescue"
101+
end
102+
end
103+
104+
describe "#enum_type" do
105+
it "returns enum type" do
106+
expect(parser_state.enum_type).to eq "yyparser_state_in_rescue_t"
107+
end
108+
end
109+
110+
describe "#enum_body" do
111+
it "returns enum body" do
112+
expect(parser_state.enum_body).to eq <<~BODY.chomp
113+
before_rescue,
114+
after_rescue,
115+
after_else,
116+
after_ensure
117+
BODY
118+
end
119+
end
120+
121+
describe "#int_to_name" do
122+
it "returns int to name table" do
123+
expect(parser_state.int_to_name).to eq [
124+
"\"before_rescue\"",
125+
"\"after_rescue\"",
126+
"\"after_else\"",
127+
"\"after_ensure\"",
128+
"YY_NULLPTR"
129+
]
130+
end
131+
end
132+
133+
describe "#enum_name_table_name" do
134+
it "returns table name" do
135+
expect(parser_state.enum_name_table_name).to eq "yyparser_state_in_rescue_names"
136+
end
137+
end
138+
139+
describe "#stack_prefix" do
140+
it "returns prefix" do
141+
expect(parser_state.stack_prefix).to eq "yyparser_state_in_rescue"
142+
end
143+
end
144+
end

template/bison/yacc.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,11 +1519,8 @@ YYLTYPE yylloc = yyloc_default;
15191519
YYLTYPE *yyls = yylsa;
15201520
YYLTYPE *yylsp = yyls;
15211521

1522-
<%- output.parser_states_stacks.each do |parser_state| -%>
1523-
/* The parser state stack (<%= parser_state %>): array, bottom, top. */
1524-
int <%= parser_state %>_a[YYINITDEPTH];
1525-
int *<%= parser_state %> = <%= parser_state %>_a;
1526-
int *<%= parser_state %>_p = <%= parser_state %>;
1522+
<%- output.parser_states_stacks.each do |states_stacks| -%>
1523+
<%= states_stacks %>
15271524
<%- end -%>
15281525

15291526
int yyn;

0 commit comments

Comments
 (0)