Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
2c4aa504
Commit
2c4aa504
authored
Feb 21, 2018
by
Grzegorz Bizon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement pipeline expressions parser
parent
91a42a1a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
94 additions
and
5 deletions
+94
-5
lib/gitlab/ci/pipeline/expression/lexeme.rb
lib/gitlab/ci/pipeline/expression/lexeme.rb
+4
-0
lib/gitlab/ci/pipeline/expression/lexer.rb
lib/gitlab/ci/pipeline/expression/lexer.rb
+2
-1
lib/gitlab/ci/pipeline/expression/statement.rb
lib/gitlab/ci/pipeline/expression/statement.rb
+31
-2
lib/gitlab/ci/pipeline/expression/string.rb
lib/gitlab/ci/pipeline/expression/string.rb
+1
-0
lib/gitlab/ci/pipeline/expression/token.rb
lib/gitlab/ci/pipeline/expression/token.rb
+5
-0
lib/gitlab/ci/pipeline/expression/variable.rb
lib/gitlab/ci/pipeline/expression/variable.rb
+6
-2
spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
+9
-0
spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
+36
-0
No files found.
lib/gitlab/ci/pipeline/expression/lexeme.rb
View file @
2c4aa504
...
@@ -7,6 +7,10 @@ module Gitlab
...
@@ -7,6 +7,10 @@ module Gitlab
raise
NotImplementedError
raise
NotImplementedError
end
end
def
self
.
build
(
token
)
raise
NotImplementedError
end
def
self
.
scan
(
scanner
)
def
self
.
scan
(
scanner
)
if
scanner
.
scan
(
self
::
PATTERN
)
if
scanner
.
scan
(
self
::
PATTERN
)
Expression
::
Token
.
new
(
scanner
.
matched
,
self
)
Expression
::
Token
.
new
(
scanner
.
matched
,
self
)
...
...
lib/gitlab/ci/pipeline/expression/lexer.rb
View file @
2c4aa504
...
@@ -5,7 +5,8 @@ module Gitlab
...
@@ -5,7 +5,8 @@ module Gitlab
class
Lexer
class
Lexer
LEXEMES
=
[
LEXEMES
=
[
Expression
::
Variable
,
Expression
::
Variable
,
Expression
::
String
Expression
::
String
,
Expression
::
Equals
]
]
MAX_CYCLES
=
5
MAX_CYCLES
=
5
...
...
lib/gitlab/ci/pipeline/expression/statement.rb
View file @
2c4aa504
...
@@ -3,6 +3,8 @@ module Gitlab
...
@@ -3,6 +3,8 @@ module Gitlab
module
Pipeline
module
Pipeline
module
Expression
module
Expression
class
Statement
class
Statement
ParserError
=
Class
.
new
(
StandardError
)
GRAMMAR
=
[
GRAMMAR
=
[
%w[variable equals string]
,
%w[variable equals string]
,
%w[variable equals variable]
,
%w[variable equals variable]
,
...
@@ -12,14 +14,41 @@ module Gitlab
...
@@ -12,14 +14,41 @@ module Gitlab
%w[variable]
%w[variable]
]
]
def
initialize
(
pipeline
,
statement
)
def
initialize
(
statement
,
pipeline
)
@pipeline
=
pipeline
@pipeline
=
pipeline
@
statement
=
statement
@
lexer
=
Expression
::
Lexer
.
new
(
statement
)
end
end
def
variables
def
variables
end
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
def
evaluate
end
end
end
end
...
...
lib/gitlab/ci/pipeline/expression/string.rb
View file @
2c4aa504
...
@@ -14,6 +14,7 @@ module Gitlab
...
@@ -14,6 +14,7 @@ module Gitlab
end
end
def
self
.
build
(
string
)
def
self
.
build
(
string
)
new
(
string
.
match
(
PATTERN
)[
:string
])
end
end
end
end
end
end
...
...
lib/gitlab/ci/pipeline/expression/token.rb
View file @
2c4aa504
...
@@ -10,7 +10,12 @@ module Gitlab
...
@@ -10,7 +10,12 @@ module Gitlab
@type
=
type
@type
=
type
end
end
def
build
@type
.
build
(
@value
)
end
def
to_lexeme
def
to_lexeme
type
.
name
.
demodulize
.
downcase
end
end
end
end
end
end
...
...
lib/gitlab/ci/pipeline/expression/variable.rb
View file @
2c4aa504
...
@@ -5,12 +5,16 @@ module Gitlab
...
@@ -5,12 +5,16 @@ module Gitlab
class
Variable
<
Expression
::
Lexeme
class
Variable
<
Expression
::
Lexeme
PATTERN
=
/\$(?<name>\w+)/
.
freeze
PATTERN
=
/\$(?<name>\w+)/
.
freeze
def
initialize
(
valu
e
)
def
initialize
(
nam
e
)
@
value
=
valu
e
@
name
=
nam
e
end
end
def
evaluate
(
**
variables
)
def
evaluate
(
**
variables
)
end
end
def
self
.
build
(
string
)
new
(
string
.
match
(
PATTERN
)[
:name
])
end
end
end
end
end
end
end
...
...
spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
View file @
2c4aa504
...
@@ -36,6 +36,15 @@ describe Gitlab::Ci::Pipeline::Expression::Lexer do
...
@@ -36,6 +36,15 @@ describe Gitlab::Ci::Pipeline::Expression::Lexer do
expect
(
tokens
.
third
.
value
).
to
eq
'"value"'
expect
(
tokens
.
third
.
value
).
to
eq
'"value"'
end
end
it
'tokenizes tokens and operators'
do
tokens
=
described_class
.
new
(
'$VARIABLE == "text"'
).
tokenize
expect
(
tokens
.
size
).
to
eq
3
expect
(
tokens
.
first
.
value
).
to
eq
'$VARIABLE'
expect
(
tokens
.
second
.
value
).
to
eq
'=='
expect
(
tokens
.
third
.
value
).
to
eq
'"text"'
end
it
'limits statement to 5 tokens'
do
it
'limits statement to 5 tokens'
do
lexer
=
described_class
.
new
(
"$V1 $V2 $V3 $V4 $V5 $V6"
)
lexer
=
described_class
.
new
(
"$V1 $V2 $V3 $V4 $V5 $V6"
)
...
...
spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
View file @
2c4aa504
require
'spec_helper'
require
'spec_helper'
describe
Gitlab
::
Ci
::
Pipeline
::
Expression
::
Statement
do
describe
Gitlab
::
Ci
::
Pipeline
::
Expression
::
Statement
do
let
(
:pipeline
)
{
build
(
:ci_pipeline
)
}
let
(
:text
)
{
'$VAR "text"'
}
subject
do
described_class
.
new
(
text
,
pipeline
)
end
describe
'#tokens'
do
it
'returns raw tokens'
do
expect
(
subject
.
tokens
.
size
).
to
eq
2
end
end
describe
'#lexemes'
do
it
'returns an array of syntax lexemes'
do
expect
(
subject
.
lexemes
).
to
eq
%w[variable string]
end
end
describe
'#parse_tree'
do
context
'when expression grammar is incorrect'
do
it
'raises an error'
do
expect
{
subject
.
parse_tree
}
.
to
raise_error
described_class
::
ParserError
end
end
context
'when expression grammar is correct'
do
let
(
:text
)
{
'$VAR == "value"'
}
it
'returns a reverse descent parse tree when using operator'
do
expect
(
subject
.
parse_tree
)
.
to
be_a
Gitlab
::
Ci
::
Pipeline
::
Expression
::
Equals
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment