The lexer maintains a stack of last seen comments.
Each AST nodes has a doc property that is filled with the
last seen comments on node creation (in fact only on important node
creation representing statements).

Signed-off-by: Brice Figureau <[EMAIL PROTECTED]>
---
 lib/puppet/parser/ast.rb            |    2 +
 lib/puppet/parser/grammar.ra        |   50 ++++---
 lib/puppet/parser/lexer.rb          |   42 ++++++-
 lib/puppet/parser/parser.rb         |  256 ++++++++++++++++++-----------------
 lib/puppet/parser/parser_support.rb |   16 ++-
 5 files changed, 212 insertions(+), 154 deletions(-)

diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index ddf8852..ede3842 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -12,6 +12,8 @@ class Puppet::Parser::AST
 
     include Puppet::Util::Errors
     include Puppet::Util::MethodHelper
+    include Puppet::Util::Docs
+
     attr_accessor :line, :file, :parent, :scope
 
     # Does this ast object set something?  If so, it gets evaluated first.
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
index 23c2934..d01ab61 100644
--- a/lib/puppet/parser/grammar.ra
+++ b/lib/puppet/parser/grammar.ra
@@ -77,26 +77,28 @@ fstatement:   NAME LPAREN funcvalues RPAREN {
     result = ast AST::Function,
         :name => val[0],
         :arguments => args,
-        :ftype => :statement
+        :ftype => :statement,
+        :doc => @lexer.getcomment
 }
  | NAME LPAREN funcvalues COMMA RPAREN {
     args = aryfy(val[2])
     result = ast AST::Function,
         :name => val[0],
         :arguments => args,
-        :ftype => :statement
+        :ftype => :statement,
+        :doc => @lexer.getcomment
 }            | NAME LPAREN RPAREN {
     result = ast AST::Function,
         :name => val[0],
         :arguments => AST::ASTArray.new({}),
-        :ftype => :statement
+        :ftype => :statement, :doc => @lexer.getcomment
 }
             | NAME funcvalues {
     args = aryfy(val[1])
     result = ast AST::Function,
         :name => val[0],
         :arguments => args,
-        :ftype => :statement
+        :ftype => :statement, :doc => @lexer.getcomment
 }
 
 funcvalues:       namestring
@@ -146,19 +148,19 @@ resource:       classname LBRACE resourceinstances 
endsemi RBRACE {
         result.push ast(AST::Resource,
             :type => val[0],
             :title => instance[0],
-            :params => instance[1])
+            :params => instance[1], :doc => @lexer.getcomment)
     }
 }           | classname LBRACE params endcomma RBRACE {
     # This is a deprecated syntax.
     error "All resource specifications require names"
 }           | classref LBRACE params endcomma RBRACE {
     # a defaults setting for a type
-    result = ast(AST::ResourceDefaults, :type => val[0], :params => val[2])
+    result = ast(AST::ResourceDefaults, :type => val[0], :params => val[2], 
:doc => @lexer.getcomment)
 }
 
 # Override a value set elsewhere in the configuration.
 resourceoverride:     resourceref LBRACE anyparams endcomma RBRACE {
-    result = ast AST::ResourceOverride, :object => val[0], :params => val[2]
+    result = ast AST::ResourceOverride, :object => val[0], :params => val[2], 
:doc => @lexer.getcomment
 }
 
 # Exported and virtual resources; these don't get sent to the client
