Module: MilkTea::Parse::Recovery

Included in:
MilkTea::Parser
Defined in:
lib/milk_tea/core/parser/recovery.rb

Constant Summary collapse

TOP_LEVEL_RECOVERY_START_TYPES =
%i[
  module import at public attribute const var type struct union enum flags variant interface
  opaque extending foreign async function event external static_assert link include compiler_flag
].freeze

Instance Method Summary collapse

Instance Method Details

#recover_match_arm_blockObject



75
76
77
78
79
80
81
# File 'lib/milk_tea/core/parser/recovery.rb', line 75

def recover_match_arm_block
  advance if check(:indent)

  arms = parse_match_arm_body([])
  advance if check(:dedent)
  arms
end

#recover_statement_block_bodyObject



67
68
69
70
71
72
73
# File 'lib/milk_tea/core/parser/recovery.rb', line 67

def recover_statement_block_body
  advance if check(:indent)

  statements = parse_statement_block_body
  advance if check(:dedent)
  statements
end

#recovery_error_block_stmt(error, body, header_type: nil, header_expression: nil, header_bindings: nil, header_iterables: nil) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/milk_tea/core/parser/recovery.rb', line 103

def recovery_error_block_stmt(error, body, header_type: nil, header_expression: nil, header_bindings: nil, header_iterables: nil)
  token = error.token
  AST::ErrorBlockStmt.new(
    body:,
    line: token&.line,
    column: token&.column,
    length: token&.lexeme&.length,
    message: error.message,
    header_type:,
    header_expression:,
    header_bindings:,
    header_iterables:,
  )
end

#recovery_error_expr(error) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/milk_tea/core/parser/recovery.rb', line 83

def recovery_error_expr(error)
  token = error.token
  AST::ErrorExpr.new(
    line: token&.line,
    column: token&.column,
    length: token&.lexeme&.length,
    message: error.message,
  )
end

#recovery_error_stmt(error) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/milk_tea/core/parser/recovery.rb', line 93

def recovery_error_stmt(error)
  token = error.token
  AST::ErrorStmt.new(
    line: token&.line,
    column: token&.column,
    length: token&.lexeme&.length,
    message: error.message,
  )
end

#recovery_statement_header_type(error) ⇒ Object



118
119
120
121
122
# File 'lib/milk_tea/core/parser/recovery.rb', line 118

def recovery_statement_header_type(error)
  return :unsafe if previous&.type == :unsafe && error.message.include?("after unsafe")

  nil
end

#synchronize_to_match_arm_boundaryObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/milk_tea/core/parser/recovery.rb', line 51

def synchronize_to_match_arm_boundary
  until eof?
    return nil if check(:dedent)

    if check(:newline)
      advance
      return recover_match_arm_block if check(:indent)
      return nil
    end

    advance
  end

  nil
end

#synchronize_to_statement_boundaryObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/milk_tea/core/parser/recovery.rb', line 34

def synchronize_to_statement_boundary
  until eof?
    return recover_statement_block_body if check(:indent)
    return nil if check(:dedent)

    if check(:newline)
      advance
      return recover_statement_block_body if check(:indent)
      return nil
    end

    advance
  end

  nil
end

#synchronize_to_top_level_boundaryObject



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/milk_tea/core/parser/recovery.rb', line 11

def synchronize_to_top_level_boundary
  seen_newline = false

  until eof?
    token = peek

    if token.type == :newline
      seen_newline = true
      advance
      next
    end

    if %i[indent dedent].include?(token.type)
      advance
      next
    end

    break if seen_newline && top_level_recovery_start?(token)

    advance
  end
end

#top_level_recovery_start?(token) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/milk_tea/core/parser/recovery.rb', line 124

def top_level_recovery_start?(token)
  token.column.to_i <= 1 && (TOP_LEVEL_RECOVERY_START_TYPES.include?(token.type) || builtin_attribute_identifier?(token))
end