Commit 92912147 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Parser now only parses JavaScript structure.

The results of DocComment and JavaScript parsing are merged together in
top-level parse method.
parent 0e8d85e0
Loading
Loading
Loading
Loading
+31 −1
Original line number Diff line number Diff line
@@ -9,7 +9,37 @@ require 'pp'

module JsDuck
  def JsDuck.parse(input)
    Parser.new(input).parse
    doc_parser = DocCommentParser.new
    documentation = []

    Parser.new(input).parse.each do |docset|
      # Parsing of doc-block may result in several doc-comment
      # objects. Only the first one of these gets augmented with
      # information inferred from the code that follows doc-block.
      comments = doc_parser.parse(docset[:comment]).map { |d| DocComment.new(d) }
      comments.each { |c| documentation << c }
      doc = comments[0]
      code = docset[:code]

      if code[:type] == :function then
        doc.set_default_name(*code[:name]) if code[:name]
        doc.set_default_params(code[:params])
      elsif code[:type] == :assignment then
        doc.set_default_name(*code[:left])
        if code[:right] then
          right = code[:right]
          if right[:type] == :function then
            doc.set_default_params(right[:params])
          elsif right[:type] == :ext_extend then
            doc.set_default_extends(right[:extend])
          elsif right[:type] == :literal then
            doc.set_default_type(right[:class])
          end
        end
      end
    end

    documentation
  end
end

+37 −25
Original line number Diff line number Diff line
@@ -4,37 +4,49 @@ module JsDuck
  class Parser
    def initialize(input)
      @lex = Lexer.new(input)
      @doc_parser = DocCommentParser.new
      @docs = []
    end

    # Parses the whole JavaScript block and returns array where for
    # each doc-comment there is a hash of two values: the comment
    # itself as string and parsed structure of the code that
    # immediately follows the comment.
    #
    # For example with the following JavaScript input:
    #
    # /**
    #  * @param {String} foo
    #  */
    # MyClass.doIt = function(foo, bar) {
    # }
    #
    # The return value of this function will be:
    #
    # [
    #   {
    #     :comment => "/**\n * @param {String} foo\n */",
    #     :code => {
    #       :type => :assignment,
    #       :left => ["MyClass", "doIt"],
    #       :right => {
    #         :type => :function,
    #         :name => nil,
    #         :params => [
    #           {:name => "foo"},
    #           {:name => "bar"}
    #         ]
    #       }
    #     }
    #   }
    # ]
    #
    def parse
      while !@lex.empty? do
        if look(:doc_comment) then
          # Parsing of doc-block may result in several doc-comment
          # objects. Only the first one of these gets augmented with
          # information inferred from the code that follows doc-block.
          docset = @doc_parser.parse(match(:doc_comment)).map { |d| DocComment.new(d) }
          docset.each { |d| @docs << d }
          doc = docset[0]

          block = code_block
          if block[:type] == :function then
            doc.set_default_name(*block[:name]) if block[:name]
            doc.set_default_params(block[:params])
          elsif block[:type] == :assignment then
            doc.set_default_name(*block[:left])
            if block[:right] then
              right = block[:right]
              if right[:type] == :function then
                doc.set_default_params(right[:params])
              elsif right[:type] == :ext_extend then
                doc.set_default_extends(right[:extend])
              elsif right[:type] == :literal then
                doc.set_default_type(right[:class])
              end
            end
          end
          @docs << {
            :comment => match(:doc_comment),
            :code => code_block
          }
        else
          @lex.next
        end