mkbison 0.0.2 → 0.0.3
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/README.md +101 -2
- data/bin/mkbison +14 -3
- data/bison_parser.rby +9 -3
- data/ext/bison_parser/bison_parser.c +93 -76
- data/ext/bison_parser/bison_parser.y +20 -5
- data/ext/bison_parser/extconf.rb +3 -1
- data/lib/bison/grammar_file.rb +1 -1
- data/lib/bison/token.rb +6 -2
- data/lib/bison/version.rb +1 -1
- data/lib/bison_parser/actions.rb +8 -4
- data/mkbison.gemspec +1 -0
- data/templates/extconf.rb.erb +2 -2
- data/templates/parser.y.erb +2 -2
- metadata +15 -2
- data/TODO.txt +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 775d49ffcf8f3320942f5d981dda023547aa9ec2
|
4
|
+
data.tar.gz: 968b178a6088323e13bd17bdd3391328c4e3430a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca6d1078b2cd885cf95ad022ecbb31e23764c188cbbce538a38bfe13c2d386d03210383133c51712da5d988dedede586a54f048855bf6114484edf521a7c1f66
|
7
|
+
data.tar.gz: c11e0370169c2052a032502dea255ff0581e97e64b72d18db3c430c7b7e47c20dd54889a51fb1ca8ba356732870d9a6b1e7b8b88468e92b67092e7d80319724f
|
data/README.md
CHANGED
@@ -16,9 +16,108 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install mkbison
|
18
18
|
|
19
|
-
|
19
|
+
You'll need to install [GNU Bison](https://www.gnu.org/software/bison/) as well, e.g.:
|
20
20
|
|
21
|
-
|
21
|
+
$ sudo apt-get install bison
|
22
|
+
|
23
|
+
## Usage and Example
|
24
|
+
|
25
|
+
The gem installs a command `mkbison` which translates `.rby` files into `.y` Bison grammar files, and generates a native ruby extension to expose the resulting parser.
|
26
|
+
|
27
|
+
`.rby` files contain a grammar definition and ruby code. Their syntax mostly mirrors that of Bison grammar files, with the following differences:
|
28
|
+
|
29
|
+
* Actions are written in ruby, rather than C (as is the lex section).
|
30
|
+
* Positional references to semantic values are not allowed.
|
31
|
+
* [Named references](http://www.gnu.org/software/bison/manual/html_node/Named-References.html) should not use a dollar sign `$`.
|
32
|
+
|
33
|
+
For example, here is a mkbison grammar for parsing very simple arithmetic expressions:
|
34
|
+
|
35
|
+
**arithmetic.rby**
|
36
|
+
```
|
37
|
+
%token NUMBER
|
38
|
+
|
39
|
+
%left OP_PLUS
|
40
|
+
%left OP_MINUS
|
41
|
+
|
42
|
+
%%
|
43
|
+
|
44
|
+
arithmetic:
|
45
|
+
expression[x]
|
46
|
+
{ self.result = x }
|
47
|
+
;
|
48
|
+
|
49
|
+
expression :
|
50
|
+
NUMBER
|
51
|
+
| addition
|
52
|
+
| subtraction
|
53
|
+
;
|
54
|
+
|
55
|
+
addition :
|
56
|
+
expression[left] OP_PLUS expression[right]
|
57
|
+
{ left + right }
|
58
|
+
;
|
59
|
+
|
60
|
+
subtraction :
|
61
|
+
expression[left] OP_MINUS expression[right]
|
62
|
+
{ left - right }
|
63
|
+
;
|
64
|
+
|
65
|
+
%%
|
66
|
+
|
67
|
+
class Arithmetic
|
68
|
+
def lex
|
69
|
+
# skip space
|
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
|
+
|
82
|
+
case c
|
83
|
+
when '0'..'9'
|
84
|
+
number = c
|
85
|
+
while (c = self.peak) && ('0'..'9').include?(c)
|
86
|
+
number << self.read
|
87
|
+
end
|
88
|
+
|
89
|
+
self.lex_value = number.to_i
|
90
|
+
return Tokens::NUMBER
|
91
|
+
|
92
|
+
when '+'
|
93
|
+
return Tokens::OP_PLUS
|
94
|
+
|
95
|
+
when '-'
|
96
|
+
return Tokens::OP_MINUS
|
97
|
+
end
|
98
|
+
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
To translate it into a Bison grammar file, run
|
105
|
+
|
106
|
+
$ bundle exec mkbison -n Arithmetic -o . arithmetic.rby
|
107
|
+
$ rake compile
|
108
|
+
|
109
|
+
This will generate and build a native extension named `arithmetic` in the current directory. A class named `Arithmetic` exposes the grammar parser. We can perform calculations now with `Arithmetic.new(expression).parse` which will return the result (or raise an exception if a syntax error is encountered).
|
110
|
+
|
111
|
+
## TODO
|
112
|
+
* 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
|
+
* Write to temp files, then move them into place
|
118
|
+
* Move base module into the c extension and document the lexing helpers
|
119
|
+
|
120
|
+
Not all Bison features are supported yet.
|
22
121
|
|
23
122
|
## Contributing
|
24
123
|
|
data/bin/mkbison
CHANGED
@@ -3,12 +3,15 @@
|
|
3
3
|
lib = File.expand_path('../../lib', __FILE__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
|
6
|
-
require 'bison'
|
7
6
|
require 'fileutils'
|
8
7
|
require 'tempfile'
|
9
8
|
require 'optparse'
|
10
9
|
require 'ostruct'
|
11
10
|
|
11
|
+
require 'cocaine'
|
12
|
+
|
13
|
+
require 'bison'
|
14
|
+
|
12
15
|
def underscore(name)
|
13
16
|
name.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
14
17
|
end
|
@@ -66,6 +69,14 @@ bison.print_class(ruby_file)
|
|
66
69
|
|
67
70
|
# Do a dry run
|
68
71
|
Tempfile.new('bison-output.c').tap do |output|
|
69
|
-
bison = ENV['BISON_PATH'] || 'bison'
|
70
|
-
|
72
|
+
bison = Cocaine::CommandLine.new(ENV['BISON_PATH'] || 'bison', '-o :out :in')
|
73
|
+
begin
|
74
|
+
bison.run(in: bison_file.path, out: output.path)
|
75
|
+
rescue Cocaine::CommandNotFoundError => e
|
76
|
+
warn("The bison command was not found on this system. " +
|
77
|
+
"Make sure to install it before attempting rake compile.")
|
78
|
+
rescue Cocaine::ExitStatusError => e
|
79
|
+
warn(e.message)
|
80
|
+
exit(1)
|
81
|
+
end
|
71
82
|
end
|
data/bison_parser.rby
CHANGED
@@ -39,14 +39,20 @@ token_list :
|
|
39
39
|
token:
|
40
40
|
HASH KW_TOKEN IDENTIFIER[name]
|
41
41
|
{ Bison::Token.new(name) }
|
42
|
-
|
|
42
|
+
| assoc_token
|
43
|
+
| token[token] NUMBER[num]
|
44
|
+
{ token.tap{ |t| t.number = num } }
|
45
|
+
;
|
46
|
+
|
47
|
+
assoc_token:
|
43
48
|
HASH KW_LEFT IDENTIFIER[name]
|
44
49
|
{ Bison::Token.new(name, :left) }
|
45
50
|
|
|
46
51
|
HASH KW_RIGHT IDENTIFIER[name]
|
47
52
|
{ Bison::Token.new(name, :right) }
|
48
|
-
|
|
49
|
-
|
53
|
+
|
|
54
|
+
assoc_token[token] IDENTIFIER[name]
|
55
|
+
{ token.tap{ |t| t.names << name } }
|
50
56
|
;
|
51
57
|
|
52
58
|
grammar_rules:
|
@@ -396,16 +396,16 @@ union yyalloc
|
|
396
396
|
/* YYFINAL -- State number of the termination state. */
|
397
397
|
#define YYFINAL 3
|
398
398
|
/* YYLAST -- Last index in YYTABLE. */
|
399
|
-
#define YYLAST
|
399
|
+
#define YYLAST 26
|
400
400
|
|
401
401
|
/* YYNTOKENS -- Number of terminals. */
|
402
402
|
#define YYNTOKENS 17
|
403
403
|
/* YYNNTS -- Number of nonterminals. */
|
404
|
-
#define YYNNTS
|
404
|
+
#define YYNNTS 10
|
405
405
|
/* YYNRULES -- Number of rules. */
|
406
|
-
#define YYNRULES
|
406
|
+
#define YYNRULES 22
|
407
407
|
/* YYNSTATES -- Number of states. */
|
408
|
-
#define YYNSTATES
|
408
|
+
#define YYNSTATES 33
|
409
409
|
|
410
410
|
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
|
411
411
|
by yylex, with out-of-bounds checking. */
|
@@ -453,9 +453,9 @@ static const yytype_uint8 yytranslate[] =
|
|
453
453
|
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
454
454
|
static const yytype_uint8 yyrline[] =
|
455
455
|
{
|
456
|
-
0, 37, 37, 50, 56, 67, 73, 84, 92,
|
457
|
-
|
458
|
-
|
456
|
+
0, 37, 37, 50, 56, 67, 73, 84, 92, 96,
|
457
|
+
107, 115, 123, 135, 141, 152, 164, 170, 178, 190,
|
458
|
+
196, 205, 214
|
459
459
|
};
|
460
460
|
#endif
|
461
461
|
|
@@ -467,8 +467,8 @@ static const char *const yytname[] =
|
|
467
467
|
"$end", "error", "$undefined", "IDENTIFIER", "NUMBER", "STRING",
|
468
468
|
"COLON", "SEMICOLON", "LBRACK", "RBRACK", "PIPE", "HASH", "DOUBLE_HASH",
|
469
469
|
"KW_TOKEN", "KW_LEFT", "KW_RIGHT", "ACTIONS", "$accept", "grammar_file",
|
470
|
-
"optional_code", "token_list", "token", "
|
471
|
-
"components", "sequence", YY_NULLPTR
|
470
|
+
"optional_code", "token_list", "token", "assoc_token", "grammar_rules",
|
471
|
+
"grammar_rule", "components", "sequence", YY_NULLPTR
|
472
472
|
};
|
473
473
|
#endif
|
474
474
|
|
@@ -487,7 +487,7 @@ static const yytype_uint16 yytoknum[] =
|
|
487
487
|
#define yypact_value_is_default(Yystate) \
|
488
488
|
(!!((Yystate) == (-8)))
|
489
489
|
|
490
|
-
#define YYTABLE_NINF -
|
490
|
+
#define YYTABLE_NINF -20
|
491
491
|
|
492
492
|
#define yytable_value_is_error(Yytable_value) \
|
493
493
|
0
|
@@ -497,9 +497,9 @@ static const yytype_uint16 yytoknum[] =
|
|
497
497
|
static const yytype_int8 yypact[] =
|
498
498
|
{
|
499
499
|
-8, 10, -7, -8, -6, -8, 8, 12, 13, 14,
|
500
|
-
-1, -8, -8, -8, -8,
|
501
|
-
-8, -4, -2, -8, -8,
|
502
|
-
-8
|
500
|
+
15, -1, -8, -8, -8, -8, -8, 16, 3, -8,
|
501
|
+
-8, -3, -8, -4, -2, -8, -8, 17, -8, -2,
|
502
|
+
18, 11, -8
|
503
503
|
};
|
504
504
|
|
505
505
|
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
|
@@ -507,22 +507,22 @@ static const yytype_int8 yypact[] =
|
|
507
507
|
means the default is an error. */
|
508
508
|
static const yytype_uint8 yydefact[] =
|
509
509
|
{
|
510
|
-
5, 0, 0, 1, 0,
|
511
|
-
3,
|
512
|
-
|
513
|
-
|
510
|
+
5, 0, 0, 1, 0, 13, 6, 8, 0, 0,
|
511
|
+
0, 3, 9, 12, 7, 10, 11, 0, 0, 2,
|
512
|
+
14, 16, 4, 0, 17, 15, 19, 21, 20, 18,
|
513
|
+
0, 0, 22
|
514
514
|
};
|
515
515
|
|
516
516
|
/* YYPGOTO[NTERM-NUM]. */
|
517
517
|
static const yytype_int8 yypgoto[] =
|
518
518
|
{
|
519
|
-
-8, -8, -8, -8, -8, -8, -8, -8, 0
|
519
|
+
-8, -8, -8, -8, -8, -8, -8, -8, -8, 0
|
520
520
|
};
|
521
521
|
|
522
522
|
/* YYDEFGOTO[NTERM-NUM]. */
|
523
523
|
static const yytype_int8 yydefgoto[] =
|
524
524
|
{
|
525
|
-
-1, 1,
|
525
|
+
-1, 1, 19, 2, 6, 7, 11, 20, 23, 24
|
526
526
|
};
|
527
527
|
|
528
528
|
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
|
@@ -530,42 +530,42 @@ static const yytype_int8 yydefgoto[] =
|
|
530
530
|
number is the opposite. If YYTABLE_NINF, syntax error. */
|
531
531
|
static const yytype_int8 yytable[] =
|
532
532
|
{
|
533
|
-
-
|
534
|
-
3,
|
535
|
-
|
533
|
+
-19, 27, 17, 25, 4, 5, 26, 8, 9, 10,
|
534
|
+
3, 18, 12, -19, 28, 13, 14, 15, 16, 22,
|
535
|
+
32, 31, 21, 0, 0, 30, 29
|
536
536
|
};
|
537
537
|
|
538
538
|
static const yytype_int8 yycheck[] =
|
539
539
|
{
|
540
540
|
3, 3, 3, 7, 11, 12, 10, 13, 14, 15,
|
541
|
-
0, 12, 4, 16, 16, 3, 3, 3, 16,
|
542
|
-
3, 6, -1, -1,
|
541
|
+
0, 12, 4, 16, 16, 3, 3, 3, 3, 16,
|
542
|
+
9, 3, 6, -1, -1, 8, 26
|
543
543
|
};
|
544
544
|
|
545
545
|
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
|
546
546
|
symbol of state STATE-NUM. */
|
547
547
|
static const yytype_uint8 yystos[] =
|
548
548
|
{
|
549
|
-
0, 18, 20, 0, 11, 12, 21, 13, 14,
|
550
|
-
|
551
|
-
|
552
|
-
9
|
549
|
+
0, 18, 20, 0, 11, 12, 21, 22, 13, 14,
|
550
|
+
15, 23, 4, 3, 3, 3, 3, 3, 12, 19,
|
551
|
+
24, 6, 16, 25, 26, 7, 10, 3, 16, 26,
|
552
|
+
8, 3, 9
|
553
553
|
};
|
554
554
|
|
555
555
|
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
|
556
556
|
static const yytype_uint8 yyr1[] =
|
557
557
|
{
|
558
558
|
0, 17, 18, 19, 19, 20, 20, 21, 21, 21,
|
559
|
-
|
560
|
-
|
559
|
+
22, 22, 22, 23, 23, 24, 25, 25, 25, 26,
|
560
|
+
26, 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
|
-
0, 2, 4, 0, 2, 0, 2, 3,
|
567
|
-
2, 0, 2, 4, 0, 1, 3, 0,
|
568
|
-
5
|
566
|
+
0, 2, 4, 0, 2, 0, 2, 3, 1, 2,
|
567
|
+
3, 3, 2, 0, 2, 4, 0, 1, 3, 0,
|
568
|
+
2, 2, 5
|
569
569
|
};
|
570
570
|
|
571
571
|
|
@@ -1405,129 +1405,146 @@ yyreduce:
|
|
1405
1405
|
|
1406
1406
|
case 8:
|
1407
1407
|
#line 93 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1408
|
+
{ (yyval) = (yyvsp[0]); }
|
1409
|
+
#line 1410 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1410
|
+
break;
|
1411
|
+
|
1412
|
+
case 9:
|
1413
|
+
#line 97 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1414
|
+
{
|
1415
|
+
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1416
|
+
rb_ivar_set(__actions, rb_intern("@token"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1417
|
+
rb_ivar_set(__actions, rb_intern("@num"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1418
|
+
(yyval) = rb_funcall(__actions, rb_intern("_2_token_445055bddb5840e621fa399faa56aefc"), 2, (yyvsp[-1]), (yyvsp[0]));
|
1419
|
+
}
|
1420
|
+
#line 1421 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1421
|
+
break;
|
1422
|
+
|
1423
|
+
case 10:
|
1424
|
+
#line 108 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1408
1425
|
{
|
1409
1426
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1410
1427
|
rb_ivar_set(__actions, rb_intern("@name"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1411
|
-
(yyval) = rb_funcall(__actions, rb_intern("
|
1428
|
+
(yyval) = rb_funcall(__actions, rb_intern("_0_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, (yyvsp[0]));
|
1412
1429
|
}
|
1413
|
-
#line
|
1430
|
+
#line 1431 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1414
1431
|
break;
|
1415
1432
|
|
1416
|
-
case
|
1417
|
-
#line
|
1433
|
+
case 11:
|
1434
|
+
#line 116 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1418
1435
|
{
|
1419
1436
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1420
1437
|
rb_ivar_set(__actions, rb_intern("@name"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1421
|
-
(yyval) = rb_funcall(__actions, rb_intern("
|
1438
|
+
(yyval) = rb_funcall(__actions, rb_intern("_1_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, (yyvsp[0]));
|
1422
1439
|
}
|
1423
|
-
#line
|
1440
|
+
#line 1441 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1424
1441
|
break;
|
1425
1442
|
|
1426
|
-
case
|
1427
|
-
#line
|
1443
|
+
case 12:
|
1444
|
+
#line 124 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1428
1445
|
{
|
1429
1446
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1430
1447
|
rb_ivar_set(__actions, rb_intern("@token"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1431
|
-
rb_ivar_set(__actions, rb_intern("@
|
1432
|
-
(yyval) = rb_funcall(__actions, rb_intern("
|
1448
|
+
rb_ivar_set(__actions, rb_intern("@name"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1449
|
+
(yyval) = rb_funcall(__actions, rb_intern("_2_assoc_token_1d82357deb6789321b86aa67cf1f1cf6"), 2, (yyvsp[-1]), (yyvsp[0]));
|
1433
1450
|
}
|
1434
|
-
#line
|
1451
|
+
#line 1452 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1435
1452
|
break;
|
1436
1453
|
|
1437
|
-
case
|
1438
|
-
#line
|
1454
|
+
case 13:
|
1455
|
+
#line 135 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1439
1456
|
{
|
1440
1457
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1441
1458
|
(yyval) = rb_funcall(__actions, rb_intern("_0_grammar_rules_99914b932bd37a50b983c5e7c90ae93b"), 0);
|
1442
1459
|
}
|
1443
|
-
#line
|
1460
|
+
#line 1461 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1444
1461
|
break;
|
1445
1462
|
|
1446
|
-
case
|
1447
|
-
#line
|
1463
|
+
case 14:
|
1464
|
+
#line 142 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1448
1465
|
{
|
1449
1466
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1450
1467
|
rb_ivar_set(__actions, rb_intern("@list"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1451
1468
|
rb_ivar_set(__actions, rb_intern("@rule"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1452
1469
|
(yyval) = rb_funcall(__actions, rb_intern("_1_grammar_rules_d4b402a4ddf06c5292ab917a96fe105c"), 2, (yyvsp[-1]), (yyvsp[0]));
|
1453
1470
|
}
|
1454
|
-
#line
|
1471
|
+
#line 1472 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1455
1472
|
break;
|
1456
1473
|
|
1457
|
-
case
|
1458
|
-
#line
|
1474
|
+
case 15:
|
1475
|
+
#line 153 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1459
1476
|
{
|
1460
1477
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1461
1478
|
rb_ivar_set(__actions, rb_intern("@name"), rb_ary_new3(2, INT2FIX((yylsp[-3]).first_line), INT2FIX((yylsp[-3]).first_column)));
|
1462
1479
|
rb_ivar_set(__actions, rb_intern("@components"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1463
1480
|
(yyval) = rb_funcall(__actions, rb_intern("_0_grammar_rule_bce7f6337f3284ba4a3537cc1d642c28"), 2, (yyvsp[-3]), (yyvsp[-1]));
|
1464
1481
|
}
|
1465
|
-
#line
|
1482
|
+
#line 1483 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1466
1483
|
break;
|
1467
1484
|
|
1468
|
-
case
|
1469
|
-
#line
|
1485
|
+
case 16:
|
1486
|
+
#line 164 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1470
1487
|
{
|
1471
1488
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1472
1489
|
(yyval) = rb_funcall(__actions, rb_intern("_0_components_99914b932bd37a50b983c5e7c90ae93b"), 0);
|
1473
1490
|
}
|
1474
|
-
#line
|
1491
|
+
#line 1492 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1475
1492
|
break;
|
1476
1493
|
|
1477
|
-
case
|
1478
|
-
#line
|
1494
|
+
case 17:
|
1495
|
+
#line 171 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1479
1496
|
{
|
1480
1497
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1481
1498
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1482
1499
|
(yyval) = rb_funcall(__actions, rb_intern("_1_components_2403a823f1a9854a29da7cf64f191fbe"), 1, (yyvsp[0]));
|
1483
1500
|
}
|
1484
|
-
#line
|
1501
|
+
#line 1502 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1485
1502
|
break;
|
1486
1503
|
|
1487
|
-
case
|
1488
|
-
#line
|
1504
|
+
case 18:
|
1505
|
+
#line 179 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1489
1506
|
{
|
1490
1507
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1491
1508
|
rb_ivar_set(__actions, rb_intern("@sequences"), rb_ary_new3(2, INT2FIX((yylsp[-2]).first_line), INT2FIX((yylsp[-2]).first_column)));
|
1492
1509
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1493
1510
|
(yyval) = rb_funcall(__actions, rb_intern("_2_components_62da044340939f02b6c0b52917617e17"), 2, (yyvsp[-2]), (yyvsp[0]));
|
1494
1511
|
}
|
1495
|
-
#line
|
1512
|
+
#line 1513 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1496
1513
|
break;
|
1497
1514
|
|
1498
|
-
case
|
1499
|
-
#line
|
1515
|
+
case 19:
|
1516
|
+
#line 190 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1500
1517
|
{
|
1501
1518
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1502
1519
|
(yyval) = rb_funcall(__actions, rb_intern("_0_sequence_99914b932bd37a50b983c5e7c90ae93b"), 0);
|
1503
1520
|
}
|
1504
|
-
#line
|
1521
|
+
#line 1522 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1505
1522
|
break;
|
1506
1523
|
|
1507
|
-
case
|
1508
|
-
#line
|
1524
|
+
case 20:
|
1525
|
+
#line 197 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1509
1526
|
{
|
1510
1527
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1511
1528
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1512
1529
|
rb_ivar_set(__actions, rb_intern("@code"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1513
1530
|
(yyval) = rb_funcall(__actions, rb_intern("_1_sequence_512ceffccf6bb7565046f90d6d7762ad"), 2, (yyvsp[-1]), (yyvsp[0]));
|
1514
1531
|
}
|
1515
|
-
#line
|
1532
|
+
#line 1533 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1516
1533
|
break;
|
1517
1534
|
|
1518
|
-
case
|
1519
|
-
#line
|
1535
|
+
case 21:
|
1536
|
+
#line 206 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1520
1537
|
{
|
1521
1538
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1522
1539
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1523
1540
|
rb_ivar_set(__actions, rb_intern("@follower"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
|
1524
1541
|
(yyval) = rb_funcall(__actions, rb_intern("_2_sequence_4b2903c3aeb37d22d413a53653d0df28"), 2, (yyvsp[-1]), (yyvsp[0]));
|
1525
1542
|
}
|
1526
|
-
#line
|
1543
|
+
#line 1544 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1527
1544
|
break;
|
1528
1545
|
|
1529
|
-
case
|
1530
|
-
#line
|
1546
|
+
case 22:
|
1547
|
+
#line 215 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
|
1531
1548
|
{
|
1532
1549
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX((yyloc).first_line), INT2FIX((yyloc).first_column)));
|
1533
1550
|
rb_ivar_set(__actions, rb_intern("@sequence"), rb_ary_new3(2, INT2FIX((yylsp[-4]).first_line), INT2FIX((yylsp[-4]).first_column)));
|
@@ -1535,11 +1552,11 @@ yyreduce:
|
|
1535
1552
|
rb_ivar_set(__actions, rb_intern("@tag"), rb_ary_new3(2, INT2FIX((yylsp[-1]).first_line), INT2FIX((yylsp[-1]).first_column)));
|
1536
1553
|
(yyval) = rb_funcall(__actions, rb_intern("_3_sequence_68f2380aa0f3a7de0fb9b3482705a54c"), 3, (yyvsp[-4]), (yyvsp[-3]), (yyvsp[-1]));
|
1537
1554
|
}
|
1538
|
-
#line
|
1555
|
+
#line 1556 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1539
1556
|
break;
|
1540
1557
|
|
1541
1558
|
|
1542
|
-
#line
|
1559
|
+
#line 1560 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
|
1543
1560
|
default: break;
|
1544
1561
|
}
|
1545
1562
|
/* User semantic actions sometimes alter yychar, and that requires
|
@@ -1774,7 +1791,7 @@ yyreturn:
|
|
1774
1791
|
#endif
|
1775
1792
|
return yyresult;
|
1776
1793
|
}
|
1777
|
-
#line
|
1794
|
+
#line 226 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1906 */
|
1778
1795
|
|
1779
1796
|
|
1780
1797
|
static VALUE cBisonParser;
|
@@ -89,11 +89,26 @@ token:
|
|
89
89
|
}
|
90
90
|
|
91
91
|
|
|
92
|
+
assoc_token
|
93
|
+
{ $$ = $1; }
|
94
|
+
|
95
|
+
|
|
96
|
+
token NUMBER
|
97
|
+
{
|
98
|
+
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX(@$.first_line), INT2FIX(@$.first_column)));
|
99
|
+
rb_ivar_set(__actions, rb_intern("@token"), rb_ary_new3(2, INT2FIX(@1.first_line), INT2FIX(@1.first_column)));
|
100
|
+
rb_ivar_set(__actions, rb_intern("@num"), rb_ary_new3(2, INT2FIX(@2.first_line), INT2FIX(@2.first_column)));
|
101
|
+
$$ = rb_funcall(__actions, rb_intern("_2_token_445055bddb5840e621fa399faa56aefc"), 2, $1, $2);
|
102
|
+
}
|
103
|
+
|
104
|
+
;
|
105
|
+
|
106
|
+
assoc_token:
|
92
107
|
HASH KW_LEFT IDENTIFIER
|
93
108
|
{
|
94
109
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX(@$.first_line), INT2FIX(@$.first_column)));
|
95
110
|
rb_ivar_set(__actions, rb_intern("@name"), rb_ary_new3(2, INT2FIX(@3.first_line), INT2FIX(@3.first_column)));
|
96
|
-
$$ = rb_funcall(__actions, rb_intern("
|
111
|
+
$$ = rb_funcall(__actions, rb_intern("_0_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, $3);
|
97
112
|
}
|
98
113
|
|
99
114
|
|
|
@@ -101,16 +116,16 @@ token:
|
|
101
116
|
{
|
102
117
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX(@$.first_line), INT2FIX(@$.first_column)));
|
103
118
|
rb_ivar_set(__actions, rb_intern("@name"), rb_ary_new3(2, INT2FIX(@3.first_line), INT2FIX(@3.first_column)));
|
104
|
-
$$ = rb_funcall(__actions, rb_intern("
|
119
|
+
$$ = rb_funcall(__actions, rb_intern("_1_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, $3);
|
105
120
|
}
|
106
121
|
|
107
122
|
|
|
108
|
-
|
123
|
+
assoc_token IDENTIFIER
|
109
124
|
{
|
110
125
|
rb_ivar_set(__actions, rb_intern("@_"), rb_ary_new3(2, INT2FIX(@$.first_line), INT2FIX(@$.first_column)));
|
111
126
|
rb_ivar_set(__actions, rb_intern("@token"), rb_ary_new3(2, INT2FIX(@1.first_line), INT2FIX(@1.first_column)));
|
112
|
-
rb_ivar_set(__actions, rb_intern("@
|
113
|
-
$$ = rb_funcall(__actions, rb_intern("
|
127
|
+
rb_ivar_set(__actions, rb_intern("@name"), rb_ary_new3(2, INT2FIX(@2.first_line), INT2FIX(@2.first_column)));
|
128
|
+
$$ = rb_funcall(__actions, rb_intern("_2_assoc_token_1d82357deb6789321b86aa67cf1f1cf6"), 2, $1, $2);
|
114
129
|
}
|
115
130
|
|
116
131
|
;
|
data/ext/bison_parser/extconf.rb
CHANGED
@@ -2,6 +2,8 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
output = "#{File.dirname(__FILE__)}/bison_parser.c"
|
4
4
|
bison_file = "#{File.dirname(__FILE__)}/bison_parser.y"
|
5
|
-
|
5
|
+
|
6
|
+
bison = find_executable(ENV['BISON_PATH'] || 'bison')
|
7
|
+
system(bison, '-o', output, bison_file) or abort("bison command failed")
|
6
8
|
|
7
9
|
create_makefile 'bison_parser/bison_parser'
|
data/lib/bison/grammar_file.rb
CHANGED
@@ -12,7 +12,7 @@ module Bison
|
|
12
12
|
|
13
13
|
def validate
|
14
14
|
errors = []
|
15
|
-
symbols = tokens.map(&:
|
15
|
+
symbols = tokens.map(&:names).flatten + rules.map(&:name)
|
16
16
|
rules.map(&:components).flatten.map(&:elements).flatten.each do |el|
|
17
17
|
unless !(Bison::Nonterminal === el) || symbols.include?(el.name)
|
18
18
|
errors << "#{el.location.join('.')}: #{el.name} is not defined"
|
data/lib/bison/token.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
module Bison
|
2
2
|
class Token
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :names
|
4
4
|
attr_accessor :number
|
5
5
|
attr_accessor :associativity
|
6
6
|
|
7
7
|
def initialize(name, assoc=nil)
|
8
|
-
self.
|
8
|
+
self.names = Array(name)
|
9
9
|
self.associativity = assoc
|
10
10
|
end
|
11
11
|
|
12
|
+
def name
|
13
|
+
names.join(' ')
|
14
|
+
end
|
15
|
+
|
12
16
|
def left?
|
13
17
|
associativity == :left
|
14
18
|
end
|
data/lib/bison/version.rb
CHANGED
data/lib/bison_parser/actions.rb
CHANGED
@@ -26,16 +26,20 @@ class BisonParser
|
|
26
26
|
Bison::Token.new(name)
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def _2_token_445055bddb5840e621fa399faa56aefc(token, num)
|
30
|
+
token.tap{ |t| t.number = num }
|
31
|
+
end
|
32
|
+
|
33
|
+
def _0_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3(name)
|
30
34
|
Bison::Token.new(name, :left)
|
31
35
|
end
|
32
36
|
|
33
|
-
def
|
37
|
+
def _1_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3(name)
|
34
38
|
Bison::Token.new(name, :right)
|
35
39
|
end
|
36
40
|
|
37
|
-
def
|
38
|
-
token.tap{ |t| t.
|
41
|
+
def _2_assoc_token_1d82357deb6789321b86aa67cf1f1cf6(token, name)
|
42
|
+
token.tap{ |t| t.names << name }
|
39
43
|
end
|
40
44
|
|
41
45
|
def _0_grammar_rules_99914b932bd37a50b983c5e7c90ae93b()
|
data/mkbison.gemspec
CHANGED
data/templates/extconf.rb.erb
CHANGED
@@ -3,7 +3,7 @@ require 'mkmf'
|
|
3
3
|
output = "#{File.dirname(__FILE__)}/<%= uname %>.c"
|
4
4
|
bison_file = "#{File.dirname(__FILE__)}/<%= uname %>.y"
|
5
5
|
|
6
|
-
bison = ENV['BISON_PATH'] || 'bison'
|
7
|
-
system(bison, '-o', output, bison_file)
|
6
|
+
bison = find_executable(ENV['BISON_PATH'] || 'bison')
|
7
|
+
system(bison, '-o', output, bison_file) or abort("bison command failed")
|
8
8
|
|
9
9
|
create_makefile '<%= uname %>/<%= uname %>'
|
data/templates/parser.y.erb
CHANGED
@@ -59,8 +59,8 @@ void Init_<%= uname %>(void) {
|
|
59
59
|
c<%= name %>Tokens = rb_define_module_under(c<%= name %>, "Tokens");
|
60
60
|
c<%= name %>Actions = rb_define_class_under(c<%= name %>, "Actions", rb_cObject);
|
61
61
|
|
62
|
-
<% tokens.each do |token| -%>
|
63
|
-
rb_define_const(c<%= name %>Tokens, "<%= token
|
62
|
+
<% tokens.map(&:names).flatten.each do |token| -%>
|
63
|
+
rb_define_const(c<%= name %>Tokens, "<%= token %>", INT2FIX(<%= token %>));
|
64
64
|
<% end -%>
|
65
65
|
|
66
66
|
rb_define_method(c<%= name %>, "parse", <%= uname %>_parse, 0);
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Woo
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: cocaine
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
description:
|
56
70
|
email:
|
57
71
|
- peter@wioux.net
|
@@ -66,7 +80,6 @@ files:
|
|
66
80
|
- LICENSE.txt
|
67
81
|
- README.md
|
68
82
|
- Rakefile
|
69
|
-
- TODO.txt
|
70
83
|
- bin/mkbison
|
71
84
|
- bison_parser.rby
|
72
85
|
- ext/bison_parser/bison_parser.c
|
data/TODO.txt
DELETED
@@ -1,5 +0,0 @@
|
|
1
|
-
* Seems like you can hit EOF in the middle of action block and get wrong error msg
|
2
|
-
* Benchmark -- what takes so long on koa?
|
3
|
-
* Support multiple tokens on %left/%right lines, for same precedence
|
4
|
-
* Write to temp file, then move into place
|
5
|
-
* Move base module into the c extension
|