Class Kwartz::CssStyleParser
In: kwartz/parser.rb
Parent: PresentationLogicParser

css style presentation logic parser

example of presentation logic in css style:

  /* comment */
  #idname, .classname, tagname {
    value:   @var;
    attrs:   "class" @classname, "bgcolro" color;
    append:  @value==item['list'] ? ' checked' : '';
    logic:   {
      @list.each { |item|
        _stag
        _cont
        _etag
      }
    }
  }

Methods

Constants

CSSSTYLE_KEYWORDS = { 'begin'=>:begin, 'end'=>:end }

Attributes

mode  [RW] 

Public Class methods

[Source]

# File kwartz/parser.rb, line 605
    def initialize(*args)
      super
      @mode = :selector           # :selector or :declaration
    end

Public Instance methods

[Source]

# File kwartz/parser.rb, line 613
    def parse(input, filename='')
      reset(input, filename)
      scan()
      rulesets = []
      while @token == :command     # '@import'
        command = @value
        case command
        when '@import'
          imported_rulesets = parse_import_command()
          rulesets += imported_rulesets
        when '@from'
          # TODO
        when '@import_pdata'
          # TODO
        else
          raise parse_error("#{command}: unsupported command.")
        end
      end
      while @token == :selector
        selectors = parse_selectors()
        unless @token == '{''{'
          raise parse_error("'#{@value}': '{' is expected.")  #'
        end
        @mode = :declaration
        _linenum, _column = @linenum, @column
        ruleset = Ruleset.new(selectors)
        parse_declaration(ruleset)
        unless @token
          raise parse_error("'#{selectors.first}': is not closed by '}'.", _linenum, _column)
        end
        @mode = :selector
        rulesets << ruleset
        scan()
      end
      unless @token == nil
        raise parse_error("'#{@value}': selector is expected.")
      end
      return rulesets
    end

Protected Instance methods

[Source]

# File kwartz/parser.rb, line 741
    def has_colon?
      unless @ch == ?:
        raise parse_error("'#{@value}': ':' is required.")
      end
      getch()
    end

[Source]

# File kwartz/parser.rb, line 735
    def keywords(keyword)
      return CSSSTYLE_KEYWORDS[keyword]
    end

[Source]

# File kwartz/parser.rb, line 766
    def parse_declaration(ruleset)
      assert unless @token == '{''{'
      while true
        scan()
        flag_escape = escape?(@value)
        case @token
        when nil     ;  break
        when '}''}'    ;  break
        when :stag   ;  has_colon?();  ruleset.set_stag    _parse_expr() , flag_escape
        when :cont   ;  has_colon?();  ruleset.set_cont    _parse_expr() , flag_escape
        when :etag   ;  has_colon?();  ruleset.set_etag    _parse_expr() , flag_escape
        when :elem   ;  has_colon?();  ruleset.set_elem    _parse_expr() , flag_escape
        when :value  ;  has_colon?();  ruleset.set_value   _parse_expr() , flag_escape
        when :attrs  ;  has_colon?();  ruleset.set_attrs   _parse_pairs(), flag_escape
        when :append ;  has_colon?();  ruleset.set_append  _parse_exprs(), flag_escape
        when :remove ;  has_colon?();  ruleset.set_remove  _parse_strs()
        when :tagname;  has_colon?();  ruleset.set_tagname _parse_str()
        when :logic  ;  has_colon?();  ruleset.set_logic   _parse_block()
        when :before ;  has_colon?();  ruleset.set_before  _parse_block()
        when :after  ;  has_colon?();  ruleset.set_after   _parse_block()
        when :begin  ;  has_colon?();  ruleset.set_before  _parse_block()
        when :end    ;  has_colon?();  ruleset.set_after   _parse_block()
        else
          raise parse_error("'#{@value}': unexpected token.")  #'
        end
      end
      return ruleset
    end

[Source]

# File kwartz/parser.rb, line 796
    def parse_import_command
      c = @ch
      c = getch() while is_whitespace(c)
      t = scan_string()
      t == :string  or raise parse_error("@import: requires filename.")
      filename = @value
      if @filename && !@filename.empty?
        dir = File.dirname(@filename)
        filename = dir + '/' + filename if dir != '.'
      end
      test(?f, filename)  or raise parse_error("'#{filename}': import file not found.")
      _linenum, _column = @linenum, @column
      c = @ch
      c = getch() while is_whitespace(c)
      c == ?; or raise parse_error("';' required.")
      c = getch()
      scan()
      parser = self.class.new(@properties)
      begin
        ruleset_list = parser.parse(File.read(filename), filename)
      rescue => ex
        parse_error(ex.message, _linenum, _column)
      end
      return ruleset_list
    end

[Source]

# File kwartz/parser.rb, line 749
    def parse_selectors
      assert unless @token == :selector
      start_linenum = @linenum
      selectors = [ @value ]
      scan()
      while @token == ','','
        scan()
        unless @token == :selector
          raise parse_error("'#{@value}': selector is expected (or additional comma exists).") #'
        end
        selectors << @value
        scan()
      end
      return selectors
    end

return false when not hooked

[Source]

# File kwartz/parser.rb, line 658
    def scan_hook
      ## comment
      c = @ch
      if c == ?/
        c = getch()
        if c == ?/      # line comment
          scan_line()
          getch()
          return scan()
        elsif c == ?*   # region comment
          start_linenum = @linenum
          while true
            c = getch() while c != ?*
            break if c == nil
            c = getch()
            break if c == ?/
          end
          if c == nil
            @error = :comment_unclosed
            @value = start_linenum
            return @token == :error
          end
          getch()
          return scan()
        else
          @value = '/'
          return @token = ?/
        end #if
      end #if

      ##
      if @mode == :selector
        # '#name' or '.name'
        if c == ?# || c == ?.
          start_char = c
          name = ''
          while is_identchar(c = getch()) || c == ?-
            name << c
          end
          if name.empty?
            @error = :invalid_char
            @value = start_char.chr
            return @token = :error
          end
          @value = start_char.chr + name
          return @token = :selector
        end
        # 'tagname'
        if is_identchar(c) || c == ?-
          name = c.chr
          while is_identchar(c = getch()) || c == ?- || c == ?:
            name << c
          end
          @value = name
          return @token = :selector
        end
        # '@import'
        if c == ?@
          name = ''
          while is_identchar(c = getch())
            name << c
          end
          if name.empty?
            @error = :invalid_char
            @value = '@'
            return @token = :error
          end
          @value = '@' + name
          return @token = :command
        end
      end

      return false

    end

[Validate]