function printTree( t, index, r, delim) {
var out = [ ] ,
prefix, res;
r = r || '' ;
delim = delim || ' ' ;
index = index || 0 ;
if ( index < t.length ) {
t = t.map ( function ( el) {
return el instanceof Array ? el : [ el] ;
} ) ;
prefix = r ? r + delim : '' ;
for ( var i = 0 ; i < t[ index] .length ; i++ ) {
if ( t[ index] [ i] instanceof Array ) {
res = printTree( t[ index] [ i] , 0 , r, delim) ;
} else {
res = [ prefix + t[ index] [ i] ] ;
}
for ( var j = 0 ; j < res.length ; j++ ) {
out = out.concat ( printTree( t, index + 1 , res[ j] , delim) ) ;
}
}
} else {
return [ r] ;
}
return out;
}
function Token( type, pos, value) {
this .type = type;
this .pos = pos;
this .value = value;
}
Token.END_OF_LINE = 0 ;
Token.OPERATOR = 1 ;
Token.TEXT = 2 ;
function Parser( text) {
this ._text = text;
this ._pos = 0 ;
this ._len = text.length ;
}
Parser.prototype = {
operators: {
'{' : true ,
'}' : true ,
'|' : true
} ,
nextToken: function ( ) {
if ( this ._pos >= this ._len) return new Token( Token.END_OF_LINE ) ;
if ( this ._text[ this ._pos] in this .operators ) {
return new Token( Token.OPERATOR , this ._pos, this ._text[ this ._pos++ ] ) ;
}
var text = '' ,
start = this ._pos;
while ( ( this ._pos < this ._len) && ! ( this ._text[ this ._pos] in this .operators ) ) {
text += this ._text[ this ._pos] ;
this ._pos++;
}
return new Token( Token.TEXT , start, text) ;
} ,
getNextToken: function ( ) {
var pos = this ._pos,
result = this .nextToken ( ) ;
this ._pos = pos;
return result;
}
} ;
function Interpretter( text) {
this ._parser = new Parser( text) ;
}
Interpretter.prototype = {
value: function ( ) {
var result = [ ] ,
token = this ._parser.getNextToken ( ) ;
while ( token.type == Token.TEXT || ( token.type == Token.OPERATOR && token.value == '{' ) ) {
token = this ._parser.nextToken ( ) ;
if ( token.type == Token.OPERATOR ) {
if ( token.value == '{' ) {
result.push ( this .expression ( ) ) ;
} else {
throw 'Syntax error at pos ' + token.pos ;
}
} else {
result.push ( token.value ) ;
}
token = this ._parser.getNextToken ( ) ;
}
return result;
} ,
includeValue: function ( variants, value) {
var hasNested = false ;
for ( var i = 0 ; i < value.length ; i++ ) {
if ( value[ i] instanceof Array ) {
hasNested = true ;
break ;
}
}
if ( hasNested) {
variants.push ( value) ;
} else {
variants = variants.concat ( value) ;
}
return variants;
} ,
expression: function ( ) {
var variants = [ ] ,
value = this .value ( ) ,
token = this ._parser.nextToken ( ) ;
variants = this .includeValue ( variants, value) ;
while ( token.value == '|' ) {
value = this .value ( ) ;
variants = this .includeValue ( variants, value) ;
token = this ._parser.nextToken ( ) ;
}
if ( ! token.type == '}' ) throw 'Syntax error at pos ' + token.pos ;
return variants;
}
} ;
var text = '{Пожалуйста|Просто} сделайте так, чтобы это ' +
'{удивительное|крутое|простое} тестовое предложение {изменялось {быстро|мгновенно}' +
' случайным образом|менялось каждый раз}.' ;
var interpretter = new Interpretter( text) ;
var v = interpretter.value ( ) ;
var r = printTree( v) ;
r.sort ( ) ;
print( r.join ( '\n ' ) ) ;
ZnVuY3Rpb24gcHJpbnRUcmVlKHQsIGluZGV4LCByLCBkZWxpbSkgewogICAgdmFyIG91dCA9IFtdLAogICAgICAgIHByZWZpeCwgcmVzOwogICAgciA9IHIgfHwgJyc7CiAgICBkZWxpbSA9IGRlbGltIHx8ICcgJzsKICAgIGluZGV4ID0gaW5kZXggfHwgMDsKICAgIGlmIChpbmRleCA8IHQubGVuZ3RoKSB7CiAgICAgICAgdCA9IHQubWFwKGZ1bmN0aW9uKGVsKSB7CiAgICAgICAgICAgIHJldHVybiBlbCBpbnN0YW5jZW9mIEFycmF5ID8gZWwgOiBbZWxdOwogICAgICAgIH0pOwogICAgICAgIHByZWZpeCA9IHIgPyByICsgZGVsaW0gOiAnJzsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRbaW5kZXhdLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmICh0W2luZGV4XVtpXSBpbnN0YW5jZW9mIEFycmF5KSB7CiAgICAgICAgICAgICAgICByZXMgPSBwcmludFRyZWUodFtpbmRleF1baV0sIDAsIHIsIGRlbGltKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHJlcyA9IFtwcmVmaXggKyB0W2luZGV4XVtpXV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCByZXMubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgIG91dCA9IG91dC5jb25jYXQocHJpbnRUcmVlKHQsIGluZGV4ICsgMSwgcmVzW2pdLCBkZWxpbSkpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gW3JdOwogICAgfQogICAgcmV0dXJuIG91dDsKfQoKZnVuY3Rpb24gVG9rZW4odHlwZSwgcG9zLCB2YWx1ZSkgewogICAgdGhpcy50eXBlID0gdHlwZTsKICAgIHRoaXMucG9zID0gcG9zOwogICAgdGhpcy52YWx1ZSA9IHZhbHVlOwp9ClRva2VuLkVORF9PRl9MSU5FID0gMDsKVG9rZW4uT1BFUkFUT1IgPSAxOwpUb2tlbi5URVhUID0gMjsKCmZ1bmN0aW9uIFBhcnNlcih0ZXh0KSB7CiAgICB0aGlzLl90ZXh0ID0gdGV4dDsKICAgIHRoaXMuX3BvcyA9IDA7CiAgICB0aGlzLl9sZW4gPSB0ZXh0Lmxlbmd0aDsKfQpQYXJzZXIucHJvdG90eXBlID0gewogICAgb3BlcmF0b3JzOiB7CiAgICAgICAgJ3snOiB0cnVlLAogICAgICAgICd9JzogdHJ1ZSwKICAgICAgICAnfCc6IHRydWUKICAgIH0sCiAgICBuZXh0VG9rZW46IGZ1bmN0aW9uKCkgewogICAgICAgIGlmICh0aGlzLl9wb3MgPj0gdGhpcy5fbGVuKSByZXR1cm4gbmV3IFRva2VuKFRva2VuLkVORF9PRl9MSU5FKTsKICAgICAgICBpZiAodGhpcy5fdGV4dFt0aGlzLl9wb3NdIGluIHRoaXMub3BlcmF0b3JzKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVG9rZW4oVG9rZW4uT1BFUkFUT1IsIHRoaXMuX3BvcywgdGhpcy5fdGV4dFt0aGlzLl9wb3MrK10pOwogICAgICAgIH0KICAgICAgICB2YXIgdGV4dCA9ICcnLAogICAgICAgICAgICBzdGFydCA9IHRoaXMuX3BvczsKICAgICAgICB3aGlsZSAoKHRoaXMuX3BvcyA8IHRoaXMuX2xlbikgJiYgISh0aGlzLl90ZXh0W3RoaXMuX3Bvc10gaW4gdGhpcy5vcGVyYXRvcnMpKSB7CiAgICAgICAgICAgIHRleHQgKz0gdGhpcy5fdGV4dFt0aGlzLl9wb3NdOwogICAgICAgICAgICB0aGlzLl9wb3MrKzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBUb2tlbihUb2tlbi5URVhULCBzdGFydCwgdGV4dCk7CiAgICB9LAogICAgZ2V0TmV4dFRva2VuOiBmdW5jdGlvbigpIHsKICAgICAgICB2YXIgcG9zID0gdGhpcy5fcG9zLAogICAgICAgICAgICByZXN1bHQgPSB0aGlzLm5leHRUb2tlbigpOwogICAgICAgIHRoaXMuX3BvcyA9IHBvczsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQp9OwoKZnVuY3Rpb24gSW50ZXJwcmV0dGVyKHRleHQpIHsKICAgIHRoaXMuX3BhcnNlciA9IG5ldyBQYXJzZXIodGV4dCk7Cn0KSW50ZXJwcmV0dGVyLnByb3RvdHlwZSA9IHsKICAgIHZhbHVlOiBmdW5jdGlvbigpIHsKICAgICAgICB2YXIgcmVzdWx0ID0gW10sCiAgICAgICAgICAgIHRva2VuID0gdGhpcy5fcGFyc2VyLmdldE5leHRUb2tlbigpOwogICAgICAgIHdoaWxlICh0b2tlbi50eXBlID09IFRva2VuLlRFWFQgfHwgKHRva2VuLnR5cGUgPT0gVG9rZW4uT1BFUkFUT1IgJiYgdG9rZW4udmFsdWUgPT0gJ3snKSkgewogICAgICAgICAgICB0b2tlbiA9IHRoaXMuX3BhcnNlci5uZXh0VG9rZW4oKTsKICAgICAgICAgICAgaWYgKHRva2VuLnR5cGUgPT0gVG9rZW4uT1BFUkFUT1IpIHsKICAgICAgICAgICAgICAgIGlmICh0b2tlbi52YWx1ZSA9PSAneycpIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaCh0aGlzLmV4cHJlc3Npb24oKSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRocm93ICdTeW50YXggZXJyb3IgYXQgcG9zICcgKyB0b2tlbi5wb3M7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICByZXN1bHQucHVzaCh0b2tlbi52YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdG9rZW4gPSB0aGlzLl9wYXJzZXIuZ2V0TmV4dFRva2VuKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9LAogICAgaW5jbHVkZVZhbHVlOiBmdW5jdGlvbih2YXJpYW50cywgdmFsdWUpIHsKICAgICAgICB2YXIgaGFzTmVzdGVkID0gZmFsc2U7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBpZiAodmFsdWVbaV0gaW5zdGFuY2VvZiBBcnJheSkgewogICAgICAgICAgICAgICAgaGFzTmVzdGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChoYXNOZXN0ZWQpIHsKICAgICAgICAgICAgdmFyaWFudHMucHVzaCh2YWx1ZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdmFyaWFudHMgPSB2YXJpYW50cy5jb25jYXQodmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdmFyaWFudHM7CiAgICB9LAogICAgZXhwcmVzc2lvbjogZnVuY3Rpb24oKSB7CiAgICAgICAgdmFyIHZhcmlhbnRzID0gW10sCiAgICAgICAgICAgIHZhbHVlID0gdGhpcy52YWx1ZSgpLAogICAgICAgICAgICB0b2tlbiA9IHRoaXMuX3BhcnNlci5uZXh0VG9rZW4oKTsKICAgICAgICB2YXJpYW50cyA9IHRoaXMuaW5jbHVkZVZhbHVlKHZhcmlhbnRzLCB2YWx1ZSk7CiAgICAgICAgd2hpbGUgKHRva2VuLnZhbHVlID09ICd8JykgewogICAgICAgICAgICB2YWx1ZSA9IHRoaXMudmFsdWUoKTsKICAgICAgICAgICAgdmFyaWFudHMgPSB0aGlzLmluY2x1ZGVWYWx1ZSh2YXJpYW50cywgdmFsdWUpOwogICAgICAgICAgICB0b2tlbiA9IHRoaXMuX3BhcnNlci5uZXh0VG9rZW4oKTsKICAgICAgICB9CiAgICAgICAgaWYgKCF0b2tlbi50eXBlID09ICd9JykgdGhyb3cgJ1N5bnRheCBlcnJvciBhdCBwb3MgJyArIHRva2VuLnBvczsKICAgICAgICByZXR1cm4gdmFyaWFudHM7CiAgICB9Cn07Cgp2YXIgdGV4dCA9ICd70J/QvtC20LDQu9GD0LnRgdGC0LB80J/RgNC+0YHRgtC+fSDRgdC00LXQu9Cw0LnRgtC1INGC0LDQuiwg0YfRgtC+0LHRiyDRjdGC0L4gJyArCiAgICAne9GD0LTQuNCy0LjRgtC10LvRjNC90L7QtXzQutGA0YPRgtC+0LV80L/RgNC+0YHRgtC+0LV9INGC0LXRgdGC0L7QstC+0LUg0L/RgNC10LTQu9C+0LbQtdC90LjQtSB70LjQt9C80LXQvdGP0LvQvtGB0Ywge9Cx0YvRgdGC0YDQvnzQvNCz0L3QvtCy0LXQvdC90L59JyArCiAgICAnINGB0LvRg9GH0LDQudC90YvQvCDQvtCx0YDQsNC30L7QvHzQvNC10L3Rj9C70L7RgdGMINC60LDQttC00YvQuSDRgNCw0Ld9Lic7CnZhciBpbnRlcnByZXR0ZXIgPSBuZXcgSW50ZXJwcmV0dGVyKHRleHQpOwp2YXIgdiA9IGludGVycHJldHRlci52YWx1ZSgpOwp2YXIgciA9IHByaW50VHJlZSh2KTsKci5zb3J0KCk7CnByaW50KHIuam9pbignXG4nKSk7
stdout
Пожалуйста сделайте так, чтобы это крутое тестовое предложение изменялось быстро случайным образом .
Пожалуйста сделайте так, чтобы это крутое тестовое предложение изменялось мгновенно случайным образом .
Пожалуйста сделайте так, чтобы это крутое тестовое предложение менялось каждый раз .
Пожалуйста сделайте так, чтобы это простое тестовое предложение изменялось быстро случайным образом .
Пожалуйста сделайте так, чтобы это простое тестовое предложение изменялось мгновенно случайным образом .
Пожалуйста сделайте так, чтобы это простое тестовое предложение менялось каждый раз .
Пожалуйста сделайте так, чтобы это удивительное тестовое предложение изменялось быстро случайным образом .
Пожалуйста сделайте так, чтобы это удивительное тестовое предложение изменялось мгновенно случайным образом .
Пожалуйста сделайте так, чтобы это удивительное тестовое предложение менялось каждый раз .
Просто сделайте так, чтобы это крутое тестовое предложение изменялось быстро случайным образом .
Просто сделайте так, чтобы это крутое тестовое предложение изменялось мгновенно случайным образом .
Просто сделайте так, чтобы это крутое тестовое предложение менялось каждый раз .
Просто сделайте так, чтобы это простое тестовое предложение изменялось быстро случайным образом .
Просто сделайте так, чтобы это простое тестовое предложение изменялось мгновенно случайным образом .
Просто сделайте так, чтобы это простое тестовое предложение менялось каждый раз .
Просто сделайте так, чтобы это удивительное тестовое предложение изменялось быстро случайным образом .
Просто сделайте так, чтобы это удивительное тестовое предложение изменялось мгновенно случайным образом .
Просто сделайте так, чтобы это удивительное тестовое предложение менялось каждый раз .