summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2018-02-21 13:38:37 +0100
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2018-02-21 13:38:37 +0100
commit2c4aa50463ed411b14003f9d929c1e03518953bf (patch)
treedf950739c517127280aa1b301bb884470fe511de /lib
parent91a42a1a8f0d4bfc63e41b2f7b29a2b0fee1a60c (diff)
downloadgitlab-ce-2c4aa50463ed411b14003f9d929c1e03518953bf.tar.gz
Implement pipeline expressions parser
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme.rb4
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexer.rb3
-rw-r--r--lib/gitlab/ci/pipeline/expression/statement.rb33
-rw-r--r--lib/gitlab/ci/pipeline/expression/string.rb1
-rw-r--r--lib/gitlab/ci/pipeline/expression/token.rb5
-rw-r--r--lib/gitlab/ci/pipeline/expression/variable.rb8
6 files changed, 49 insertions, 5 deletions
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme.rb b/lib/gitlab/ci/pipeline/expression/lexeme.rb
index bbf3fec7407..91ba333d8dd 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme.rb
@@ -7,6 +7,10 @@ module Gitlab
raise NotImplementedError
end
+ def self.build(token)
+ raise NotImplementedError
+ end
+
def self.scan(scanner)
if scanner.scan(self::PATTERN)
Expression::Token.new(scanner.matched, self)
diff --git a/lib/gitlab/ci/pipeline/expression/lexer.rb b/lib/gitlab/ci/pipeline/expression/lexer.rb
index 8432b36b066..ee202ebce69 100644
--- a/lib/gitlab/ci/pipeline/expression/lexer.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexer.rb
@@ -5,7 +5,8 @@ module Gitlab
class Lexer
LEXEMES = [
Expression::Variable,
- Expression::String
+ Expression::String,
+ Expression::Equals
]
MAX_CYCLES = 5
diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb
index 91d91195f5a..417b3f806b1 100644
--- a/lib/gitlab/ci/pipeline/expression/statement.rb
+++ b/lib/gitlab/ci/pipeline/expression/statement.rb
@@ -3,6 +3,8 @@ module Gitlab
module Pipeline
module Expression
class Statement
+ ParserError = Class.new(StandardError)
+
GRAMMAR = [
%w[variable equals string],
%w[variable equals variable],
@@ -12,14 +14,41 @@ module Gitlab
%w[variable]
]
- def initialize(pipeline, statement)
+ def initialize(statement, pipeline)
@pipeline = pipeline
- @statement = statement
+ @lexer = Expression::Lexer.new(statement)
end
def variables
end
+ def tokens
+ @lexer.tokenize
+ end
+
+ def lexemes
+ @lexemes ||= tokens.map(&:to_lexeme)
+ end
+
+ ##
+ # Our syntax is very simple, so we don't need yet to implement a
+ # recurisive parser, we can use the most simple approach to create
+ # a reverse descent parse tree "by hand".
+ #
+ def parse_tree
+ raise ParserError if lexemes.empty?
+
+ unless GRAMMAR.find { |syntax| syntax == lexemes }
+ raise ParserError, 'Unknown pipeline expression!'
+ end
+
+ if lexemes.many?
+ Expression::Equals.new(tokens.first.build, tokens.last.build)
+ else
+ tokens.first.build
+ end
+ end
+
def evaluate
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/string.rb b/lib/gitlab/ci/pipeline/expression/string.rb
index e6cc50c56d8..6a59b81467c 100644
--- a/lib/gitlab/ci/pipeline/expression/string.rb
+++ b/lib/gitlab/ci/pipeline/expression/string.rb
@@ -14,6 +14,7 @@ module Gitlab
end
def self.build(string)
+ new(string.match(PATTERN)[:string])
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/token.rb b/lib/gitlab/ci/pipeline/expression/token.rb
index 03a47a17d40..3b957c83016 100644
--- a/lib/gitlab/ci/pipeline/expression/token.rb
+++ b/lib/gitlab/ci/pipeline/expression/token.rb
@@ -10,7 +10,12 @@ module Gitlab
@type = type
end
+ def build
+ @type.build(@value)
+ end
+
def to_lexeme
+ type.name.demodulize.downcase
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/variable.rb b/lib/gitlab/ci/pipeline/expression/variable.rb
index ec6c03d336a..d6a7a655220 100644
--- a/lib/gitlab/ci/pipeline/expression/variable.rb
+++ b/lib/gitlab/ci/pipeline/expression/variable.rb
@@ -5,12 +5,16 @@ module Gitlab
class Variable < Expression::Lexeme
PATTERN = /\$(?<name>\w+)/.freeze
- def initialize(value)
- @value = value
+ def initialize(name)
+ @name = name
end
def evaluate(**variables)
end
+
+ def self.build(string)
+ new(string.match(PATTERN)[:name])
+ end
end
end
end