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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 71a987a62e2d5a4ff59028f97bbb5d3f58d2c8f2
4
- data.tar.gz: b5780f28d873a785a96dc0ad3b444158409bed52
3
+ metadata.gz: 775d49ffcf8f3320942f5d981dda023547aa9ec2
4
+ data.tar.gz: 968b178a6088323e13bd17bdd3391328c4e3430a
5
5
  SHA512:
6
- metadata.gz: 909d99dfc14789d8ffbbf7a2396e82f085f85448cd87ca75b8efa6e3fb779a4c317e1928a9a499e5d9f191c494e3f99206afcf94bada2022f57d93840d883a87
7
- data.tar.gz: 47033ca52ad47487545b17d405fa2615c86a9c9ebdc5cff36ef14d4e739518490ae6c0be7035ea73881c0295c425862bee7f94f397a1717f5ea7485c7d7da656
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
- ## Usage
19
+ You'll need to install [GNU Bison](https://www.gnu.org/software/bison/) as well, e.g.:
20
20
 
21
- TODO: Write usage instructions here
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
 
@@ -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
- system(bison, '-o', output.path, bison_file.path)
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
@@ -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
- | token[token] NUMBER[num]
49
- { token.tap{ |t| t.number = num } }
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 25
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 9
404
+ #define YYNNTS 10
405
405
  /* YYNRULES -- Number of rules. */
406
- #define YYNRULES 20
406
+ #define YYNRULES 22
407
407
  /* YYNSTATES -- Number of states. */
408
- #define YYNSTATES 31
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, 100,
457
- 108, 120, 126, 137, 149, 155, 163, 175, 181, 190,
458
- 199
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", "grammar_rules", "grammar_rule",
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 -18
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, 15, 2, -8, -8, -3,
501
- -8, -4, -2, -8, -8, 11, -8, -2, 17, 16,
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, 11, 6, 0, 0, 0,
511
- 3, 10, 7, 8, 9, 0, 0, 2, 12, 14,
512
- 4, 0, 15, 13, 17, 19, 18, 16, 0, 0,
513
- 20
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, 17, 2, 6, 10, 18, 21, 22
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
- -17, 25, 15, 23, 4, 5, 24, 7, 8, 9,
534
- 3, 16, 11, -17, 26, 12, 13, 14, 20, 28,
535
- 29, 19, 0, 0, 27, 30
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, 8,
542
- 3, 6, -1, -1, 24, 9
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, 15,
550
- 22, 4, 3, 3, 3, 3, 12, 19, 23, 6,
551
- 16, 24, 25, 7, 10, 3, 16, 25, 8, 3,
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
- 21, 22, 22, 23, 24, 24, 24, 25, 25, 25,
560
- 25
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, 3, 3,
567
- 2, 0, 2, 4, 0, 1, 3, 0, 2, 2,
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("_1_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, (yyvsp[0]));
1428
+ (yyval) = rb_funcall(__actions, rb_intern("_0_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, (yyvsp[0]));
1412
1429
  }
1413
- #line 1414 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1430
+ #line 1431 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1414
1431
  break;
1415
1432
 
1416
- case 9:
1417
- #line 101 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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("_2_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, (yyvsp[0]));
1438
+ (yyval) = rb_funcall(__actions, rb_intern("_1_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, (yyvsp[0]));
1422
1439
  }
1423
- #line 1424 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1440
+ #line 1441 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1424
1441
  break;
1425
1442
 
1426
- case 10:
1427
- #line 109 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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("@num"), rb_ary_new3(2, INT2FIX((yylsp[0]).first_line), INT2FIX((yylsp[0]).first_column)));
1432
- (yyval) = rb_funcall(__actions, rb_intern("_3_token_445055bddb5840e621fa399faa56aefc"), 2, (yyvsp[-1]), (yyvsp[0]));
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 1435 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1451
+ #line 1452 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1435
1452
  break;
1436
1453
 
1437
- case 11:
1438
- #line 120 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1444 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1460
+ #line 1461 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1444
1461
  break;
1445
1462
 
1446
- case 12:
1447
- #line 127 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1455 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1471
+ #line 1472 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1455
1472
  break;
1456
1473
 
1457
- case 13:
1458
- #line 138 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1466 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1482
+ #line 1483 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1466
1483
  break;
1467
1484
 
1468
- case 14:
1469
- #line 149 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1475 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1491
+ #line 1492 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1475
1492
  break;
1476
1493
 
1477
- case 15:
1478
- #line 156 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1485 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1501
+ #line 1502 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1485
1502
  break;
1486
1503
 
1487
- case 16:
1488
- #line 164 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1496 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1512
+ #line 1513 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1496
1513
  break;
1497
1514
 
1498
- case 17:
1499
- #line 175 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1505 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1521
+ #line 1522 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1505
1522
  break;
1506
1523
 
1507
- case 18:
1508
- #line 182 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1516 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1532
+ #line 1533 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1516
1533
  break;
1517
1534
 
1518
- case 19:
1519
- #line 191 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1527 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1543
+ #line 1544 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1527
1544
  break;
1528
1545
 
1529
- case 20:
1530
- #line 200 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1661 */
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 1539 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1555
+ #line 1556 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
1539
1556
  break;
1540
1557
 
1541
1558
 
1542
- #line 1543 "../../../../ext/bison_parser/bison_parser.c" /* yacc.c:1661 */
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 211 "../../../../ext/bison_parser/bison_parser.y" /* yacc.c:1906 */
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("_1_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, $3);
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("_2_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, $3);
119
+ $$ = rb_funcall(__actions, rb_intern("_1_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3"), 1, $3);
105
120
  }
106
121
 
107
122
  |
108
- token NUMBER
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("@num"), rb_ary_new3(2, INT2FIX(@2.first_line), INT2FIX(@2.first_column)));
113
- $$ = rb_funcall(__actions, rb_intern("_3_token_445055bddb5840e621fa399faa56aefc"), 2, $1, $2);
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
  ;
@@ -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
- system('bison', '-o', output, bison_file)
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'
@@ -12,7 +12,7 @@ module Bison
12
12
 
13
13
  def validate
14
14
  errors = []
15
- symbols = tokens.map(&:name) + rules.map(&:name)
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"
@@ -1,14 +1,18 @@
1
1
  module Bison
2
2
  class Token
3
- attr_accessor :name
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.name = name
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
@@ -1,3 +1,3 @@
1
1
  module Bison
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -26,16 +26,20 @@ class BisonParser
26
26
  Bison::Token.new(name)
27
27
  end
28
28
 
29
- def _1_token_f014c38ad08ecac5d62c0e3fa23163b3(name)
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 _2_token_f014c38ad08ecac5d62c0e3fa23163b3(name)
37
+ def _1_assoc_token_f014c38ad08ecac5d62c0e3fa23163b3(name)
34
38
  Bison::Token.new(name, :right)
35
39
  end
36
40
 
37
- def _3_token_445055bddb5840e621fa399faa56aefc(token, num)
38
- token.tap{ |t| t.number = num }
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()
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rake-compiler"
24
+ spec.add_development_dependency "cocaine"
24
25
  end
@@ -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 %>'
@@ -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.name %>", INT2FIX(<%= token.name %>));
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.2
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