Module: RemLint::Classifier

Defined in:
lib/remlint/command.rb

Overview

Splits a logical line into its opening keyword and the rest.

Deliberately shallow: Remind's grammar is loose enough that a full parse would be a second implementation of Remind, and wrong in different places than the first. Rules that need to look inside args reach for ExprLexer; rules that only care which command this is stop here.

Constant Summary collapse

COMMENT =
/\A\s*[#;]/
BLANK =
/\A\s*\z/m
WORD =
/\A\s*(\S+)/

Class Method Summary collapse

Class Method Details

.all(logical_lines) ⇒ Object



98
99
100
# File 'lib/remlint/command.rb', line 98

def all(logical_lines)
  logical_lines.map { |logical_line| call(logical_line) }
end

.bare(logical_line, kind) ⇒ Object



122
123
124
125
126
127
128
129
130
# File 'lib/remlint/command.rb', line 122

def bare(logical_line, kind)
  Command.new(
    keyword:      nil,
    word:         nil,
    args:         logical_line.text,
    logical_line: logical_line,
    kind:         kind,
  )
end

.call(logical_line) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/remlint/command.rb', line 86

def call(logical_line)
  text = logical_line.text

  if text.match?(BLANK)
    bare(logical_line, :blank)
  elsif text.match?(COMMENT)
    bare(logical_line, :comment)
  else
    classify_code(logical_line, text)
  end
end

.classify_code(logical_line, text) ⇒ Object

A line opening with a clause keyword -- a month, a weekday, an ordinal -- is a trigger with the REM left off, not a command named JANUARY. It gets kind: :implicit like a line opening with a bare day number, and keeps its whole text as args, because the clause is part of the trigger rather than something the command takes.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/remlint/command.rb', line 107

def classify_code(logical_line, text)
  match = text.match(WORD)
  word = match[1]
  keyword = Vocabulary.keyword(word)
  commands = !keyword.nil? && !keyword.clause?

  Command.new(
    keyword:      keyword,
    word:         word,
    args:         commands ? match.post_match.sub(/\A[ \t]+/, "") : text.sub(/\A\s*/, ""),
    logical_line: logical_line,
    kind:         commands ? :keyword : :implicit,
  )
end