diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2018-05-22 20:46:26 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-22 20:46:26 +0300 |
commit | 9ecd92c6fedd052f4115683726a5cc6ebaa33e85 (patch) | |
tree | 794a3df4990aa5397c7e284185b284bb956b6cb5 /mesonbuild/mparser.py | |
parent | f4194d4dbc5c48ff9a0d76c779876aab60754230 (diff) | |
parent | fe6fc59ee75f44acdaac0abc757c687916d4618a (diff) | |
download | meson-9ecd92c6fedd052f4115683726a5cc6ebaa33e85.zip meson-9ecd92c6fedd052f4115683726a5cc6ebaa33e85.tar.gz meson-9ecd92c6fedd052f4115683726a5cc6ebaa33e85.tar.bz2 |
Merge pull request #3490 from MathieuDuponchelle/dict_builtin
Add new built-in type, dict
Diffstat (limited to 'mesonbuild/mparser.py')
-rw-r--r-- | mesonbuild/mparser.py | 60 |
1 files changed, 55 insertions, 5 deletions
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 8cef377..78683be 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -104,6 +104,8 @@ class Lexer: ('rparen', re.compile(r'\)')), ('lbracket', re.compile(r'\[')), ('rbracket', re.compile(r'\]')), + ('lcurl', re.compile(r'\{')), + ('rcurl', re.compile(r'\}')), ('dblquote', re.compile(r'"')), ('string', re.compile(r"'([^'\\]|(\\.))*'")), ('comma', re.compile(r',')), @@ -134,6 +136,7 @@ class Lexer: loc = 0 par_count = 0 bracket_count = 0 + curl_count = 0 col = 0 while loc < len(self.code): matched = False @@ -160,6 +163,10 @@ class Lexer: bracket_count += 1 elif tid == 'rbracket': bracket_count -= 1 + elif tid == 'lcurl': + curl_count += 1 + elif tid == 'rcurl': + curl_count -= 1 elif tid == 'dblquote': raise ParseException('Double quotes are not supported. Use single quotes.', self.getline(line_start), lineno, col) elif tid == 'string': @@ -187,7 +194,7 @@ This will become a hard error in a future Meson release.""", self.getline(line_s elif tid == 'eol' or tid == 'eol_cont': lineno += 1 line_start = loc - if par_count > 0 or bracket_count > 0: + if par_count > 0 or bracket_count > 0 or curl_count > 0: break elif tid == 'id': if match_text in self.keywords: @@ -241,6 +248,13 @@ class ArrayNode: self.colno = args.colno self.args = args +class DictNode: + def __init__(self, args): + self.subdir = args.subdir + self.lineno = args.lineno + self.colno = args.colno + self.args = args + class EmptyNode: def __init__(self, lineno, colno): self.subdir = '' @@ -340,10 +354,10 @@ class PlusAssignmentNode: self.value = value class ForeachClauseNode: - def __init__(self, lineno, colno, varname, items, block): + def __init__(self, lineno, colno, varnames, items, block): self.lineno = lineno self.colno = colno - self.varname = varname + self.varnames = varnames self.items = items self.block = block @@ -601,6 +615,10 @@ class Parser: args = self.args() self.block_expect('rbracket', block_start) return ArrayNode(args) + elif self.accept('lcurl'): + key_values = self.key_values() + self.block_expect('rcurl', block_start) + return DictNode(key_values) else: return self.e9() @@ -618,6 +636,31 @@ class Parser: return StringNode(t) return EmptyNode(self.current.lineno, self.current.colno) + def key_values(self): + s = self.statement() + a = ArgumentNode(s) + + while not isinstance(s, EmptyNode): + potential = self.current + if self.accept('colon'): + if not isinstance(s, StringNode): + raise ParseException('Key must be a string.', + self.getline(), s.lineno, s.colno) + if s.value in a.kwargs: + # + 1 to colno to point to the actual string, not the opening quote + raise ParseException('Duplicate dictionary key: {}'.format(s.value), + self.getline(), s.lineno, s.colno + 1) + a.set_kwarg(s.value, self.statement()) + potential = self.current + if not self.accept('comma'): + return a + a.commas.append(potential) + else: + raise ParseException('Only key:value pairs are valid in dict construction.', + self.getline(), s.lineno, s.colno) + s = self.statement() + return a + def args(self): s = self.statement() a = ArgumentNode(s) @@ -629,7 +672,7 @@ class Parser: a.append(s) elif self.accept('colon'): if not isinstance(s, IdNode): - raise ParseException('Keyword argument must be a plain identifier.', + raise ParseException('Dictionary key must be a plain identifier.', self.getline(), s.lineno, s.colno) a.set_kwarg(s.value, self.statement()) potential = self.current @@ -664,10 +707,17 @@ class Parser: t = self.current self.expect('id') varname = t + varnames = [t] + + if self.accept('comma'): + t = self.current + self.expect('id') + varnames.append(t) + self.expect('colon') items = self.statement() block = self.codeblock() - return ForeachClauseNode(varname.lineno, varname.colno, varname, items, block) + return ForeachClauseNode(varname.lineno, varname.colno, varnames, items, block) def ifblock(self): condition = self.statement() |