class CrossPlane::Lexer

Constants

EXTERNAL_LEXERS
NEWLINE

Attributes

filename[RW]

Public Class Methods

new(*args) click to toggle source
# File lib/crossplane/lexer.rb, line 13
def initialize(*args)
        args = args[0] || {}

        required = ['filename']
        conflicts = []
        requires = {}
        valid = {
                'params' => [
                        'filename',
                ]
        }

        content = CrossPlane.utils.validate_constructor(client: self, args: args, required: required, conflicts: conflicts, requires: requires, valid: valid)
        self.filename = content[:filename]
end

Public Instance Methods

lex(*args) click to toggle source
# File lib/crossplane/lexer.rb, line 29
def lex(*args)
        tokens = _lex_file()
        _balance_braces(tokens)
        tokens
end

Private Instance Methods

_balance_braces(tokens) { |token, line| ... } click to toggle source
# File lib/crossplane/lexer.rb, line 130
def _balance_braces(tokens)
        depth = 0

        for token, line in tokens
                if token == '}'
                        depth = depth -1
                elsif token == '{'
                        depth = depth + 1
                end

                if depth < 0
                        reason = 'unexpected "}"'
                        raise CrossPlane::NgxParserSyntaxError.new(self.filename, line, reason)
                else
                        yield token, line if block_given?
                end
        end

        if depth > 0
                reason = 'unexpected end of file, expecting "}"'
                raise CrossPlane::NgxParserSyntaxError.new(self.filename, line, reason)
        end
end
_lex_file(*args) click to toggle source
# File lib/crossplane/lexer.rb, line 36
def _lex_file(*args)
        token = ''  # the token buffer
        next_token_is_directive = true
        
        enum = Enumerator.new do |y|
                File.open(self.filename, 'r') { |f|
                        f.each do |line|
                                lineno = $.
                                line.split('').each do |char|
                                        y.yield [char, lineno]
                                end
                        end
                }
        end

        tokens = []
        begin
                while tuple = enum.next
                        char, line = tuple
                        if CrossPlane.utils.isspace(char)
                                if not token.empty?
                                        tokens.push([token, line])
                                        if next_token_is_directive and EXTERNAL_LEXERS[token]
                                                next_token_is_directive = true
                                        else
                                                next_token_is_directive = false
                                        end
                                end

                                while CrossPlane.utils.isspace(char)
                                        char, line = enum.next
                                end

                                token = ''
                        end

                        # if starting comment
                        if token.empty? and char == '#'
                                while not char.end_with?(NEWLINE)
                                        token = token + char
                                        char, _ = enum.next
                                end
                                tokens.push([token, line])
                                token = ''
                                next
                        end

                        # handle parameter expansion syntax (ex: "${var[@]}")
                        if token and token[-1] == '$' and char == '{'
                                next_token_is_directive = false
                                while token[-1] != '}' and not CrossPlane.utils.isspace(char)
                                        token += char
                                        char, line = enum.next
                                end
                        end

                        # if a quote is found, add the whole string to the token buffer
                        if ['"', "'"].include?(char)
                                if not token.empty?
                                        token = token + char
                                        next
                                end
                                quote = char
                                char, line = enum.next
                                while char != quote
                                        if char == '\\' + quote
                                                token = token + quote
                                        else
                                                token = token + char
                                        end
                                        char, line = enum.next
                                end

                                tokens.push([token, line])
                                token = ''
                                next
                        end

                        if ['{', '}', ';'].include?(char)
                                if not token.empty?
                                        tokens.push([token, line])
                                        token = ''
                                end
                                tokens.push([char, line]) if char.length > 0
                                next_token_is_directive = true
                                next
                        end
                        token = token + char
                end
        rescue StopIteration
        end
        tokens
end