• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

type-ruby / t-ruby / 20560723383

28 Dec 2025 10:58PM UTC coverage: 79.074% (+1.7%) from 77.331%
20560723383

Pull #29

github

web-flow
Merge 5876e651d into fda099366
Pull Request #29: refactor: migrate parser from regex to token-based parser combinator

1848 of 2097 new or added lines in 53 files covered. (88.13%)

6 existing lines in 2 files now uncovered.

6643 of 8401 relevant lines covered (79.07%)

908.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.14
/lib/t_ruby/parser_combinator/declaration_parser.rb
1
# frozen_string_literal: true
2

3
module TRuby
1✔
4
  module ParserCombinator
1✔
5
    # Declaration Parser - Parse T-Ruby declarations
6
    class DeclarationParser
1✔
7
      include DSL
1✔
8

9
      def initialize
1✔
10
        @type_parser = TypeParser.new
7✔
11
        build_parsers
7✔
12
      end
13

14
      def parse(input)
1✔
15
        result = @declaration.parse(input.strip)
5✔
16
        if result.success?
5✔
17
          { success: true, declarations: result.value }
5✔
18
        else
NEW
19
          { success: false, error: result.error, position: result.position }
×
20
        end
21
      end
22

23
      def parse_file(input)
1✔
24
        result = @program.parse(input)
2✔
25
        if result.success?
2✔
26
          { success: true, declarations: result.value.compact }
2✔
27
        else
NEW
28
          { success: false, error: result.error, position: result.position }
×
29
        end
30
      end
31

32
      private
1✔
33

34
      def build_parsers
1✔
35
        # Type expression (delegate to TypeParser)
36
        lazy { parse_type_inline }
7✔
37

38
        # Keywords
39
        kw_type = lexeme(string("type"))
7✔
40
        kw_interface = lexeme(string("interface"))
7✔
41
        kw_def = lexeme(string("def"))
7✔
42
        kw_end = lexeme(string("end"))
7✔
43
        lexeme(string("class"))
7✔
44
        lexeme(string("module"))
7✔
45

46
        # Type alias: type Name = Definition
47
        type_alias = (
48
          kw_type >>
7✔
49
          lexeme(identifier) <<
50
          lexeme(char("=")) >>
51
          regex(/[^\n]+/).map(&:strip)
52
        ).map do |((_, name), definition)|
53
          type_result = @type_parser.parse(definition)
6✔
54
          if type_result[:success]
6✔
55
            IR::TypeAlias.new(name: name, definition: type_result[:type])
6✔
56
          end
57
        end
58

59
        # Interface member: name: Type
60
        interface_member = (
61
          lexeme(identifier) <<
7✔
62
          lexeme(char(":")) >>
63
          regex(/[^\n]+/).map(&:strip)
64
        ).map do |(name, type_str)|
NEW
65
          type_result = @type_parser.parse(type_str)
×
NEW
66
          if type_result[:success]
×
NEW
67
            IR::InterfaceMember.new(name: name, type_signature: type_result[:type])
×
68
          end
69
        end
70

71
        # Interface: interface Name ... end
72
        interface_body = (interface_member << (newline | spaces)).many
7✔
73

74
        interface_decl = (
75
          kw_interface >>
7✔
76
          lexeme(identifier) <<
77
          (newline | spaces) >>
7✔
78
          interface_body <<
79
          kw_end
80
        ).map do |((_, name), members)|
NEW
81
          IR::Interface.new(name: name, members: members.compact)
×
82
        end
83

84
        # Parameter: name: Type or name
85
        param = (
86
          identifier >>
7✔
87
          (lexeme(char(":")) >> regex(/[^,)]+/).map(&:strip)).optional
7✔
88
        ).map do |(name, type_str)|
89
          type_node = if type_str
5✔
90
                        type_str_val = type_str.is_a?(Array) ? type_str.last : type_str
5✔
91
                        result = @type_parser.parse(type_str_val)
5✔
92
                        result[:success] ? result[:type] : nil
5✔
93
                      end
94
          IR::Parameter.new(name: name, type_annotation: type_node)
5✔
95
        end
96

97
        # Parameters list
98
        params_list = (
99
          lexeme(char("(")) >>
7✔
100
          param.sep_by(lexeme(char(","))) <<
101
          lexeme(char(")"))
102
        ).map { |(_, params)| params }
4✔
103

104
        # Return type annotation
105
        return_type = (
106
          lexeme(char(":")) >>
7✔
107
          regex(/[^\n]+/).map(&:strip)
108
        ).map { |(_, type_str)| type_str }.optional
3✔
109

110
        # Method definition: def name(params): ReturnType
111
        method_def = (
112
          kw_def >>
7✔
113
          identifier >>
114
          params_list.optional >>
115
          return_type
116
        ).map do |(((_, name), params), ret_str)|
117
          ret_type = if ret_str
4✔
118
                       result = @type_parser.parse(ret_str)
3✔
119
                       result[:success] ? result[:type] : nil
3✔
120
                     end
121
          IR::MethodDef.new(
4✔
122
            name: name,
123
            params: params || [],
124
            return_type: ret_type
125
          )
126
        end
127

128
        # Any declaration
129
        @declaration = choice(
7✔
130
          type_alias,
131
          interface_decl,
132
          method_def
133
        )
134

135
        # Line (declaration or empty)
136
        line = (@declaration << (newline | eof)) | (spaces >> newline).map { nil }
7✔
137

138
        # Program (multiple declarations)
139
        @program = line.many
7✔
140
      end
141

142
      def parse_type_inline
1✔
NEW
143
        Lazy.new { @type_parser.instance_variable_get(:@type_expr) }
×
144
      end
145
    end
146
  end
147
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc