I ported the NPM's fluent-bundle
package to ActionScript for internal use for a higher-level FTL
object. However, it seems like something is wrong with the internal FTL parser.
For reference:
I've used trace()
statements and determined the parsePatternElements()
is infinitely looping, always branching at the if (indent)
line:
// Parse a complex pattern as an array of elements.
function parsePatternElements(elements:Array, commonIndent:Number):Array
{
while (true)
{
if (test(RE_TEXT_RUN))
{
elements.push(match1(RE_TEXT_RUN));
continue;
}
if (source.charAt(cursor) === '{')
{
elements.push(parsePlaceable());
continue;
}
if (source.charAt(cursor) === '}')
{
throw new SyntaxError('Unbalanced closing brace');
}
var indent:* = parseIndent();
if (indent)
{
elements.push(indent);
commonIndent = Math.min(commonIndent, indent.length);
continue;
}
break;
}
var lastIndex:Number = elements.length - 1;
var lastElement:* = elements[lastIndex];
// Trim the trailing spaces in the last element if it's a TextElement.
if (typeof lastElement == 'string')
{
elements[lastIndex] = trim(lastElement, RE_TRAILING_SPACES);
}
var baked:Array = [];
for each (var element:* in elements)
{
if (element is Indent)
{
// Dedent indented lines by the maximum common indent.
element = Indent(element).value.slice(0, Indent(element).value.length - commonIndent);
}
if (element)
{
baked.push(element);
}
}
return baked;
} // parsePatternElements
Here's the indent code: (parseIndent
is looping at the line if (source.charAt(cursor - 1) === ' ')
)
// Parse blank space. Return it if it looks like indent before a pattern
// line. Skip it othwerwise.
function parseIndent():*
{
var start:Number = cursor;
consumeToken(TOKEN_BLANK);
// Check the first non-blank character after the indent.
switch (source.charAt(cursor))
{
case '.':
case '[':
case '*':
case '}':
case '':
case undefined: // EOF
// A special character. End the Pattern.
return false;
case '{':
// Placeables don't require indentation (in EBNF: block-placeable).
// Continue the Pattern.
return makeIndent(source.slice(start, cursor));
}
// If the first character on the line is not one of the special characters
// listed above, it's a regular text character. Check if there's at least
// one space of indent before it.
if (source.charAt(cursor - 1) === ' ')
{
// It's an indented text character (in EBNF: indented-char). Continue
// the Pattern.
return makeIndent(source.slice(start, cursor));
}
// A not-indented text character is likely the identifier of the next
// message. End the Pattern.
return false;
} // parseIndent
// Trim blanks in text according to the given regex.
function trim(text:String, re:StickyRegExp):String
{
return text.replace(re.regExp, '');
}
// Normalize a blank block and extract the indent details.
function makeIndent(blank:String):Indent
{
var value:String = blank.replace(RE_BLANK_LINES.regExp, '\n');
var length:Number = RE_INDENT.regExp.exec(blank)[1].length;
return new Indent(value, length);
}
If I return false
at the parseIndent
's condition if (source.charAt(cursor - 1) === ' ')
, the infinite loop stops, but then the parser doesn't parse the resource correctly.
Here's the project I'm using to debug it:
Here's the parser:
Appreciate any tips!