mkbison 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|