aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurin-Luis Lehning <65224843+e820@users.noreply.github.com>2021-03-07 04:59:38 +0100
committerXavier Claessens <xclaesse@gmail.com>2021-03-10 08:55:22 -0500
commit130adef77880fc99ee0a06cf3fba7696c7e7c7bc (patch)
treeb24d73969ee550251e29f08914cf80ec8d86cfc9
parent442416db6fbb35d0293bc036642e10d36d9dfc00 (diff)
downloadmeson-130adef77880fc99ee0a06cf3fba7696c7e7c7bc.zip
meson-130adef77880fc99ee0a06cf3fba7696c7e7c7bc.tar.gz
meson-130adef77880fc99ee0a06cf3fba7696c7e7c7bc.tar.bz2
Add support for basic format strings
-rw-r--r--mesonbuild/interpreterbase.py14
-rw-r--r--mesonbuild/mparser.py15
-rw-r--r--test cases/common/238 fstrings/meson.build9
3 files changed, 36 insertions, 2 deletions
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 026eaf2..d486b89 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -708,6 +708,8 @@ class InterpreterBase:
return self.evaluate_indexing(cur)
elif isinstance(cur, mparser.TernaryNode):
return self.evaluate_ternary(cur)
+ elif isinstance(cur, mparser.FormatStringNode):
+ return self.evaluate_fstring(cur)
elif isinstance(cur, mparser.ContinueNode):
raise ContinueRequest()
elif isinstance(cur, mparser.BreakNode):
@@ -926,6 +928,18 @@ The result of this is undefined and will become a hard error in a future Meson r
else:
return self.evaluate_statement(node.falseblock)
+ def evaluate_fstring(self, node: mparser.FormatStringNode) -> TYPE_var:
+ assert(isinstance(node, mparser.FormatStringNode))
+
+ def replace(match: T.Match[str]) -> str:
+ var = str(match.group(1))
+ try:
+ return str(self.variables[var])
+ except KeyError:
+ raise mesonlib.MesonException(f'Identifier "{var}" does not name a variable.')
+
+ return re.sub(r'{([_a-zA-Z][_0-9a-zA-Z]*)}', replace, node.value)
+
def evaluate_foreach(self, node: mparser.ForeachClauseNode) -> None:
assert(isinstance(node, mparser.ForeachClauseNode))
items = self.evaluate_statement(node.items)
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py
index 79f461e..1079682 100644
--- a/mesonbuild/mparser.py
+++ b/mesonbuild/mparser.py
@@ -114,6 +114,7 @@ class Lexer:
self.token_specification = [
# Need to be sorted longest to shortest.
('ignore', re.compile(r'[ \t]')),
+ ('fstring', re.compile(r"f'([^'\\]|(\\.))*'")),
('id', re.compile('[_a-zA-Z][_0-9a-zA-Z]*')),
('number', re.compile(r'0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-fA-F]+|0|[1-9]\d*')),
('eol_cont', re.compile(r'\\\n')),
@@ -189,7 +190,7 @@ class Lexer:
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':
+ elif tid in {'string', 'fstring'}:
# Handle here and not on the regexp to give a better error message.
if match_text.find("\n") != -1:
mlog.warning(textwrap.dedent("""\
@@ -200,7 +201,7 @@ class Lexer:
str(lineno),
str(col)
)
- value = match_text[1:-1]
+ value = match_text[2 if tid == 'fstring' else 1:-1]
try:
value = ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, value)
except MesonUnicodeDecodeError as err:
@@ -288,6 +289,14 @@ class StringNode(ElementaryNode[str]):
def __str__(self) -> str:
return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno)
+class FormatStringNode(ElementaryNode[str]):
+ def __init__(self, token: Token[str]):
+ super().__init__(token)
+ assert isinstance(self.value, str)
+
+ def __str__(self) -> str:
+ return "Format string node: '{self.value}' ({self.lineno}, {self.colno})."
+
class ContinueNode(ElementaryNode):
pass
@@ -671,6 +680,8 @@ class Parser:
return NumberNode(t)
if self.accept('string'):
return StringNode(t)
+ if self.accept('fstring'):
+ return FormatStringNode(t)
return EmptyNode(self.current.lineno, self.current.colno, self.current.filename)
def key_values(self) -> ArgumentNode:
diff --git a/test cases/common/238 fstrings/meson.build b/test cases/common/238 fstrings/meson.build
new file mode 100644
index 0000000..ffee053
--- /dev/null
+++ b/test cases/common/238 fstrings/meson.build
@@ -0,0 +1,9 @@
+project('meson-test', 'c')
+
+n = 10
+m = 'bar'
+s = f'test {n} string ({n}): {m}'
+
+if s != 'test 10 string (10): bar'
+ error('Incorrect string formatting')
+endif