mkbison 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/README.md +75 -52
- data/bin/mkbison +3 -1
- data/bison_parser.rby +2 -15
- data/examples/arithmetic/Gemfile +4 -0
- data/examples/arithmetic/Rakefile +5 -0
- data/examples/arithmetic/arithmetic.rby +80 -0
- data/ext/bison_parser/bison_parser.c +42 -51
- data/ext/bison_parser/bison_parser.y +2 -9
- data/ext/bison_parser/extconf.rb +5 -0
- data/lib/bison/version.rb +1 -1
- data/lib/bison_parser.rb +1 -13
- data/lib/bison_parser/actions.rb +2 -6
- data/lib/bison_parser/base.rb +25 -1
- data/templates/base.rb.erb +25 -1
- data/templates/extconf.rb.erb +5 -0
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4953dfa30988cbe416adf37cf53b7cc7cb6650e5
|
4
|
+
data.tar.gz: 4d2ca4c185047779a8f1aa998ee27b512ae161f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b34b3be1c7e9212793c7b7a4d3efb4bed4ac290e575a54b95f8d0c3c258ed4b67d6e1c7422f7ebd86026ebeaec2c4a634a1813a29805c33e6d9dc6861cd96b6
|
7
|
+
data.tar.gz: 634ec92aa22ec51f382d316f32ea70c152f9a835ba40ccc802a2bb7166eef13b9a0cb3dc0d64fd5e031cd92c5b0031d58d893890a04d21252271a50be0e50e0d
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,43 +1,31 @@
|
|
1
1
|
# mkbison
|
2
2
|
|
3
|
-
|
3
|
+
`mkbison` is a tool to create native ruby extensions containing [GNU Bison](https://www.gnu.org/software/bison/) generated LALR(1) grammar parsers.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
Add
|
7
|
+
Add these lines to your application's Gemfile:
|
8
8
|
|
9
9
|
gem 'mkbison'
|
10
|
+
gem 'rake-compiler'
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install mkbison
|
18
|
-
|
19
|
-
You'll need to install [GNU Bison](https://www.gnu.org/software/bison/) as well, e.g.:
|
12
|
+
You'll need to install a GNU Bison version >= 3.0.0 as well, with e.g.:
|
20
13
|
|
21
14
|
$ sudo apt-get install bison
|
22
15
|
|
23
16
|
## Usage and Example
|
24
17
|
|
25
|
-
|
26
|
-
|
27
|
-
`.rby` files contain a grammar definition and ruby code. Their syntax mostly mirrors that of Bison grammar files, with the following differences:
|
18
|
+
`mkbison` operates on grammar files with a syntax which mostly mirrors the Bison grammar. For example, here is a file which describes basic arithmetic:
|
28
19
|
|
29
|
-
|
30
|
-
|
31
|
-
* [Named references](http://www.gnu.org/software/bison/manual/html_node/Named-References.html) should not use a dollar sign `$`.
|
20
|
+
**[arithmetic.rby](https://github.com/wioux/mkbison/blob/master/examples/arithmetic/arithmetic.rby)**
|
21
|
+
```yacc
|
32
22
|
|
33
|
-
For example, here is a mkbison grammar for parsing very simple arithmetic expressions:
|
34
|
-
|
35
|
-
**arithmetic.rby**
|
36
|
-
```
|
37
23
|
%token NUMBER
|
24
|
+
%token LPAREN
|
25
|
+
%token RPAREN
|
38
26
|
|
39
|
-
%left OP_PLUS
|
40
|
-
%left
|
27
|
+
%left OP_PLUS OP_MINUS
|
28
|
+
%left OP_TIMES OP_OVER
|
41
29
|
|
42
30
|
%%
|
43
31
|
|
@@ -48,8 +36,14 @@ arithmetic:
|
|
48
36
|
|
49
37
|
expression :
|
50
38
|
NUMBER
|
39
|
+
| OP_MINUS expression[x]
|
40
|
+
{ -x }
|
41
|
+
| LPAREN expression[x] RPAREN
|
42
|
+
{ x }
|
51
43
|
| addition
|
52
44
|
| subtraction
|
45
|
+
| multiplication
|
46
|
+
| division
|
53
47
|
;
|
54
48
|
|
55
49
|
addition :
|
@@ -62,30 +56,24 @@ subtraction :
|
|
62
56
|
{ left - right }
|
63
57
|
;
|
64
58
|
|
59
|
+
multiplication:
|
60
|
+
expression[left] OP_TIMES expression[right]
|
61
|
+
{ left * right }
|
62
|
+
;
|
63
|
+
|
64
|
+
division:
|
65
|
+
expression[left] OP_OVER expression[right]
|
66
|
+
{ left / right }
|
67
|
+
;
|
68
|
+
|
65
69
|
%%
|
66
70
|
|
67
71
|
class Arithmetic
|
68
72
|
def lex
|
69
|
-
|
70
|
-
while true
|
71
|
-
while (c = self.read) && c =~ /\s/
|
72
|
-
end
|
73
|
-
|
74
|
-
if c == '#'
|
75
|
-
while (char = self.read) && char != "\n"
|
76
|
-
end
|
77
|
-
else
|
78
|
-
break
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
73
|
+
c = read_over_whitespace
|
82
74
|
case c
|
83
75
|
when '0'..'9'
|
84
|
-
number = c
|
85
|
-
while (c = self.peak) && ('0'..'9').include?(c)
|
86
|
-
number << self.read
|
87
|
-
end
|
88
|
-
|
76
|
+
number = read_integer(c)
|
89
77
|
self.lex_value = number.to_i
|
90
78
|
return Tokens::NUMBER
|
91
79
|
|
@@ -94,30 +82,65 @@ class Arithmetic
|
|
94
82
|
|
95
83
|
when '-'
|
96
84
|
return Tokens::OP_MINUS
|
97
|
-
end
|
98
85
|
|
99
|
-
|
86
|
+
when '*'
|
87
|
+
return Tokens::OP_TIMES
|
88
|
+
|
89
|
+
when '/'
|
90
|
+
return Tokens::OP_OVER
|
91
|
+
|
92
|
+
when '('
|
93
|
+
return Tokens::LPAREN
|
94
|
+
|
95
|
+
when ')'
|
96
|
+
return Tokens::RPAREN
|
97
|
+
|
98
|
+
else
|
99
|
+
return nil
|
100
|
+
end
|
100
101
|
end
|
101
102
|
end
|
102
103
|
```
|
103
104
|
|
104
|
-
|
105
|
+
The structure here should be recognizable to those familiar with GNU Bison. If you aren't, you might want to [read up on its usage](https://www.gnu.org/software/bison/manual/html_node/index.html) before using `mkbison`.
|
105
106
|
|
106
|
-
|
107
|
-
|
107
|
+
There are three sections:
|
108
|
+
|
109
|
+
1) Token and precedence definitions
|
110
|
+
2) The description of the grammar
|
111
|
+
3) The lexing implementation
|
112
|
+
|
113
|
+
To compile this into a ruby extension which we can use to calculate basic arithmetic expressions, first run `mkbison`:
|
114
|
+
|
115
|
+
$ bundle exec mkbison -n Arithmetic arithmetic.rby
|
116
|
+
|
117
|
+
This creates the ruby extension in the current directory (under `lib/` and `ext/` directories). The Bison translation of the grammar can be found at `ext/arithmetic/arithmetic.y`. Once compiled, we'll be able to require it as `'arithmetic'` and use it with `Arithmetic.new(expression).parse`.
|
118
|
+
|
119
|
+
Next we'll need to create a `rake` task as follows:
|
120
|
+
|
121
|
+
**[Rakefile](https://github.com/wioux/mkbison/blob/master/examples/arithmetic/Rakefile)**
|
122
|
+
```ruby
|
123
|
+
require "rake/extensiontask"
|
124
|
+
|
125
|
+
Rake::ExtensionTask.new "arithmetic" do |ext|
|
126
|
+
ext.lib_dir = "lib/arithmetic"
|
127
|
+
end
|
128
|
+
```
|
108
129
|
|
109
|
-
|
130
|
+
Once we have that, we can compile our extension simply by running
|
131
|
+
|
132
|
+
$ rake compile
|
110
133
|
|
111
134
|
## TODO
|
135
|
+
* Add tests
|
136
|
+
* Support string/character literals in grammar rules
|
112
137
|
* Automatically create Rakefile task
|
113
|
-
* Change the parsers initialize() behavior (don't assume argument is file path)
|
114
|
-
|
115
|
-
* Seems like you can hit EOF in the middle of action block and get wrong error msg
|
116
|
-
* Benchmark -- what takes so long on the koa grammar?
|
117
138
|
* Write to temp files, then move them into place
|
118
139
|
* Move base module into the c extension and document the lexing helpers
|
140
|
+
* Seems like you can hit EOF in the middle of action block and get wrong error msg
|
141
|
+
* Benchmark -- what takes so long on the koa grammar?
|
119
142
|
|
120
|
-
Not all Bison features are supported yet
|
143
|
+
Not all Bison features are supported yet...
|
121
144
|
|
122
145
|
## Contributing
|
123
146
|
|
data/bin/mkbison
CHANGED
@@ -17,6 +17,7 @@ def underscore(name)
|
|
17
17
|
end
|
18
18
|
|
19
19
|
options = OpenStruct.new
|
20
|
+
options.output = '.'
|
20
21
|
|
21
22
|
opts = OptionParser.new do |opts|
|
22
23
|
opts.banner += ' grammar_file'
|
@@ -39,7 +40,7 @@ options.name or abort(opts.help)
|
|
39
40
|
options.output or abort(opts.help)
|
40
41
|
|
41
42
|
begin
|
42
|
-
bison = BisonParser.new(grammar_file).parse
|
43
|
+
bison = BisonParser.new(File.open(grammar_file, 'r')).parse
|
43
44
|
rescue BisonParser::Error => e
|
44
45
|
abort(e.message)
|
45
46
|
end
|
@@ -72,6 +73,7 @@ Tempfile.new('bison-output.c').tap do |output|
|
|
72
73
|
bison = Cocaine::CommandLine.new(ENV['BISON_PATH'] || 'bison', '-o :out :in')
|
73
74
|
begin
|
74
75
|
bison.run(in: bison_file.path, out: output.path)
|
76
|
+
warn bison.command_error_output
|
75
77
|
rescue Cocaine::CommandNotFoundError => e
|
76
78
|
warn("The bison command was not found on this system. " +
|
77
79
|
"Make sure to install it before attempting rake compile.")
|
data/bison_parser.rby
CHANGED
@@ -68,8 +68,7 @@ grammar_rule:
|
|
68
68
|
;
|
69
69
|
|
70
70
|
components:
|
71
|
-
|
72
|
-
| sequence[sequence]
|
71
|
+
sequence[sequence]
|
73
72
|
{ [sequence] }
|
74
73
|
|
|
75
74
|
components[sequences] PIPE sequence[sequence]
|
@@ -104,19 +103,7 @@ class BisonParser
|
|
104
103
|
return Tokens::ACTIONS
|
105
104
|
end
|
106
105
|
|
107
|
-
|
108
|
-
while true
|
109
|
-
while (c = self.read) && c =~ /\s/
|
110
|
-
end
|
111
|
-
|
112
|
-
if c == '#'
|
113
|
-
while (char = self.read) && char != "\n"
|
114
|
-
end
|
115
|
-
else
|
116
|
-
break
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
106
|
+
c = read_over_whitespace(line_comment_prefix: '#')
|
120
107
|
return nil unless c
|
121
108
|
|
122
109
|
case c
|
@@ -0,0 +1,80 @@
|
|
1
|
+
%token NUMBER
|
2
|
+
%token LPAREN
|
3
|
+
%token RPAREN
|
4
|
+
|
5
|
+
%left OP_PLUS OP_MINUS
|
6
|
+
%left OP_TIMES OP_OVER
|
7
|
+
|
8
|
+
%%
|
9
|
+
|
10
|
+
arithmetic:
|
11
|
+
expression[x]
|
12
|
+
{ self.result = x }
|
13
|
+
;
|
14
|
+
|
15
|
+
expression :
|
16
|
+
NUMBER
|
17
|
+
| OP_MINUS expression[x]
|
18
|
+
{ -x }
|
19
|
+
| LPAREN expression[x] RPAREN
|
20
|
+
{ x }
|
21
|
+
| addition
|
22
|
+
| subtraction
|
23
|
+
| multiplication
|
24
|
+
| division
|
25
|
+
;
|
26
|
+
|
27
|
+
addition :
|
28
|
+
expression[left] OP_PLUS expression[right]
|
29
|
+
{ left + right }
|
30
|
+
;
|
31
|
+
|
32
|
+
subtraction :
|
33
|
+
expression[left] OP_MINUS expression[right]
|
34
|
+
{ left - right }
|
35
|
+
;
|
36
|
+
|
37
|
+
multiplication:
|
38
|
+
expression[left] OP_TIMES expression[right]
|
39
|
+
{ left * right }
|
40
|
+
;
|
41
|
+
|
42
|
+
division:
|
43
|
+
expression[left] OP_OVER expression[right]
|
44
|
+
{ left / right }
|
45
|
+
;
|
46
|
+
|
47
|
+
%%
|
48
|
+
|
49
|
+
class Arithmetic
|
50
|
+
def lex
|
51
|
+
c = read_over_whitespace
|
52
|
+
case c
|
53
|
+
when '0'..'9'
|
54
|
+
number = read_integer(c)
|
55
|
+
self.lex_value = number.to_i
|
56
|
+
return Tokens::NUMBER
|
57
|
+
|
58
|
+
when '+'
|
59
|
+
return Tokens::OP_PLUS
|
60
|
+
|
61
|
+
when '-'
|
62
|
+
return Tokens::OP_MINUS
|
63
|
+
|
64
|
+
when '*'
|
65
|
+
return Tokens::OP_TIMES
|
66
|
+
|
67
|
+
when '/'
|
68
|
+
return Tokens::OP_OVER
|
69
|
+
|
70
|
+
when '('
|
71
|
+
return Tokens::LPAREN
|
72
|
+
|
73
|
+
when ')'
|
74
|
+
return Tokens::RPAREN
|
75
|
+
|
76
|
+
else
|
77
|
+
return nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -403,7 +403,7 @@ union yyalloc
|
|
403
403
|
/* YYNNTS -- Number of nonterminals. */
|
404
404
|
#define YYNNTS 10
|
405
405
|
/* YYNRULES -- Number of rules. */
|
406
|
-
#define YYNRULES
|
406
|
+
#define YYNRULES 21
|
407
407
|
/* YYNSTATES -- Number of states. */
|
408
408
|
#define YYNSTATES 33
|
409
409
|
|
@@ -454,8 +454,8 @@ static const yytype_uint8 yytranslate[] =
|
|
454
454
|
static const yytype_uint8 yyrline[] =
|
455
455
|
{
|
456
456
|
0, 37, 37, 50, 56, 67, 73, 84, 92, 96,
|
457
|
-
107, 115, 123, 135, 141, 152,
|
458
|
-
|
457
|
+
107, 115, 123, 135, 141, 152, 163, 171, 183, 189,
|
458
|
+
198, 207
|
459
459
|
};
|
460
460
|
#endif
|
461
461
|
|
@@ -482,12 +482,12 @@ static const yytype_uint16 yytoknum[] =
|
|
482
482
|
};
|
483
483
|
# endif
|
484
484
|
|
485
|
-
#define YYPACT_NINF -
|
485
|
+
#define YYPACT_NINF -9
|
486
486
|
|
487
487
|
#define yypact_value_is_default(Yystate) \
|
488
|
-
(!!((Yystate) == (-
|
488
|
+
(!!((Yystate) == (-9)))
|
489
489
|
|
490
|
-
#define YYTABLE_NINF -
|
490
|
+
#define YYTABLE_NINF -1
|
491
491
|
|
492
492
|
#define yytable_value_is_error(Yytable_value) \
|
493
493
|
0
|
@@ -496,10 +496,10 @@ static const yytype_uint16 yytoknum[] =
|
|
496
496
|
STATE-NUM. */
|
497
497
|
static const yytype_int8 yypact[] =
|
498
498
|
{
|
499
|
-
-
|
500
|
-
|
501
|
-
-
|
502
|
-
|
499
|
+
-9, 9, -8, -9, -7, -9, 7, 11, 12, 13,
|
500
|
+
14, -2, -9, -9, -9, -9, -9, 6, 2, -9,
|
501
|
+
-9, -9, -9, -5, -3, -9, -9, 15, -9, -3,
|
502
|
+
16, 17, -9
|
503
503
|
};
|
504
504
|
|
505
505
|
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
|
@@ -509,14 +509,14 @@ static const yytype_uint8 yydefact[] =
|
|
509
509
|
{
|
510
510
|
5, 0, 0, 1, 0, 13, 6, 8, 0, 0,
|
511
511
|
0, 3, 9, 12, 7, 10, 11, 0, 0, 2,
|
512
|
-
14,
|
513
|
-
0, 0,
|
512
|
+
14, 18, 4, 0, 16, 15, 18, 20, 19, 17,
|
513
|
+
0, 0, 21
|
514
514
|
};
|
515
515
|
|
516
516
|
/* YYPGOTO[NTERM-NUM]. */
|
517
517
|
static const yytype_int8 yypgoto[] =
|
518
518
|
{
|
519
|
-
-
|
519
|
+
-9, -9, -9, -9, -9, -9, -9, -9, -9, -6
|
520
520
|
};
|
521
521
|
|
522
522
|
/* YYDEFGOTO[NTERM-NUM]. */
|
@@ -528,18 +528,18 @@ static const yytype_int8 yydefgoto[] =
|
|
528
528
|
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
|
529
529
|
positive, shift that token. If negative, reduce the rule whose
|
530
530
|
number is the opposite. If YYTABLE_NINF, syntax error. */
|
531
|
-
static const
|
531
|
+
static const yytype_uint8 yytable[] =
|
532
532
|
{
|
533
|
-
|
534
|
-
|
535
|
-
|
533
|
+
27, 17, 25, 4, 5, 26, 8, 9, 10, 3,
|
534
|
+
18, 12, 21, 28, 13, 14, 15, 16, 22, 31,
|
535
|
+
29, 0, 0, 30, 0, 0, 32
|
536
536
|
};
|
537
537
|
|
538
538
|
static const yytype_int8 yycheck[] =
|
539
539
|
{
|
540
|
-
3, 3,
|
541
|
-
|
542
|
-
|
540
|
+
3, 3, 7, 11, 12, 10, 13, 14, 15, 0,
|
541
|
+
12, 4, 6, 16, 3, 3, 3, 3, 16, 3,
|
542
|
+
26, -1, -1, 8, -1, -1, 9
|
543
543
|
};
|
544
544
|
|
545
545
|
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
|
@@ -556,16 +556,16 @@ static const yytype_uint8 yystos[] =
|
|
556
556
|
static const yytype_uint8 yyr1[] =
|
557
557
|
{
|
558
558
|
0, 17, 18, 19, 19, 20, 20, 21, 21, 21,
|
559
|
-
22, 22, 22, 23, 23, 24, 25, 25,
|
560
|
-
26, 26
|
559
|
+
22, 22, 22, 23, 23, 24, 25, 25, 26, 26,
|
560
|
+
26, 26
|
561
561
|
};
|
562
562
|
|
563
563
|
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
|
564
564
|
static const yytype_uint8 yyr2[] =
|
565
565
|
{
|
566
566
|
0, 2, 4, 0, 2, 0, 2, 3, 1, 2,
|
567
|
-
3, 3, 2, 0, 2, 4,
|
568
|
-
2,
|
567
|
+
3, 3, 2, 0, 2, 4, 1, 3, 0, 2,
|
568
|
+
2, 5
|
569
569
|
};
|
570
570
|
|
571
571
|
|
@@ -1486,65 +1486,56 @@ yyreduce:
|
|
1486
1486
|
#line 164 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1487
1487
|
{
|
1488
1488
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1489
|
-
(
|
1489
|
+
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1490
|
+
(yyval) = rb_funcall(__actions, rb_intern("_0_components_2403a823f1a9854a29da7cf64f191fbe"), 1, (yyvsp[0]));
|
1490
1491
|
}
|
1491
|
-
#line
|
1492
|
+
#line 1493 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1492
1493
|
break;
|
1493
1494
|
|
1494
1495
|
case 17:
|
1495
|
-
#line
|
1496
|
+
#line 172 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1496
1497
|
{
|
1497
1498
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1499
|
+
rb_ivar_set(__actions, rb_intern("@sequences"), rb_ary_new3(2, INT2FIX((yylsp[-2]).first_line), INT2FIX((yylsp[-2]).first_column)));
|
1498
1500
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1499
|
-
(yyval) = rb_funcall(__actions, rb_intern("
|
1501
|
+
(yyval) = rb_funcall(__actions, rb_intern("_1_components_62da044340939f02b6c0b52917617e17"), 2, (yyvsp[-2]), (yyvsp[0]));
|
1500
1502
|
}
|
1501
|
-
#line
|
1503
|
+
#line 1504 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1502
1504
|
break;
|
1503
1505
|
|
1504
1506
|
case 18:
|
1505
|
-
#line
|
1507
|
+
#line 183 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1506
1508
|
{
|
1507
1509
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1508
|
-
|
1509
|
-
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1510
|
-
(yyval) = rb_funcall(__actions, rb_intern("_2_components_62da044340939f02b6c0b52917617e17"), 2, (yyvsp[-2]), (yyvsp[0]));
|
1510
|
+
(yyval) = rb_funcall(__actions, rb_intern("_0_sequence_99914b932bd37a50b983c5e7c90ae93b"), 0);
|
1511
1511
|
}
|
1512
1512
|
#line 1513 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1513
1513
|
break;
|
1514
1514
|
|
1515
1515
|
case 19:
|
1516
1516
|
#line 190 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1517
|
-
{
|
1518
|
-
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1519
|
-
(yyval) = rb_funcall(__actions, rb_intern("_0_sequence_99914b932bd37a50b983c5e7c90ae93b"), 0);
|
1520
|
-
}
|
1521
|
-
#line 1522 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1522
|
-
break;
|
1523
|
-
|
1524
|
-
case 20:
|
1525
|
-
#line 197 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1526
1517
|
{
|
1527
1518
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1528
1519
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1529
1520
|
rb_ivar_set(__actions, rb_intern("@code"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1530
1521
|
(yyval) = rb_funcall(__actions, rb_intern("_1_sequence_512ceffccf6bb7565046f90d6d7762ad"), 2, (yyvsp[-1]), (yyvsp[0]));
|
1531
1522
|
}
|
1532
|
-
#line
|
1523
|
+
#line 1524 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1533
1524
|
break;
|
1534
1525
|
|
1535
|
-
case
|
1536
|
-
#line
|
1526
|
+
case 20:
|
1527
|
+
#line 199 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1537
1528
|
{
|
1538
1529
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1539
1530
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1540
1531
|
rb_ivar_set(__actions, rb_intern("@follower"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1541
1532
|
(yyval) = rb_funcall(__actions, rb_intern("_2_sequence_4b2903c3aeb37d22d413a53653d0df28"), 2, (yyvsp[-1]), (yyvsp[0]));
|
1542
1533
|
}
|
1543
|
-
#line
|
1534
|
+
#line 1535 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1544
1535
|
break;
|
1545
1536
|
|
1546
|
-
case
|
1547
|
-
#line
|
1537
|
+
case 21:
|
1538
|
+
#line 208 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1548
1539
|
{
|
1549
1540
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1550
1541
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[-4]).first_line), INT2FIX((yylsp[-4]).first_column)));
|
@@ -1552,11 +1543,11 @@ yyreduce:
|
|
1552
1543
|
rb_ivar_set(__actions, rb_intern("@tag"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1553
1544
|
(yyval) = rb_funcall(__actions, rb_intern("_3_sequence_68f2380aa0f3a7de0fb9b3482705a54c"), 3, (yyvsp[-4]), (yyvsp[-3]), (yyvsp[-1]));
|
1554
1545
|
}
|
1555
|
-
#line
|
1546
|
+
#line 1547 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1556
1547
|
break;
|
1557
1548
|
|
1558
1549
|
|
1559
|
-
#line
|
1550
|
+
#line 1551 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1560
1551
|
default: break;
|
1561
1552
|
}
|
1562
1553
|
/* User semantic actions sometimes alter yychar, and that requires
|
@@ -1791,7 +1782,7 @@ yyreturn:
|
|
1791
1782
|
#endif
|
1792
1783
|
return yyresult;
|
1793
1784
|
}
|
1794
|
-
#line
|
1785
|
+
#line 219 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1906 */
|
1795
1786
|
|
1796
1787
|
|
1797
1788
|
static VALUE cBisonParser;
|
@@ -160,18 +160,11 @@ grammar_rule:
|
|
160
160
|
;
|
161
161
|
|
162
162
|
components:
|
163
|
-
|
164
|
-
{
|
165
|
-
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX(@$.first_line), INT2FIX(@$.first_column)));
|
166
|
-
$$ = rb_funcall(__actions, rb_intern("_0_components_99914b932bd37a50b983c5e7c90ae93b"), 0);
|
167
|
-
}
|
168
|
-
|
169
|
-
|
|
170
163
|
sequence
|
171
164
|
{
|
172
165
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX(@$.first_line), INT2FIX(@$.first_column)));
|
173
166
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX(@1.first_line), INT2FIX(@1.first_column)));
|
174
|
-
$$ = rb_funcall(__actions, rb_intern("
|
167
|
+
$$ = rb_funcall(__actions, rb_intern("_0_components_2403a823f1a9854a29da7cf64f191fbe"), 1, $1);
|
175
168
|
}
|
176
169
|
|
177
170
|
|
|
@@ -180,7 +173,7 @@ components:
|
|
180
173
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX(@$.first_line), INT2FIX(@$.first_column)));
|
181
174
|
rb_ivar_set(__actions, rb_intern("@sequences"), rb_ary_new3(2, INT2FIX(@1.first_line), INT2FIX(@1.first_column)));
|
182
175
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX(@3.first_line), INT2FIX(@3.first_column)));
|
183
|
-
$$ = rb_funcall(__actions, rb_intern("
|
176
|
+
$$ = rb_funcall(__actions, rb_intern("_1_components_62da044340939f02b6c0b52917617e17"), 2, $1, $3);
|
184
177
|
}
|
185
178
|
|
186
179
|
;
|
data/ext/bison_parser/extconf.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'mkmf'
|
2
|
+
require 'shellwords'
|
2
3
|
|
3
4
|
output = "#{File.dirname(__FILE__)}/bison_parser.c"
|
4
5
|
bison_file = "#{File.dirname(__FILE__)}/bison_parser.y"
|
5
6
|
|
6
7
|
bison = find_executable(ENV['BISON_PATH'] || 'bison')
|
8
|
+
bison_version = `#{Shellwords.shellescape(bison)} --version`.lines[0]
|
9
|
+
if bison_version =~ / [012]\.\d+(\.\d+)?\b/
|
10
|
+
abort("bison version must be >= 3.0.0")
|
11
|
+
end
|
7
12
|
system(bison, '-o', output, bison_file) or abort("bison command failed")
|
8
13
|
|
9
14
|
create_makefile 'bison_parser/bison_parser'
|
data/lib/bison/version.rb
CHANGED
data/lib/bison_parser.rb
CHANGED
@@ -12,19 +12,7 @@ class BisonParser
|
|
12
12
|
return Tokens::ACTIONS
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
while true
|
17
|
-
while (c = self.read) && c =~ /\s/
|
18
|
-
end
|
19
|
-
|
20
|
-
if c == '#'
|
21
|
-
while (char = self.read) && char != "\n"
|
22
|
-
end
|
23
|
-
else
|
24
|
-
break
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
15
|
+
c = read_over_whitespace(line_comment_prefix: '#')
|
28
16
|
return nil unless c
|
29
17
|
|
30
18
|
case c
|
data/lib/bison_parser/actions.rb
CHANGED
@@ -54,15 +54,11 @@ class BisonParser
|
|
54
54
|
Bison::Rule.new(name, components).tap{ |r| r.location = @name }
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
58
|
-
[]
|
59
|
-
end
|
60
|
-
|
61
|
-
def _1_components_2403a823f1a9854a29da7cf64f191fbe(sequence)
|
57
|
+
def _0_components_2403a823f1a9854a29da7cf64f191fbe(sequence)
|
62
58
|
[sequence]
|
63
59
|
end
|
64
60
|
|
65
|
-
def
|
61
|
+
def _1_components_62da044340939f02b6c0b52917617e17(sequences, sequence)
|
66
62
|
sequences << sequence
|
67
63
|
end
|
68
64
|
|
data/lib/bison_parser/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
1
3
|
class BisonParser
|
2
4
|
attr_reader :io
|
3
5
|
attr_accessor :lex_value, :token_row, :token_col, :row, :col
|
@@ -6,12 +8,34 @@ class BisonParser
|
|
6
8
|
module Base
|
7
9
|
def initialize(io)
|
8
10
|
if String === io
|
9
|
-
io =
|
11
|
+
io = StringIO.new(io)
|
10
12
|
end
|
11
13
|
@source = io.respond_to?(:path) ? io.path : nil
|
12
14
|
@io, @row, @col = io, 1, 0
|
13
15
|
end
|
14
16
|
|
17
|
+
def read_over_whitespace(line_comment_prefix: nil)
|
18
|
+
while true
|
19
|
+
while (c = self.read) && c =~ /\s/
|
20
|
+
end
|
21
|
+
|
22
|
+
if line_comment_prefix && c == line_comment_prefix
|
23
|
+
while (char = self.read) && char != "\n"
|
24
|
+
end
|
25
|
+
else
|
26
|
+
break
|
27
|
+
end
|
28
|
+
end
|
29
|
+
c
|
30
|
+
end
|
31
|
+
|
32
|
+
def read_integer(number='')
|
33
|
+
while (c = self.peak) && ('0'..'9').include?(c)
|
34
|
+
number << self.read
|
35
|
+
end
|
36
|
+
number
|
37
|
+
end
|
38
|
+
|
15
39
|
def read
|
16
40
|
io.read(1).tap do |c|
|
17
41
|
if c == "\n"
|
data/templates/base.rb.erb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
1
3
|
class <%= name %>
|
2
4
|
attr_reader :io
|
3
5
|
attr_accessor :lex_value, :token_row, :token_col, :row, :col
|
@@ -6,12 +8,34 @@ class <%= name %>
|
|
6
8
|
module Base
|
7
9
|
def initialize(io)
|
8
10
|
if String === io
|
9
|
-
io =
|
11
|
+
io = StringIO.new(io)
|
10
12
|
end
|
11
13
|
@source = io.respond_to?(:path) ? io.path : nil
|
12
14
|
@io, @row, @col = io, 1, 0
|
13
15
|
end
|
14
16
|
|
17
|
+
def read_over_whitespace(line_comment_prefix: nil)
|
18
|
+
while true
|
19
|
+
while (c = self.read) && c =~ /\s/
|
20
|
+
end
|
21
|
+
|
22
|
+
if line_comment_prefix && c == line_comment_prefix
|
23
|
+
while (char = self.read) && char != "\n"
|
24
|
+
end
|
25
|
+
else
|
26
|
+
break
|
27
|
+
end
|
28
|
+
end
|
29
|
+
c
|
30
|
+
end
|
31
|
+
|
32
|
+
def read_integer(number='')
|
33
|
+
while (c = self.peak) && ('0'..'9').include?(c)
|
34
|
+
number << self.read
|
35
|
+
end
|
36
|
+
number
|
37
|
+
end
|
38
|
+
|
15
39
|
def read
|
16
40
|
io.read(1).tap do |c|
|
17
41
|
if c == "\n"
|
data/templates/extconf.rb.erb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'mkmf'
|
2
|
+
require 'shellwords'
|
2
3
|
|
3
4
|
output = "#{File.dirname(__FILE__)}/<%= uname %>.c"
|
4
5
|
bison_file = "#{File.dirname(__FILE__)}/<%= uname %>.y"
|
5
6
|
|
6
7
|
bison = find_executable(ENV['BISON_PATH'] || 'bison')
|
8
|
+
bison_version = `#{Shellwords.shellescape(bison)} --version`.lines[0]
|
9
|
+
if bison_version =~ / [012]\.\d+(\.\d+)?\b/
|
10
|
+
abort("bison version must be >= 3.0.0")
|
11
|
+
end
|
7
12
|
system(bison, '-o', output, bison_file) or abort("bison command failed")
|
8
13
|
|
9
14
|
create_makefile '<%= uname %>/<%= uname %>'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mkbison
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Woo
|
@@ -82,6 +82,9 @@ files:
|
|
82
82
|
- Rakefile
|
83
83
|
- bin/mkbison
|
84
84
|
- bison_parser.rby
|
85
|
+
- examples/arithmetic/Gemfile
|
86
|
+
- examples/arithmetic/Rakefile
|
87
|
+
- examples/arithmetic/arithmetic.rby
|
85
88
|
- ext/bison_parser/bison_parser.c
|
86
89
|
- ext/bison_parser/bison_parser.y
|
87
90
|
- ext/bison_parser/extconf.rb
|