Commit 1858fd1

mo khan <mo@mokhan.ca>
2021-05-09 19:38:11
[wip] parse arguments
1 parent 10c6d26
Changed files (2)
lib
spandx
terraform
parsers
spec
unit
terraform
lib/spandx/terraform/parsers/hcl.rb
@@ -4,24 +4,28 @@ module Spandx
   module Terraform
     module Parsers
       class Hcl < Parslet::Parser
-        rule(:anything) { match('.').repeat }
         rule(:alpha) { match['a-zA-Z'] }
         rule(:assign) { str('=') }
         rule(:crlf) { match('[\r\n]') }
         rule(:digit) { match('\d') }
         rule(:dot) { str('.') }
         rule(:eol) { whitespace? >> crlf.repeat }
+        rule(:hyphen) { str('-') }
         rule(:lcurly) { str('{') }
+        rule(:major) { number }
+        rule(:major_minor) { (number >> dot >> number) }
+        rule(:major_minor_patch) { number >> dot >> number >> dot >> number }
         rule(:number) { digit.repeat }
+        rule(:pre_release) { hyphen >> (alpha | digit).repeat }
+        rule(:pre_release?) { pre_release.maybe }
         rule(:quote) { str('"') }
         rule(:rcurly) { str('}') }
         rule(:space) { match('\s') }
-        rule(:pre_release) { hyphen >> (alpha | digit).repeat }
-        rule(:pre_release?) { pre_release.maybe }
+        rule(:tilda_wacka) { str("~>") }
         rule(:version) { number >> dot >> number >> dot >> number >> pre_release? }
         rule(:whitespace) { space.repeat }
         rule(:whitespace?) { whitespace.maybe }
-        rule(:hyphen) { str('-') }
+        rule(:greater_than_or_equal_to) { str('>=') }
 
         rule :attribute_name do
           alpha.repeat
@@ -35,29 +39,55 @@ module Spandx
           match('[0-9A-Za-z.~> ]')
         end
 
+        rule(:version_constraint) do
+          pessimistic_version_constraint | greater_than_or_equal_to_version
+        end
+
         rule :version_assignment do
-          whitespace? >> str('version') >> whitespace >> assign >> whitespace >> quote >> version.as(:version) >> quote
+          str('version') >> whitespace >> assign >> whitespace >> quote >> version.as(:version) >> quote
+        end
+
+        rule :constraint_assignment do
+          str("constraints") >> whitespace >> assign >> whitespace >> quote >> version_constraint.as(:constraints) >> quote
+        end
+
+        rule(:pessimistic_version_constraint) do
+          tilda_wacka >> whitespace >> (
+            major_minor_patch |
+            major_minor |
+            major
+          )
         end
 
-        rule :constraints do
-          anything
+        rule(:greater_than_or_equal_to_version) do
+          greater_than_or_equal_to >> whitespace >> (
+            major_minor_patch |
+            major_minor |
+            major
+          )
         end
 
-        rule :hashes do
-          anything
+        rule :argument do
+          (
+            str('version') |
+            str('constraints')
+          ).as(:argument) >> whitespace >> assign >> whitespace >> quote >> (
+            version |
+            version_constraint
+          ).as(:value) >> quote
         end
 
-        rule :assignments do
-          # (version_assignment | constraints | hashes).repeat
-          version_assignment >> eol
+        rule :arguments do
+          #((version_assignment | constraint_assignment) >> eol).repeat
+          (argument >> eol).repeat
         end
 
         rule :block do
-          whitespace >> lcurly >> eol >> assignments >> rcurly >> eol
+          whitespace >> lcurly >> eol >> arguments >> rcurly >> eol
         end
 
         rule :identifier do
-          whitespace >> quote >> match('[a-zA-Z./]').repeat.as(:name) >> quote >> whitespace
+          whitespace >> quote >> ((alpha | match('[./]')).repeat).as(:name) >> quote >> whitespace
         end
 
         rule :provider do
spec/unit/terraform/parsers/hcl_spec.rb
@@ -11,13 +11,18 @@ RSpec.describe Spandx::Terraform::Parsers::Hcl do
         <<~HCL
           provider "registry.terraform.io/hashicorp/aws" {
             version     = "3.39.0"
+            constraints = "~> 3.27"
           }
         HCL
       end
 
       specify { expect(subject[0].dig(:provider, :name).to_s).to eql('registry.terraform.io/hashicorp/aws') }
-      specify { expect(subject[0].dig(:provider, :version).to_s).to eql('3.39.0') }
+      specify { expect(subject[1].dig(:provider, :version).to_s).to eql('3.39.0') }
+      specify { expect(subject[2].dig(:provider, :constraints).to_s).to eql('~> 3.27') }
       specify { expect(subject).to be_truthy }
+      specify do
+        puts subject
+      end
     end
   end
 
@@ -53,6 +58,34 @@ RSpec.describe Spandx::Terraform::Parsers::Hcl do
     end
   end
 
+  describe '#constraint_assignment' do
+    subject { parser.constraint_assignment }
+
+    [
+      'constraints = ">= 3"',
+      'constraints = ">= 3.27"',
+      'constraints = ">= 3.27.0"',
+      'constraints = "~> 3"',
+      'constraints = "~> 3.27"',
+      'constraints = "~> 3.27.0"',
+    ].each do |raw|
+      specify { expect(subject).to parse(raw) }
+    end
+  end
+
+  describe '#version_constraint' do
+    [
+      '~> 3',
+      '~> 3.27',
+      '~> 3.27.0',
+      '>= 1.2.0',
+      '>= 1.20',
+      '>= 10',
+    ].each do |raw|
+      specify { expect(parser.version_constraint).to parse(raw) }
+    end
+  end
+
   (('a'..'z').to_a + ('A'..'Z').to_a).each do |letter|
     specify { expect(parser.alpha).to parse(letter) }
   end