@@ -198,7 +200,7 @@ collection:     classref collectrhand {
         Puppet.warning addcontext("Collection names must now be capitalized")
     end
     type = val[0].downcase
-    args = {:type => type}
+    args = {:type => type, :doc => @lexer.getcomment }
 
     if val[1].is_a?(AST::CollExpr)
         args[:query] = val[1]
@@ -303,12 +305,12 @@ assignment:     VARIABLE EQUALS expression {
     end
     # this is distinct from referencing a variable
     variable = ast AST::Name, :value => val[0]
-    result = ast AST::VarDef, :name => variable, :value => val[2]
+    result = ast AST::VarDef, :name => variable, :value => val[2], :doc => 
@lexer.getcomment
 }
 
 append:     VARIABLE APPENDS expression {
     variable = ast AST::Name, :value => val[0]
-    result = ast AST::VarDef, :name => variable, :value => val[2], :append => 
true
+    result = ast AST::VarDef, :name => variable, :value => val[2], :append => 
true, :doc => @lexer.getcomment
 }
 
 params:   # nothing
@@ -412,7 +414,8 @@ resourceref: NAME LBRACK rvalues RBRACK {
 ifstatement:      IF expression LBRACE statements RBRACE else {
     args = {
         :test => val[1],
-        :statements => val[3]
+        :statements => val[3],
+        :doc => @lexer.getcomment
     }
 
     if val[5]
@@ -424,7 +427,8 @@ ifstatement:      IF expression LBRACE statements RBRACE 
else {
                 | IF expression LBRACE RBRACE else {
     args = {
         :test => val[1],
-        :statements => ast(AST::Nop)
+        :statements => ast(AST::Nop),
+        :doc => @lexer.getcomment
     }
 
     if val[4]
@@ -436,10 +440,10 @@ ifstatement:      IF expression LBRACE statements RBRACE 
else {
 
 else:             # nothing
                 | ELSE LBRACE statements RBRACE {
-    result = ast AST::Else, :statements => val[2]
+    result = ast AST::Else, :statements => val[2], :doc => @lexer.getcomment
 }
                 | ELSE LBRACE RBRACE {
-    result = ast AST::Else, :statements => ast(AST::Nop)
+    result = ast AST::Else, :statements => ast(AST::Nop), :doc => 
@lexer.getcomment
 }
 
 # Unlike yacc/bison, it seems racc
@@ -512,7 +516,7 @@ casestatement:  CASE rvalue LBRACE caseopts RBRACE {
     unless options.instance_of?(AST::ASTArray)
         options = ast AST::ASTArray, :children => [val[3]]
     end
-    result = ast AST::CaseStatement, :test => val[1], :options => options
+    result = ast AST::CaseStatement, :test => val[1], :options => options, 
:doc => @lexer.getcomment
 }
 
 caseopts:     caseopt
@@ -545,7 +549,7 @@ casevalues:       selectlhand
 }
 
 selector:     selectlhand QMARK svalues {
-    result = ast AST::Selector, :param => val[0], :values => val[2]
+    result = ast AST::Selector, :param => val[0], :values => val[2], :doc => 
@lexer.getcomment
 }
 
 svalues:      selectval
@@ -587,19 +591,19 @@ import: IMPORT qtexts {
         import(file)
     end
 
-    result = AST::ASTArray.new(:children => [])
+    result = AST::ASTArray.new(:children => [], :doc => @lexer.getcomment)
 }
 
 # Disable definition inheritance for now. 8/27/06, luke
 #definition: DEFINE NAME argumentlist parent LBRACE statements RBRACE {
 definition: DEFINE classname argumentlist LBRACE statements RBRACE {
-    newdefine classname(val[1]), :arguments => val[2], :code => val[4]
+    newdefine classname(val[1]), :arguments => val[2], :code => val[4], :doc 
=> @lexer.getcomment
     @lexer.indefine = false
     result = nil
 
 #}           | DEFINE NAME argumentlist parent LBRACE RBRACE {
 }           | DEFINE classname argumentlist LBRACE RBRACE {
-    newdefine classname(val[1]), :arguments => val[2]
+    newdefine classname(val[1]), :arguments => val[2], :doc => 
@lexer.getcomment
     @lexer.indefine = false
     result = nil
 }
@@ -608,20 +612,20 @@ definition: DEFINE classname argumentlist LBRACE 
statements RBRACE {
 hostclass: CLASS classname classparent LBRACE statements RBRACE {
     # Our class gets defined in the parent namespace, not our own.
     @lexer.namepop
-    newclass classname(val[1]), :code => val[4], :parent => val[2]
+    newclass classname(val[1]), :code => val[4], :parent => val[2], :doc => 
@lexer.getcomment
     result = nil
 }           | CLASS classname classparent LBRACE RBRACE {
     # Our class gets defined in the parent namespace, not our own.
     @lexer.namepop
-    newclass classname(val[1]), :parent => val[2]
+    newclass classname(val[1]), :parent => val[2], :doc => @lexer.getcomment
     result = nil
 }
 
 nodedef: NODE hostnames nodeparent LBRACE statements RBRACE {
-    newnode val[1], :parent => val[2], :code => val[4]
+    newnode val[1], :parent => val[2], :code => val[4], :doc => 
@lexer.getcomment
     result = nil
 }       |  NODE hostnames nodeparent LBRACE RBRACE {
-    newnode val[1], :parent => val[2]
+    newnode val[1], :parent => val[2], :doc => @lexer.getcomment
     result = nil
 }
 
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index 9226434..4ff2d25 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -17,7 +17,7 @@ class Puppet::Parser::Lexer
 
     # Our base token class.
     class Token
-        attr_accessor :regex, :name, :string, :skip, :incr_line, :skip_text
+        attr_accessor :regex, :name, :string, :skip, :incr_line, :skip_text, 
:accumulate
 
         def initialize(regex, name)
             if regex.is_a?(String)
@@ -32,6 +32,10 @@ class Puppet::Parser::Lexer
             self.skip
         end
 
+        def accumulate?
+            self.accumulate
+        end
+
         def to_s
             if self.string
                 @string
@@ -155,7 +159,10 @@ class Puppet::Parser::Lexer
         [string_token, value]
     end
 
-    TOKENS.add_token :COMMENT, %r{#.*}, :skip => true
+    TOKENS.add_token :COMMENT, %r{#.*}, :accumulate => true, :skip => true do 
|lexer,value|
+        value.sub!('#','')
+        [self, value]
+    end
 
     TOKENS.add_token :RETURN, "\n", :skip => true, :incr_line => true, 
:skip_text => true
 
@@ -320,6 +327,7 @@ class Puppet::Parser::Lexer
         @namestack = []
         @indefine = false
         @expected = []
+        @commentstack = ['']
     end
 
     # Make any necessary changes to the token and/or value.
@@ -328,12 +336,18 @@ class Puppet::Parser::Lexer
 
         skip() if token.skip_text
 
-        return if token.skip
+        return if token.skip and not token.accumulate?
 
         token, value = token.convert(self, value) if 
token.respond_to?(:convert)
 
         return unless token
 
+        if token.accumulate?
+            @commentstack.last << value+"\n"
+        end
+
+        return if token.skip
+
         return token, value
     end
 
@@ -388,6 +402,13 @@ class Puppet::Parser::Lexer
 
             next unless final_token
 
+            # push comments on block change
+            if final_token.name == :LBRACE
+                commentpush('')
+            elsif final_token.name == :RBRACE
+                commentpop
+            end
+
             if match = @@pairs[value] and final_token.name != :DQUOTE and 
final_token.name != :SQUOTE
                 @expected << match
             elsif exp = @expected[-1] and exp == value and final_token.name != 
:DQUOTE and final_token.name != :SQUOTE
@@ -448,4 +469,19 @@ class Puppet::Parser::Lexer
     def string=(string)
         @scanner = StringScanner.new(string)
     end
+
+    # returns the content of the currently accumulated content cache
+    def commentpop
+        return @commentstack.pop
+    end
+
+    def getcomment
+        comment = @commentstack.pop
+        @commentstack.push('')
+        return comment
+    end
+
+    def commentpush(value)
+        @commentstack.push(value)
+    end
 end
-- 
1.6.0.2


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to