114 lines
2.9 KiB
Plaintext
114 lines
2.9 KiB
Plaintext
|
|
start = token*
|
||
|
|
|
||
|
|
token
|
||
|
|
= argument / select / plural / function
|
||
|
|
/ '#' { return { type: 'octothorpe' }; }
|
||
|
|
/ str:char+ { return str.join(''); }
|
||
|
|
|
||
|
|
argument = '{' _ arg:id _ '}' {
|
||
|
|
return {
|
||
|
|
type: 'argument',
|
||
|
|
arg: arg
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
select = '{' _ arg:id _ ',' _ 'select' _ ',' _ cases:selectCase+ _ '}' {
|
||
|
|
return {
|
||
|
|
type: 'select',
|
||
|
|
arg: arg,
|
||
|
|
cases: cases
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
plural = '{' _ arg:id _ ',' _ type:('plural'/'selectordinal') _ ',' _ offset:offset? cases:pluralCase+ _ '}' {
|
||
|
|
var ls = ((type === 'selectordinal') ? options.ordinal : options.cardinal)
|
||
|
|
|| ['zero', 'one', 'two', 'few', 'many', 'other'];
|
||
|
|
if (ls && ls.length) cases.forEach(function(c) {
|
||
|
|
if (isNaN(c.key) && ls.indexOf(c.key) < 0) throw new Error(
|
||
|
|
'Invalid key `' + c.key + '` for argument `' + arg + '`.' +
|
||
|
|
' Valid ' + type + ' keys for this locale are `' + ls.join('`, `') +
|
||
|
|
'`, and explicit keys like `=0`.');
|
||
|
|
});
|
||
|
|
return {
|
||
|
|
type: type,
|
||
|
|
arg: arg,
|
||
|
|
offset: offset || 0,
|
||
|
|
cases: cases
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function = '{' _ arg:id _ ',' _ key:id _ params:functionParams '}' {
|
||
|
|
return {
|
||
|
|
type: 'function',
|
||
|
|
arg: arg,
|
||
|
|
key: key,
|
||
|
|
params: params
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
id = $([0-9a-zA-Z$_][^ \t\n\r,.+={}]*)
|
||
|
|
|
||
|
|
paramDefault = str:paramcharsDefault+ { return str.join(''); }
|
||
|
|
|
||
|
|
paramStrict = str:paramcharsStrict+ { return str.join(''); }
|
||
|
|
|
||
|
|
selectCase = _ key:id _ tokens:caseTokens { return { key: key, tokens: tokens }; }
|
||
|
|
|
||
|
|
pluralCase = _ key:pluralKey _ tokens:caseTokens { return { key: key, tokens: tokens }; }
|
||
|
|
|
||
|
|
caseTokens = '{' (_ & '{')? tokens:token* _ '}' { return tokens; }
|
||
|
|
|
||
|
|
offset = _ 'offset' _ ':' _ d:digits _ { return d; }
|
||
|
|
|
||
|
|
pluralKey
|
||
|
|
= id
|
||
|
|
/ '=' d:digits { return d; }
|
||
|
|
|
||
|
|
functionParams
|
||
|
|
= p:functionParamsDefault* ! { return options.strictFunctionParams; } { return p; }
|
||
|
|
/ p:functionParamsStrict* & { return options.strictFunctionParams; } { return p; }
|
||
|
|
|
||
|
|
functionParamsStrict = _ ',' p:paramStrict { return p; }
|
||
|
|
|
||
|
|
functionParamsDefault = _ ',' _ p:paramDefault _ { return p.replace(/^[ \t\n\r]*|[ \t\n\r]*$/g, ''); }
|
||
|
|
|
||
|
|
doubleapos = "''" { return "'"; }
|
||
|
|
|
||
|
|
inapos = doubleapos / str:[^']+ { return str.join(''); }
|
||
|
|
|
||
|
|
quotedCurly
|
||
|
|
= "'{"str:inapos*"'" { return '\u007B'+str.join(''); }
|
||
|
|
/ "'}"str:inapos*"'" { return '\u007D'+str.join(''); }
|
||
|
|
|
||
|
|
quotedFunctionParams
|
||
|
|
= quotedCurly
|
||
|
|
/ "'"
|
||
|
|
|
||
|
|
char
|
||
|
|
= [^{}#\\\0-\x08\x0e-\x1f\x7f]
|
||
|
|
/ '\\\\' { return '\\'; }
|
||
|
|
/ '\\#' { return '#'; }
|
||
|
|
/ '\\{' { return '\u007B'; }
|
||
|
|
/ '\\}' { return '\u007D'; }
|
||
|
|
/ '\\u' h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit {
|
||
|
|
return String.fromCharCode(parseInt('0x' + h1 + h2 + h3 + h4));
|
||
|
|
}
|
||
|
|
|
||
|
|
paramcharsCommon
|
||
|
|
= doubleapos
|
||
|
|
/ quotedFunctionParams
|
||
|
|
|
||
|
|
paramcharsDefault
|
||
|
|
= paramcharsCommon
|
||
|
|
/ str:[^',}]+ { return str.join(''); }
|
||
|
|
|
||
|
|
paramcharsStrict
|
||
|
|
= paramcharsCommon
|
||
|
|
/ str:[^'}]+ { return str.join(''); }
|
||
|
|
|
||
|
|
digits = $([0-9]+)
|
||
|
|
|
||
|
|
hexDigit = [0-9a-fA-F]
|
||
|
|
|
||
|
|
_ = $([ \t\n\r]*)
|