mkbison 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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