aboutsummaryrefslogtreecommitdiffstats
path: root/tool/lrama/lib/lrama/grammar/symbol.rb
blob: 39e5218d5369a2946e786ac3ac46ee5788ebab63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Symbol is both of nterm and term
# `number` is both for nterm and term
# `token_id` is tokentype for term, internal sequence number for nterm
#
# TODO: Add validation for ASCII code range for Token::Char

module Lrama
  class Grammar
    class Symbol < Struct.new(:id, :alias_name, :number, :tag, :term, :token_id, :nullable, :precedence, :printer, :error_token, keyword_init: true)
      attr_accessor :first_set, :first_set_bitmap
      attr_writer :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol

      def term?
        term
      end

      def nterm?
        !term
      end

      def eof_symbol?
        !!@eof_symbol
      end

      def error_symbol?
        !!@error_symbol
      end

      def undef_symbol?
        !!@undef_symbol
      end

      def accept_symbol?
        !!@accept_symbol
      end

      def display_name
        alias_name || id.s_value
      end

      # name for yysymbol_kind_t
      #
      # See: b4_symbol_kind_base
      def enum_name
        case
        when accept_symbol?
          name = "YYACCEPT"
        when eof_symbol?
          name = "YYEOF"
        when term? && id.is_a?(Lrama::Lexer::Token::Char)
          name = number.to_s + display_name
        when term? && id.is_a?(Lrama::Lexer::Token::Ident)
          name = id.s_value
        when nterm? && (id.s_value.include?("$") || id.s_value.include?("@"))
          name = number.to_s + id.s_value
        when nterm?
          name = id.s_value
        else
          raise "Unexpected #{self}"
        end

        "YYSYMBOL_" + name.gsub(/\W+/, "_")
      end

      # comment for yysymbol_kind_t
      def comment
        case
        when accept_symbol?
          # YYSYMBOL_YYACCEPT
          id.s_value
        when eof_symbol?
          # YYEOF
          alias_name
        when (term? && 0 < token_id && token_id < 128)
          # YYSYMBOL_3_backslash_, YYSYMBOL_14_
          alias_name || id.s_value
        when id.s_value.include?("$") || id.s_value.include?("@")
          # YYSYMBOL_21_1
          id.s_value
        else
          # YYSYMBOL_keyword_class, YYSYMBOL_strings_1
          alias_name || id.s_value
        end
      end
    end
  end
end