summaryrefslogtreecommitdiff
path: root/lib/spack/spack/spec.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/spack/spec.py')
-rw-r--r--lib/spack/spack/spec.py44
1 files changed, 27 insertions, 17 deletions
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index b7ff676fe2..09769e4860 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -4981,7 +4981,7 @@ class LazySpecCache(collections.defaultdict):
#: These are possible token types in the spec grammar.
-HASH, DEP, AT, COLON, COMMA, ON, OFF, PCT, EQ, ID, VAL, FILE = range(12)
+HASH, DEP, VER, COLON, COMMA, ON, OFF, PCT, EQ, ID, VAL, FILE = range(12)
#: Regex for fully qualified spec names. (e.g., builtin.hdf5)
spec_id_re = r"\w[\w.-]*"
@@ -5001,10 +5001,13 @@ class SpecLexer(spack.parse.Lexer):
)
super(SpecLexer, self).__init__(
[
- (r"\^", lambda scanner, val: self.token(DEP, val)),
- (r"\@", lambda scanner, val: self.token(AT, val)),
+ (
+ r"\@([\w.\-]*\s*)*(\s*\=\s*\w[\w.\-]*)?",
+ lambda scanner, val: self.token(VER, val),
+ ),
(r"\:", lambda scanner, val: self.token(COLON, val)),
(r"\,", lambda scanner, val: self.token(COMMA, val)),
+ (r"\^", lambda scanner, val: self.token(DEP, val)),
(r"\+", lambda scanner, val: self.token(ON, val)),
(r"\-", lambda scanner, val: self.token(OFF, val)),
(r"\~", lambda scanner, val: self.token(OFF, val)),
@@ -5142,7 +5145,7 @@ class SpecParser(spack.parse.Parser):
else:
# If the next token can be part of a valid anonymous spec,
# create the anonymous spec
- if self.next.type in (AT, ON, OFF, PCT):
+ if self.next.type in (VER, ON, OFF, PCT):
# Raise an error if the previous spec is already concrete
if specs and specs[-1].concrete:
raise RedundantSpecError(specs[-1], "compiler, version, " "or variant")
@@ -5250,7 +5253,7 @@ class SpecParser(spack.parse.Parser):
spec.name = spec_name
while self.next:
- if self.accept(AT):
+ if self.accept(VER):
vlist = self.version_list()
spec._add_versions(vlist)
@@ -5268,7 +5271,6 @@ class SpecParser(spack.parse.Parser):
elif self.accept(ID):
self.previous = self.token
if self.accept(EQ):
- # We're adding a key-value pair to the spec
self.expect(VAL)
spec._add_flag(self.previous.value, self.token.value)
self.previous = None
@@ -5304,16 +5306,24 @@ class SpecParser(spack.parse.Parser):
return self.token.value
def version(self):
+
start = None
end = None
- if self.accept(ID):
- start = self.token.value
- if self.accept(EQ):
- # This is for versions that are associated with a hash
- # i.e. @[40 char hash]=version
- start += self.token.value
- self.expect(VAL)
- start += self.token.value
+
+ def str_translate(value):
+ # return None for empty strings since we can end up with `'@'.strip('@')`
+ if not (value and value.strip()):
+ return None
+ else:
+ return value
+
+ if self.token.type is COMMA:
+ # need to increment commas, could be ID or COLON
+ self.accept(ID)
+
+ if self.token.type in (VER, ID):
+ version_spec = self.token.value.lstrip("@")
+ start = str_translate(version_spec)
if self.accept(COLON):
if self.accept(ID):
@@ -5323,10 +5333,10 @@ class SpecParser(spack.parse.Parser):
else:
end = self.token.value
elif start:
- # No colon, but there was a version.
+ # No colon, but there was a version
return vn.Version(start)
else:
- # No colon and no id: invalid version.
+ # No colon and no id: invalid version
self.next_token_error("Invalid version specifier")
if start:
@@ -5349,7 +5359,7 @@ class SpecParser(spack.parse.Parser):
compiler = CompilerSpec.__new__(CompilerSpec)
compiler.name = self.token.value
compiler.versions = vn.VersionList()
- if self.accept(AT):
+ if self.accept(VER):
vlist = self.version_list()
compiler._add_versions(vlist)
else: