Module: LangScan::Shell

Defined in:
lib/langscan/sh.rb,
ext/langscan/sh/sh/sh.c

Defined Under Namespace

Classes: Tokenizer

Constant Summary collapse

Keywords =
%w(
  case do done elif else esac fi for function if in select then until
  while time
)
ShBuiltinCommands =
%w(
  break cd continue eval exec exit export getopts hash pwd readonly
  return shift test times trap umask unset
)
BashBuiltinCommands =
%w(
  alias bind builtin caller command declare echo enable help let
  local logout printf read shopt set source type typeset ulimit unalias
)
KeywordsHash =
{}

Class Method Summary collapse

Class Method Details

.abbrevObject



22
23
24
# File 'lib/langscan/sh.rb', line 22

def abbrev
  "sh"
end

.each_fragment(input) ⇒ Object

LangScan::Shell.each_fragment iterates over shell script fragments in input. The fragments contains tokens and inter-token spaces and comments.

If a String is specified, the String itself is assumed as a shell script. If a IO is specified, the content of the IO is assumed as a shell script.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/langscan/sh.rb', line 77

def each_fragment(input) # :yields: token
  begin
    tokenizer = Tokenizer.new(input)
    while token_info = tokenizer.get_token
      type, text, beg_lineno, beg_columnno, beg_byteno, end_lineno, end_columnno, end_byteno = token_info
      token = Fragment.new(type, text, beg_lineno, beg_byteno)
      if token.type == :ident
        if KeywordsHash[token.text]
          token.type = :keyword 
        end
      end

      yield token
    end
  ensure
    tokenizer.close
  end
end

.extnamesObject



26
27
28
# File 'lib/langscan/sh.rb', line 26

def extnames
  [".sh"]
end

.nameObject



18
19
20
# File 'lib/langscan/sh.rb', line 18

def name
  "shell script"
end

.scan(input, &block) ⇒ Object

LangScan::Shell.scan iterates over shell scripts. It yields for each Fragment.



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
# File 'lib/langscan/sh.rb', line 32

def scan(input, &block)
  last_token = nil
  each_fragment(input) {|t|
    if t.type == :ident
      if t.text[0] == ?$
        yield Fragment.new(:punct, '$', t.beg_lineno, t.beg_byteno)
        yield Fragment.new(:ident, t.text[1 .. -1], t.beg_lineno,
                           t.beg_byteno + 1)
        last_token = nil
        next
      end

      if last_token != nil && last_token.type == :keyword && last_token.text == "function"
        t.type = :fundef
      end
    end

    if t.type == :heredoc_end
      blank_len = t.text.rindex(/\s/)
      if blank_len == nil
        yield Fragment.new(:ident, t.text, t.beg_lineno, t.beg_byteno)
      else
        yield Fragment.new(:space, t.text[0 .. blank_len],
                           t.beg_lineno, t.beg_byteno)
        yield Fragment.new(:ident, t.text[blank_len+1 .. -1],
                           t.beg_lineno, t.beg_byteno+blank_len+1)
      end
      next
    end

    t.type = :ident if t.type == :heredoc_beg

    yield t

    if t.type != :space && t.type != :comment
      last_token = t
    end
  }
end