phase2_ungetc (c);
}
-/* Number of open template literals `...${ */
-static int template_literal_depth;
-
-/* Number of open '{' tokens, at each template literal level.
- The "current" element is brace_depths[template_literal_depth]. */
-static int *brace_depths;
-/* Number of allocated elements in brace_depths. */
-static size_t brace_depths_alloc;
-
-/* Adds a new brace_depths level after template_literal_depth was
- incremented. */
+/* Various syntactic constructs can be nested:
+ - braces in expressions {
+ - template literals `...${
+ - XML elements <tag>
+ - embedded JavaScript in XML {
+ For a well-formed program:
+ - expressions must have balanced braces;
+ - template literals must be closed before the embedded JavaScript is closed;
+ - the embedded JavaScript must be closed before the XML element is closed;
+ - and so on.
+ Therefore we can represent these nested syntactic constructs with a stack;
+ each element is a new level. */
+enum level_ty
+{
+ level_brace = 1,
+ level_template_literal = 2,
+ level_xml_element = 3,
+ level_embedded_js_in_xml = 4
+};
+/* The level stack. */
+static unsigned char *levels /* = NULL */;
+/* Number of allocated elements in levels. */
+static size_t levels_alloc /* = 0 */;
+/* Number of currently used elements in levels. */
+static size_t level;
+
+/* Adds a new level. */
static void
-new_brace_depth_level (void)
+new_level (enum level_ty l)
{
- if (template_literal_depth == brace_depths_alloc)
+ if (level == levels_alloc)
{
- brace_depths_alloc = 2 * brace_depths_alloc + 1;
- /* Now template_literal_depth < brace_depths_alloc. */
- brace_depths =
- (int *) xrealloc (brace_depths, brace_depths_alloc * sizeof (int));
+ levels_alloc = 2 * levels_alloc + 1;
+ /* Now level < levels_alloc. */
+ levels =
+ (unsigned char *)
+ xrealloc (levels, levels_alloc * sizeof (unsigned char));
}
- brace_depths[template_literal_depth] = 0;
+ levels[level++] = l;
}
-/* Number of open XML elements. */
-static int xml_element_depth;
-static bool inside_embedded_js_in_xml;
+/* Returns the current level's type,
+ as one of the level_* enum items, or 0 if the level stack is empty. */
+#define level_type() \
+ (level > 0 ? levels[level - 1] : 0)
/* Parses some XML markup.
Returns 0 for an XML comment,
{
mixed_string_buffer_destroy (&msb);
tp->type = last_token_type = token_type_ltemplate;
- template_literal_depth++;
- new_brace_depth_level ();
+ new_level (level_template_literal);
break;
}
- XMLMarkup and XMLElement are not allowed after an expression,
- embedded JavaScript expressions in XML do not recurse.
*/
- if (xml_element_depth > 0
- || (!inside_embedded_js_in_xml
+ if (level_type () == level_xml_element
+ || (level_type () != level_embedded_js_in_xml
&& ! is_after_expression ()))
{
/* Recognize XML markup: XML comment, CDATA, Processing
/* Opening element. */
phase2_ungetc (c);
lexical_context = lc_xml_open_tag;
- xml_element_depth++;
+ new_level (level_xml_element);
}
tp->type = last_token_type = token_type_xml_tag;
}
return;
case '>':
- if (xml_element_depth > 0 && !inside_embedded_js_in_xml)
+ if (level_type () == level_xml_element)
{
switch (lexical_context)
{
return;
case lc_xml_close_tag:
- if (--xml_element_depth > 0)
+ level--;
+ if (memchr (levels, level_xml_element, level) != NULL)
lexical_context = lc_xml_content;
else
lexical_context = lc_outside;
return;
case '/':
- if (xml_element_depth > 0 && !inside_embedded_js_in_xml)
+ if (level_type () == level_xml_element)
{
/* If it appears in an opening tag of an XML element, it's
part of '/>'. */
c = phase2_getc ();
if (c == '>')
{
- if (--xml_element_depth > 0)
+ level--;
+ if (memchr (levels, level_xml_element, level) != NULL)
lexical_context = lc_xml_content;
else
lexical_context = lc_outside;
return;
case '{':
- if (xml_element_depth > 0 && !inside_embedded_js_in_xml)
- inside_embedded_js_in_xml = true;
+ if (level_type () == level_xml_element)
+ new_level (level_embedded_js_in_xml);
else
- brace_depths[template_literal_depth]++;
+ new_level (level_brace);
tp->type = last_token_type = token_type_lbrace;
return;
case '}':
- if (xml_element_depth > 0 && inside_embedded_js_in_xml)
- inside_embedded_js_in_xml = false;
- else if (brace_depths[template_literal_depth] > 0)
- brace_depths[template_literal_depth]--;
- else if (template_literal_depth > 0)
+ if (level_type () == level_embedded_js_in_xml)
+ level--;
+ else if (level_type () == level_brace)
+ level--;
+ else if (level_type () == level_template_literal)
{
/* Middle or right part of template literal. */
for (;;)
if (uc == P7_EOF || uc == P7_STRING_END)
{
tp->type = last_token_type = token_type_rtemplate;
- template_literal_depth--;
+ level--;
break;
}
phase5_pushback_length = 0;
last_token_type = token_type_start;
- template_literal_depth = 0;
- new_brace_depth_level ();
- xml_element_depth = 0;
- inside_embedded_js_in_xml = false;
+ level = 0;
flag_context_list_table = flag_table;
paren_nesting_depth = 0;
return <a>{ 'b' }</a>;
}
var s10 = _("Expected translation string #9");
+// Mixing JSX with template literals.
+var s11 = 0;
+var s12 = (
+ <div>
+ _("Expected translation string #10");
+ {`${ _("Expected translation string #11") }`}
+ _("Expected translation string #12");
+ </div>
+);
+var s13 = _("Expected translation string #13");
+var s14 = <div className={`${ _("Expected translation string #14") }`} /> ;
+var s15 = _("Expected translation string #15");
+var s16 = { a: 1, b: <div className={`${ _("Expected translation string #16") }`} /> };
+var s17 = _("Expected translation string #17");
+var s18 = `begin${ <div> _("Expected translation string #18") </div> }end`;
+var s19 = _("Expected translation string #19");
EOF
: ${XGETTEXT=xgettext}
msgid "Expected translation string #9"
msgstr ""
+
+msgid "Expected translation string #10"
+msgstr ""
+
+msgid "Expected translation string #11"
+msgstr ""
+
+msgid "Expected translation string #12"
+msgstr ""
+
+msgid "Expected translation string #13"
+msgstr ""
+
+msgid "Expected translation string #14"
+msgstr ""
+
+msgid "Expected translation string #15"
+msgstr ""
+
+msgid "Expected translation string #16"
+msgstr ""
+
+msgid "Expected translation string #17"
+msgstr ""
+
+msgid "Expected translation string #18"
+msgstr ""
+
+msgid "Expected translation string #19"
+msgstr ""
EOF
: ${DIFF=diff}