Skip to content

Instantly share code, notes, and snippets.

@istarkov
Last active March 14, 2021 16:59
Show Gist options
  • Save istarkov/8d02e4dfb33088a4fd84d29782a00076 to your computer and use it in GitHub Desktop.
Save istarkov/8d02e4dfb33088a4fd84d29782a00076 to your computer and use it in GitHub Desktop.
Icu messages format pegjs parser
/*Parses ICU messages format https://messageformat.github.io/messageformat/guide/
like
{from} - {to} {results, plural,
one { # result }
many { # results }
} text {vr} rmm
{s, select,
man { He is "#"#"#" }
woman { She is # }
}
*/
Expression = _ w: (b:(Variable / PluralBlock / SelectBlock / AnyText) e:Expression* { return [b, ...e.flat()]})+ _ { return w.flat()}
Variable = _ '{' _ v: Var _ '}' _ {return {type: 'Variable', name: v } ;}
BlockExpression = _ w: (b:(Variable / BlockVariable / PluralBlock / SelectBlock / BlockAnyText) e:BlockExpression* { return [b, ...e.flat()]})+ _ { return w.flat()}
BlockVariable = _ '#' _ {return {type: 'BlockVariable' } ;}
SelectBlock = _ '{' _ v:Var _ ',' _ pk:SelectKeyword _ ',' _ ps:Select _ '}' { return {type:'SelectBlock', blockVariable: v, select: ps}}
Select = w:SelectCase+ { return {type: 'select', cases: w}}
SelectCase = _ cs:SelectCaseValue _ '{' txt: BlockExpression '}' _ { return {'case':cs, 'expression':txt}}
SelectCaseValue = _ w:(Integer / Var) _ { return w }
SelectKeyword = _ w:('select') _ { return w }
PluralBlock = _ '{' _ v:Var _ ',' _ pk:PluralKeyword _ ',' _ ps:PluralSelect _ '}' { return {type:'PluralBlock', blockVariable: v, select: ps}}
PluralSelect = w:PluralCase+ { return {type: 'select', cases: w}}
PluralCase = _ cs:PluralSelectCaseValue _ '{' txt: BlockExpression '}' _ { return {'case':cs, 'expression':txt}}
PluralSelectCaseValue = _ w:(Integer / 'zero' / 'one' / 'two' / 'few' / 'many' / 'other') _ { return w }
PluralKeyword = _ w:('plural' / 'selectordinal') _ { return w }
BlockText = ([^"{}#]+ / '"') { return text() }
BlockCommentedSymbols = (CommentedSymbols / '"#"') { return `${text().substr(1,1)}` }
BlockAnyText = a:(w: BlockCommentedSymbols+ { return w.join('') } / w:BlockText c:BlockCommentedSymbols* { return w + c.join('') })+ { return {type: 'Text', value: a.join('')} }
AnyText = a:(w: CommentedSymbols+ { return w.join('') } / w:Text c:CommentedSymbols* { return w + c.join('') })+ { return {type: 'Text', value: a.join('')} }
CommentedSymbols = ('"{"' / '"}"') { return `${text().substr(1,1)}` }
Text = ([^"{}]+ / '"') { return text() }
Var = [a-z]+[a-zA-Z0-9_]* { return text(); }
Integer "integer"
= [0-9]+ { return text(); }
_ "whitespace"
= [ \t\n\r]*
@istarkov
Copy link
Author

istarkov commented Mar 14, 2021

TODO:

  • Add '#' support for plurals blocks
  • Add select block

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment