diff --git a/Gopkg.lock b/Gopkg.lock index b5dc577..bef2d00 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,15 +1,9 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. -[[projects]] - branch = "master" - name = "github.com/mattn/kinako" - packages = ["ast","parser","vm"] - revision = "332c0a7e205a29536e672337a4bea6c7a96b04c1" - [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "d3069fabe2d6f79fe33ad88133e861db84aef0400f6b949c4e64395913b3ae97" + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 353e507..d7072c2 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,7 +1,6 @@ - # Gopkg.toml example # -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html # for detailed Gopkg.toml documentation. # # required = ["github.com/user/thing/cmd/thing"] @@ -17,10 +16,15 @@ # source = "github.com/myfork/project2" # # [[override]] -# name = "github.com/x/y" -# version = "2.4.0" +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true -[[constraint]] - branch = "master" - name = "github.com/mattn/kinako" +[prune] + go-tests = true + unused-packages = true diff --git a/plurals/compiler.go b/plurals/compiler.go new file mode 100644 index 0000000..e1641b5 --- /dev/null +++ b/plurals/compiler.go @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved. + * Licensed under the MIT License. See LICENSE file in the project root for full license information. + */ +package plurals + +import ( + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +type match struct { + openPos int + closePos int +} + +var pat = regexp.MustCompile(`(\?|:|\|\||&&|==|!=|>=|>|<=|<|%|\d+|n)`) + +type exprToken interface { + compile(tokens []string) (expr Expression, err error) +} + +type testToken interface { + compile(tokens []string) (test test, err error) +} + +type cmpTestBuilder func(val uint32, flipped bool) test +type logicTestBuild func(left test, right test) test + +var ternaryToken ternaryStruct + +type ternaryStruct struct{} + +func (ternaryStruct) compile(tokens []string) (expr Expression, err error) { + main, err := splitTokens(tokens, "?") + if err != nil { + return expr, err + } + test, err := compileTest(strings.Join(main.Left, "")) + if err != nil { + return expr, err + } + actions, err := splitTokens(main.Right, ":") + if err != nil { + return expr, err + } + true_action, err := compileExpression(strings.Join(actions.Left, "")) + if err != nil { + return expr, err + } + false_action, err := compileExpression(strings.Join(actions.Right, "")) + if err != nil { + return expr, nil + } + return ternary{ + test: test, + trueExpr: true_action, + falseExpr: false_action, + }, nil +} + +var constToken constValStruct + +type constValStruct struct{} + +func (constValStruct) compile(tokens []string) (expr Expression, err error) { + if len(tokens) == 0 { + return expr, errors.New("got nothing instead of constant") + } + if len(tokens) != 1 { + return expr, fmt.Errorf("invalid constant: %s", strings.Join(tokens, "")) + } + i, err := strconv.Atoi(tokens[0]) + if err != nil { + return expr, err + } + return constValue{value: i}, nil +} + +func compileLogicTest(tokens []string, sep string, builder logicTestBuild) (test test, err error) { + split, err := splitTokens(tokens, sep) + if err != nil { + return test, err + } + left, err := compileTest(strings.Join(split.Left, "")) + if err != nil { + return test, err + } + right, err := compileTest(strings.Join(split.Right, "")) + if err != nil { + return test, err + } + return builder(left, right), nil +} + +var orToken orStruct + +type orStruct struct{} + +func (orStruct) compile(tokens []string) (test test, err error) { + return compileLogicTest(tokens, "||", buildOr) +} +func buildOr(left test, right test) test { + return or{left: left, right: right} +} + +var andToken andStruct + +type andStruct struct{} + +func (andStruct) compile(tokens []string) (test test, err error) { + return compileLogicTest(tokens, "&&", buildAnd) +} +func buildAnd(left test, right test) test { + return and{left: left, right: right} +} + +func compileMod(tokens []string) (math math, err error) { + split, err := splitTokens(tokens, "%") + if err != nil { + return math, err + } + if len(split.Left) != 1 || split.Left[0] != "n" { + return math, errors.New("Modulus operation requires 'n' as left operand") + } + if len(split.Right) != 1 { + return math, errors.New("Modulus operation requires simple integer as right operand") + } + i, err := parseUint32(split.Right[0]) + if err != nil { + return math, err + } + return mod{value: uint32(i)}, nil +} + +func subPipe(modTokens []string, actionTokens []string, builder cmpTestBuilder, flipped bool) (test test, err error) { + modifier, err := compileMod(modTokens) + if err != nil { + return test, err + } + if len(actionTokens) != 1 { + return test, errors.New("can only get modulus of integer") + } + i, err := parseUint32(actionTokens[0]) + if err != nil { + return test, err + } + action := builder(uint32(i), flipped) + return pipe{ + modifier: modifier, + action: action, + }, nil +} + +func compileEquality(tokens []string, sep string, builder cmpTestBuilder) (test test, err error) { + split, err := splitTokens(tokens, sep) + if err != nil { + return test, err + } + if len(split.Left) == 1 && split.Left[0] == "n" { + if len(split.Right) != 1 { + return test, errors.New("test can only compare n to integers") + } + i, err := parseUint32(split.Right[0]) + if err != nil { + return test, err + } + return builder(i, false), nil + } else if len(split.Right) == 1 && split.Right[0] == "n" { + if len(split.Left) != 1 { + return test, errors.New("test can only compare n to integers") + } + i, err := parseUint32(split.Left[0]) + if err != nil { + return test, err + } + return builder(i, true), nil + } else if contains(split.Left, "n") && contains(split.Left, "%") { + return subPipe(split.Left, split.Right, builder, false) + } else { + return test, errors.New("equality test must have 'n' as one of the two tests") + } +} + +var eqToken eqStruct + +type eqStruct struct{} + +func (eqStruct) compile(tokens []string) (test test, err error) { + return compileEquality(tokens, "==", buildEq) +} +func buildEq(val uint32, flipped bool) test { + return equal{value: val} +} + +var neqToken neqStruct + +type neqStruct struct{} + +func (neqStruct) compile(tokens []string) (test test, err error) { + return compileEquality(tokens, "!=", buildNeq) +} +func buildNeq(val uint32, flipped bool) test { + return notequal{value: val} +} + +var gtToken gtStruct + +type gtStruct struct{} + +func (gtStruct) compile(tokens []string) (test test, err error) { + return compileEquality(tokens, ">", buildGt) +} +func buildGt(val uint32, flipped bool) test { + return gt{value: val, flipped: flipped} +} + +var gteToken gteStruct + +type gteStruct struct{} + +func (gteStruct) compile(tokens []string) (test test, err error) { + return compileEquality(tokens, ">=", buildGte) +} +func buildGte(val uint32, flipped bool) test { + return gte{value: val, flipped: flipped} +} + +var ltToken ltStruct + +type ltStruct struct{} + +func (ltStruct) compile(tokens []string) (test test, err error) { + return compileEquality(tokens, "<", buildLt) +} +func buildLt(val uint32, flipped bool) test { + return lt{value: val, flipped: flipped} +} + +var lteToken lteStruct + +type lteStruct struct{} + +func (lteStruct) compile(tokens []string) (test test, err error) { + return compileEquality(tokens, "<=", buildLte) +} +func buildLte(val uint32, flipped bool) test { + return lte{value: val, flipped: flipped} +} + +type testTokenDef struct { + op string + token testToken +} + +var precedence = []testTokenDef{ + {op: "||", token: orToken}, + {op: "&&", token: andToken}, + {op: "==", token: eqToken}, + {op: "!=", token: neqToken}, + {op: ">=", token: gteToken}, + {op: ">", token: gtToken}, + {op: "<=", token: lteToken}, + {op: "<", token: ltToken}, +} + +type splitted struct { + Left []string + Right []string +} + +// Find index of token in list of tokens +func index(tokens []string, sep string) int { + for index, token := range tokens { + if token == sep { + return index + } + } + return -1 +} + +// Split a list of tokens by a token into a splitted struct holding the tokens +// before and after the token to be split by. +func splitTokens(tokens []string, sep string) (s splitted, err error) { + index := index(tokens, sep) + if index == -1 { + return s, fmt.Errorf("'%s' not found in ['%s']", sep, strings.Join(tokens, "','")) + } + return splitted{ + Left: tokens[:index], + Right: tokens[index+1:], + }, nil +} + +// Scan a string for parenthesis +func scan(s string) <-chan match { + ch := make(chan match) + go func() { + depth := 0 + opener := 0 + for index, char := range s { + switch char { + case '(': + if depth == 0 { + opener = index + } + depth++ + case ')': + depth-- + if depth == 0 { + ch <- match{ + openPos: opener, + closePos: index + 1, + } + } + } + + } + close(ch) + }() + return ch +} + +// Split the string into tokens +func split(s string) <- chan string { + ch := make(chan string) + go func() { + s = strings.Replace(s, " ", "", -1) + if !strings.Contains(s, "(") { + ch <- s + } else { + last := 0 + end := len(s) + for info := range scan(s) { + if last != info.openPos { + ch <- s[last:info.openPos] + } + ch <- s[info.openPos:info.closePos] + last = info.closePos + } + if last != end { + ch <- s[last:] + } + } + close(ch) + }() + return ch +} + +// Tokenizes a string into a list of strings, tokens grouped by parenthesis are +// not split! If the string starts with ( and ends in ), those are stripped. +func tokenize(s string) []string { + /* + TODO: Properly detect if the string starts with a ( and ends with a ) + and that those two form a matching pair. + + Eg: (foo) -> true; (foo)(bar) -> false; + */ + if s[0] == '(' && s[len(s)-1] == ')' { + s = s[1 : len(s)-1] + } + ret := []string{} + for chunk := range split(s) { + if len(chunk) != 0 { + if chunk[0] == '(' && chunk[len(chunk)-1] == ')' { + ret = append(ret, chunk) + } else { + for _, token := range pat.FindAllStringSubmatch(chunk, -1) { + ret = append(ret, token[0]) + } + } + } else { + fmt.Printf("Empty chunk in string '%s'\n", s) + } + } + return ret +} + +// Compile a string containing a plural form expression to a Expression object. +func Compile(s string) (expr Expression, err error) { + if s == "0" { + return constValue{value: 0}, nil + } + if !strings.Contains(s, "?") { + s += "?1:0" + } + return compileExpression(s) +} + +// Check if a token is in a slice of strings +func contains(haystack []string, needle string) bool { + for _, s := range haystack { + if s == needle { + return true + } + } + return false +} + +// Compiles an expression (ternary or constant) +func compileExpression(s string) (expr Expression, err error) { + tokens := tokenize(s) + if contains(tokens, "?") { + return ternaryToken.compile(tokens) + } else { + return constToken.compile(tokens) + } +} + +// Compiles a test (comparison) +func compileTest(s string) (test test, err error) { + tokens := tokenize(s) + for _, tokenDef := range precedence { + if contains(tokens, tokenDef.op) { + return tokenDef.token.compile(tokens) + } + } + return test, errors.New("cannot compile") +} + +func parseUint32(s string) (ui uint32, err error) { + i, err := strconv.ParseUint(s, 10, 32) + if err != nil { + return ui, err + } else { + return uint32(i), nil + } +} diff --git a/plurals/compiler_test.go b/plurals/compiler_test.go new file mode 100644 index 0000000..ba8f58d --- /dev/null +++ b/plurals/compiler_test.go @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved. + * Licensed under the MIT License. See LICENSE file in the project root for full license information. + */ + +package plurals + +import ( + "encoding/json" + "os" + "testing" +) + +type fixture struct { + PluralForm string + Fixture []int +} + +func TestCompiler(t *testing.T) { + f, err := os.Open("testdata/pluralforms.json") + if err != nil { + t.Fatal(err) + } + dec := json.NewDecoder(f) + var fixtures []fixture + err = dec.Decode(&fixtures) + if err != nil { + t.Fatal(err) + } + for _, data := range fixtures { + expr, err := Compile(data.PluralForm) + if err != nil { + t.Errorf("'%s' triggered error: %s", data.PluralForm, err) + } else if expr == nil { + t.Logf("'%s' compiled to nil", data.PluralForm) + t.Fail() + } else { + for n, e := range data.Fixture { + i := expr.Eval(uint32(n)) + if i != e { + t.Logf("'%s' with n = %d, expected %d, got %d, compiled to %s", data.PluralForm, n, e, i, expr) + t.Fail() + } + if i == -1 { + break + } + } + } + } +} diff --git a/plurals/expression.go b/plurals/expression.go new file mode 100644 index 0000000..993fcd5 --- /dev/null +++ b/plurals/expression.go @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved. + * Licensed under the MIT License. See LICENSE file in the project root for full license information. + */ + +package plurals + +// Expression is a plurals expression. Eval evaluates the expression for +// a given n value. Use plurals.Compile to generate Expression instances. +type Expression interface { + Eval(n uint32) int +} + +type constValue struct { + value int +} + +func (c constValue) Eval(n uint32) int { + return c.value +} + +type test interface { + test(n uint32) bool +} + +type ternary struct { + test test + trueExpr Expression + falseExpr Expression +} + +func (t ternary) Eval(n uint32) int { + if t.test.test(n) { + if t.trueExpr == nil { + return -1 + } + return t.trueExpr.Eval(n) + } else { + if t.falseExpr == nil { + return -1 + } + return t.falseExpr.Eval(n) + } +} diff --git a/plurals/math.go b/plurals/math.go new file mode 100644 index 0000000..ceaeaaf --- /dev/null +++ b/plurals/math.go @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved. + * Licensed under the MIT License. See LICENSE file in the project root for full license information. + */ + +package plurals + +type math interface { + calc(n uint32) uint32 +} + +type mod struct { + value uint32 +} + +func (m mod) calc(n uint32) uint32 { + return n % m.value +} diff --git a/plurals/testdata/pluralforms.json b/plurals/testdata/pluralforms.json new file mode 100644 index 0000000..259e02e --- /dev/null +++ b/plurals/testdata/pluralforms.json @@ -0,0 +1 @@ +[{"fixture": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "pluralform": "0"}, {"fixture": [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "pluralform": "n!=1"}, {"fixture": [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "pluralform": "n>1"}, {"fixture": [2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], "pluralform": "n%10==1&&n%100!=11?0:n!=0?1:2"}, {"fixture": [2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], "pluralform": "n==1?0:n==2?1:2"}, {"fixture": [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], "pluralform": "n==1?0:(n==0||(n%100>0&&n%100<20))?1:2"}, {"fixture": [2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2], "pluralform": "n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?1:2"}, {"fixture": [2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2], "pluralform": "n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2"}, {"fixture": [2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], "pluralform": "(n==1)?0:(n>=2&&n<=4)?1:2"}, {"fixture": [2, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2], "pluralform": "n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2"}, {"fixture": [3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], "pluralform": "n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3"}, {"fixture": [0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5], "pluralform": "n==0?0:n==1?1:n==2?2:n%100>=3&&n%100<=10?3:n%100>=11?4:5"}] diff --git a/plurals/tests.go b/plurals/tests.go new file mode 100644 index 0000000..e0137e0 --- /dev/null +++ b/plurals/tests.go @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved. + * Licensed under the MIT License. See LICENSE file in the project root for full license information. + */ + +package plurals + +type equal struct { + value uint32 +} + +func (e equal) test(n uint32) bool { + return n == e.value +} + +type notequal struct { + value uint32 +} + +func (e notequal) test(n uint32) bool { + return n != e.value +} + +type gt struct { + value uint32 + flipped bool +} + +func (e gt) test(n uint32) bool { + if e.flipped { + return e.value > n + } else { + return n > e.value + } +} + +type lt struct { + value uint32 + flipped bool +} + +func (e lt) test(n uint32) bool { + if e.flipped { + return e.value < n + } else { + return n < e.value + } +} + +type gte struct { + value uint32 + flipped bool +} + +func (e gte) test(n uint32) bool { + if e.flipped { + return e.value >= n + } else { + return n >= e.value + } +} + +type lte struct { + value uint32 + flipped bool +} + +func (e lte) test(n uint32) bool { + if e.flipped { + return e.value <= n + } else { + return n <= e.value + } +} + +type and struct { + left test + right test +} + +func (e and) test(n uint32) bool { + if !e.left.test(n) { + return false + } else { + return e.right.test(n) + } +} + +type or struct { + left test + right test +} + +func (e or) test(n uint32) bool { + if e.left.test(n) { + return true + } else { + return e.right.test(n) + } +} + +type pipe struct { + modifier math + action test +} + +func (e pipe) test(n uint32) bool { + return e.action.test(e.modifier.calc(n)) +} diff --git a/po.go b/po.go index a3fbb42..6b453a4 100644 --- a/po.go +++ b/po.go @@ -9,7 +9,7 @@ import ( "strings" "sync" - "github.com/mattn/kinako/vm" + "github.com/leonelquinteros/gotext/plurals" ) type translation struct { @@ -33,7 +33,7 @@ func (t *translation) get() string { } } - // Return unstranlated id by default + // Return untranslated id by default return t.id } @@ -45,7 +45,7 @@ func (t *translation) getN(n int) string { } } - // Return unstranlated singular if corresponding + // Return untranslated singular if corresponding if n == 0 { return t.id } @@ -89,8 +89,9 @@ type Po struct { PluralForms string // Parsed Plural-Forms header values - nplurals int - plural string + nplurals int + plural string + pluralforms plurals.Expression // Storage translations map[string]*translation @@ -107,7 +108,7 @@ type Po struct { type parseState int const ( - head parseState = iota + head parseState = iota msgCtxt msgID msgIDPlural @@ -377,6 +378,11 @@ func (po *Po) parseHeaders() { case "plural": po.plural = vs[1] + + if expr, err := plurals.Compile(po.plural); err == nil { + po.pluralforms = expr + } + } } } @@ -387,35 +393,16 @@ func (po *Po) pluralForm(n int) int { po.RLock() defer po.RUnlock() - // Failsafe - if po.nplurals < 1 { - return 0 - } - if po.plural == "" { - return 0 - } - - // Init compiler - env := vm.NewEnv() - env.Define("n", n) - - plural, err := env.Execute(po.plural) - if err != nil { - return 0 - } - if plural.Type().Name() == "bool" { - if plural.Bool() { + // Failure fallback + if po.pluralforms == nil { + /* Use the Germanic plural rule. */ + if n == 1 { + return 0 + } else { return 1 } - // Else - return 0 } - - if int(plural.Int()) > po.nplurals { - return 0 - } - - return int(plural.Int()) + return po.pluralforms.Eval(uint32(n)) } // Get retrieves the corresponding translation for the given string. diff --git a/po_test.go b/po_test.go index 7eb9a7c..d898522 100644 --- a/po_test.go +++ b/po_test.go @@ -136,7 +136,7 @@ msgstr "More translation" t.Errorf("Expected 'This one is the plural: Variable' but got '%s'", tr) } - // Test inexistent translations + // Test not existent translations tr = po.Get("This is a test") if tr != "This is a test" { t.Errorf("Expected 'This is a test' but got '%s'", tr) @@ -212,6 +212,37 @@ msgstr[1] "TR Plural: %s" msgstr[2] "TR Plural 2: %s" +` + // Create po object + po := new(Po) + po.Parse(str) + + v := "Var" + tr := po.GetN("Singular: %s", "Plural: %s", 2, v) + if tr != "TR Plural: Var" { + t.Errorf("Expected 'TR Plural: Var' but got '%s'", tr) + } + + tr = po.GetN("Singular: %s", "Plural: %s", 1, v) + if tr != "TR Singular: Var" { + t.Errorf("Expected 'TR Singular: Var' but got '%s'", tr) + } +} + + +func TestPluralNoHeaderInformation(t *testing.T) { + // Set PO content + str := ` +msgid "" +msgstr "" + +msgid "Singular: %s" +msgid_plural "Plural: %s" +msgstr[0] "TR Singular: %s" +msgstr[1] "TR Plural: %s" +msgstr[2] "TR Plural 2: %s" + + ` // Create po object po := new(Po) diff --git a/vendor/github.com/mattn/kinako/README.md b/vendor/github.com/mattn/kinako/README.md deleted file mode 100644 index 0b73325..0000000 --- a/vendor/github.com/mattn/kinako/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# kinako - -Kinako is small VM written in Go. - -![](https://raw.githubusercontent.com/mattn/kinako/master/kinako.png) - -(Picture licensed under CC BY-SA 3.0 by wikipedia) - -## Installation -Requires Go. -``` -$ go get -u github.com/mattn/kinako -``` - -## Usage - -Embedding the interpreter into your own program: - -```Go -var env = vm.NewEnv() - -env.Define("foo", 1) -val, err := env.Execute(`foo + 3`) -if err != nil { - panic(err) -} - -fmt.Println(val) -``` - -# License - -MIT - -# Author - -Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/kinako/_example/main.go b/vendor/github.com/mattn/kinako/_example/main.go deleted file mode 100644 index 71e2054..0000000 --- a/vendor/github.com/mattn/kinako/_example/main.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/mattn/kinako/vm" -) - -func main() { - env := vm.NewEnv() - v, err := env.Execute(`foo=1; foo+3`) - if err != nil { - log.Fatal(err) - } - - fmt.Println(v) -} diff --git a/vendor/github.com/mattn/kinako/ast/expr.go b/vendor/github.com/mattn/kinako/ast/expr.go deleted file mode 100644 index 758cc08..0000000 --- a/vendor/github.com/mattn/kinako/ast/expr.go +++ /dev/null @@ -1,112 +0,0 @@ -package ast - -type Token struct { - Tok int - Lit string -} - -// Position provides interface to store code locations. -type Position struct { - Line int - Column int -} - -// Expr provides all of interfaces for expression. -type Expr interface { - expr() -} - -// ExprImpl provide commonly implementations for Expr. -type ExprImpl struct { -} - -// expr provide restraint interface. -func (x *ExprImpl) expr() {} - -// NumberExpr provide Number expression. -type NumberExpr struct { - ExprImpl - Lit string -} - -// UnaryExpr provide unary minus expression. ex: -1, ^1, ~1. -type UnaryExpr struct { - ExprImpl - Operator string - Expr Expr -} - -// IdentExpr provide identity expression. -type IdentExpr struct { - ExprImpl - Lit string -} - -// Stmt provides all of interfaces for statement. -type Stmt interface { - stmt() -} - -// StmtImpl provide commonly implementations for Stmt.. -type StmtImpl struct { -} - -// stmt provide restraint interface. -func (x *StmtImpl) stmt() {} - -// LetsStmt provide multiple statement of let. -type LetsStmt struct { - StmtImpl - Lhss []Expr - Operator string - Rhss []Expr -} - -// StringExpr provide String expression. -type StringExpr struct { - ExprImpl - Lit string -} - -type TernaryOpExpr struct { - ExprImpl - Expr Expr - Lhs Expr - Rhs Expr -} - -// CallExpr provide calling expression. -type CallExpr struct { - ExprImpl - Func interface{} - Name string - SubExprs []Expr -} - -// ParenExpr provide parent block expression. -type ParenExpr struct { - ExprImpl - SubExpr Expr -} - -// BinOpExpr provide binary operator expression. -type BinOpExpr struct { - ExprImpl - Lhs Expr - Operator string - Rhs Expr -} - -// ExprStmt provide expression statement. -type ExprStmt struct { - StmtImpl - Expr Expr -} - -// LetStmt provide statement of let. -type LetStmt struct { - StmtImpl - Lhs Expr - Operator string - Rhs Expr -} diff --git a/vendor/github.com/mattn/kinako/kinako.png b/vendor/github.com/mattn/kinako/kinako.png deleted file mode 100644 index a7130c6..0000000 Binary files a/vendor/github.com/mattn/kinako/kinako.png and /dev/null differ diff --git a/vendor/github.com/mattn/kinako/parser/Makefile b/vendor/github.com/mattn/kinako/parser/Makefile deleted file mode 100644 index 88d6ad6..0000000 --- a/vendor/github.com/mattn/kinako/parser/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all : parser.go - -parser.go : parser.go.y - goyacc -o $@ parser.go.y diff --git a/vendor/github.com/mattn/kinako/parser/lexer.go b/vendor/github.com/mattn/kinako/parser/lexer.go deleted file mode 100644 index f2d8b0e..0000000 --- a/vendor/github.com/mattn/kinako/parser/lexer.go +++ /dev/null @@ -1,427 +0,0 @@ -package parser - -import ( - "errors" - "fmt" - "unicode" - - "github.com/mattn/kinako/ast" -) - -const ( - EOF = -1 // End of file. - EOL = '\n' // End of line. -) - -// Error provides a convenient interface for handling runtime error. -// It can be Error inteface with type cast which can call Pos(). -type Error struct { - Message string - Filename string - Fatal bool -} - -// Error returns the error message. -func (e *Error) Error() string { - return e.Message -} - -// Scanner stores informations for lexer. -type Scanner struct { - src []rune - offset int - lineHead int - line int -} - -// Init resets code to scan. -func (s *Scanner) Init(src string) { - s.src = []rune(src) -} - -// Scan analyses token, and decide identify or literals. -func (s *Scanner) Scan() (tok int, lit string, pos ast.Position, err error) { -retry: - s.skipBlank() - pos = s.pos() - switch ch := s.peek(); { - case isLetter(ch): - tok = IDENT - lit, err = s.scanIdentifier() - if err != nil { - return - } - case isDigit(ch): - tok = NUMBER - lit, err = s.scanNumber() - if err != nil { - return - } - case ch == '"': - tok = STRING - lit, err = s.scanString('"') - if err != nil { - return - } - case ch == '\'': - tok = STRING - lit, err = s.scanString('\'') - if err != nil { - return - } - case ch == '`': - tok = STRING - lit, err = s.scanRawString() - if err != nil { - return - } - default: - switch ch { - case EOF: - tok = EOF - case '#': - for !isEOL(s.peek()) { - s.next() - } - goto retry - case '!': - s.next() - switch s.peek() { - case '=': - tok = NEQ - lit = "!=" - default: - s.back() - tok = int(ch) - lit = string(ch) - } - case '=': - s.next() - switch s.peek() { - case '=': - tok = EQEQ - lit = "==" - default: - s.back() - tok = int(ch) - lit = string(ch) - } - case '+': - tok = int(ch) - lit = string(ch) - case '-': - tok = int(ch) - lit = string(ch) - case '*': - tok = int(ch) - lit = string(ch) - case '/': - tok = int(ch) - lit = string(ch) - case '>': - s.next() - switch s.peek() { - case '=': - tok = GE - lit = ">=" - case '>': - tok = SHIFTRIGHT - lit = ">>" - default: - s.back() - tok = int(ch) - lit = string(ch) - } - case '<': - s.next() - switch s.peek() { - case '=': - tok = LE - lit = "<=" - case '<': - tok = SHIFTLEFT - lit = "<<" - default: - s.back() - tok = int(ch) - lit = string(ch) - } - case '|': - s.next() - switch s.peek() { - case '|': - tok = OROR - lit = "||" - default: - s.back() - tok = int(ch) - lit = string(ch) - } - case '&': - s.next() - switch s.peek() { - case '&': - tok = ANDAND - lit = "&&" - default: - s.back() - tok = int(ch) - lit = string(ch) - } - case '.': - tok = int(ch) - lit = string(ch) - case '\n': - tok = int(ch) - lit = string(ch) - case '(', ')', ':', ';', '%', '?', '{', '}', ',', '[', ']', '^': - tok = int(ch) - lit = string(ch) - default: - err = fmt.Errorf(`syntax error "%s"`, string(ch)) - tok = int(ch) - lit = string(ch) - return - } - s.next() - } - return -} - -// isLetter returns true if the rune is a letter for identity. -func isLetter(ch rune) bool { - return unicode.IsLetter(ch) || ch == '_' -} - -// isDigit returns true if the rune is a number. -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' -} - -// isHex returns true if the rune is a hex digits. -func isHex(ch rune) bool { - return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F') -} - -// isEOL returns true if the rune is at end-of-line or end-of-file. -func isEOL(ch rune) bool { - return ch == '\n' || ch == -1 -} - -// isBlank returns true if the rune is empty character.. -func isBlank(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\r' -} - -// peek returns current rune in the code. -func (s *Scanner) peek() rune { - if s.reachEOF() { - return EOF - } - return s.src[s.offset] -} - -// next moves offset to next. -func (s *Scanner) next() { - if !s.reachEOF() { - if s.peek() == '\n' { - s.lineHead = s.offset + 1 - s.line++ - } - s.offset++ - } -} - -// current returns the current offset. -func (s *Scanner) current() int { - return s.offset -} - -// offset sets the offset value. -func (s *Scanner) set(o int) { - s.offset = o -} - -// back moves back offset once to top. -func (s *Scanner) back() { - s.offset-- -} - -// reachEOF returns true if offset is at end-of-file. -func (s *Scanner) reachEOF() bool { - return len(s.src) <= s.offset -} - -// pos returns the position of current. -func (s *Scanner) pos() ast.Position { - return ast.Position{Line: s.line + 1, Column: s.offset - s.lineHead + 1} -} - -// skipBlank moves position into non-black character. -func (s *Scanner) skipBlank() { - for isBlank(s.peek()) { - s.next() - } -} - -// scanIdentifier returns identifier begining at current position. -func (s *Scanner) scanIdentifier() (string, error) { - var ret []rune - for { - if !isLetter(s.peek()) && !isDigit(s.peek()) { - break - } - ret = append(ret, s.peek()) - s.next() - } - return string(ret), nil -} - -// scanNumber returns number begining at current position. -func (s *Scanner) scanNumber() (string, error) { - var ret []rune - ch := s.peek() - ret = append(ret, ch) - s.next() - if ch == '0' && s.peek() == 'x' { - ret = append(ret, s.peek()) - s.next() - for isHex(s.peek()) { - ret = append(ret, s.peek()) - s.next() - } - } else { - for isDigit(s.peek()) || s.peek() == '.' { - ret = append(ret, s.peek()) - s.next() - } - if s.peek() == 'e' { - ret = append(ret, s.peek()) - s.next() - if isDigit(s.peek()) || s.peek() == '+' || s.peek() == '-' { - ret = append(ret, s.peek()) - s.next() - for isDigit(s.peek()) || s.peek() == '.' { - ret = append(ret, s.peek()) - s.next() - } - } - for isDigit(s.peek()) || s.peek() == '.' { - ret = append(ret, s.peek()) - s.next() - } - } - if isLetter(s.peek()) { - return "", errors.New("identifier starts immediately after numeric literal") - } - } - return string(ret), nil -} - -// scanRawString returns raw-string starting at current position. -func (s *Scanner) scanRawString() (string, error) { - var ret []rune - for { - s.next() - if s.peek() == EOF { - return "", errors.New("unexpected EOF") - break - } - if s.peek() == '`' { - s.next() - break - } - ret = append(ret, s.peek()) - } - return string(ret), nil -} - -// scanString returns string starting at current position. -// This handles backslash escaping. -func (s *Scanner) scanString(l rune) (string, error) { - var ret []rune -eos: - for { - s.next() - switch s.peek() { - case EOL: - return "", errors.New("unexpected EOL") - case EOF: - return "", errors.New("unexpected EOF") - case l: - s.next() - break eos - case '\\': - s.next() - switch s.peek() { - case 'b': - ret = append(ret, '\b') - continue - case 'f': - ret = append(ret, '\f') - continue - case 'r': - ret = append(ret, '\r') - continue - case 'n': - ret = append(ret, '\n') - continue - case 't': - ret = append(ret, '\t') - continue - } - ret = append(ret, s.peek()) - continue - default: - ret = append(ret, s.peek()) - } - } - return string(ret), nil -} - -// Lexer provides inteface to parse codes. -type Lexer struct { - s *Scanner - lit string - pos ast.Position - e error - stmts []ast.Stmt -} - -// Lex scans the token and literals. -func (l *Lexer) Lex(lval *yySymType) int { - tok, lit, pos, err := l.s.Scan() - if err != nil { - l.e = &Error{Message: fmt.Sprintf("%s", err.Error()), Fatal: true} - } - lval.tok = ast.Token{Tok: tok, Lit: lit} - l.lit = lit - l.pos = pos - return tok -} - -// Error sets parse error. -func (l *Lexer) Error(msg string) { - l.e = &Error{Message: msg, Fatal: false} -} - -// Parser provides way to parse the code using Scanner. -func Parse(s *Scanner) ([]ast.Stmt, error) { - l := Lexer{s: s} - if yyParse(&l) != 0 { - return nil, l.e - } - return l.stmts, l.e -} - -func EnableErrorVerbose() { - yyErrorVerbose = true -} - -// ParserSrc provides way to parse the code from source. -func ParseSrc(src string) ([]ast.Stmt, error) { - scanner := &Scanner{ - src: []rune(src), - } - return Parse(scanner) -} diff --git a/vendor/github.com/mattn/kinako/parser/parser.go b/vendor/github.com/mattn/kinako/parser/parser.go deleted file mode 100644 index 661cd19..0000000 --- a/vendor/github.com/mattn/kinako/parser/parser.go +++ /dev/null @@ -1,778 +0,0 @@ -//line parser.go.y:2 -package parser - -import __yyfmt__ "fmt" - -//line parser.go.y:2 -import ( - "github.com/mattn/kinako/ast" -) - -//line parser.go.y:16 -type yySymType struct { - yys int - compstmt []ast.Stmt - stmts []ast.Stmt - stmt ast.Stmt - expr ast.Expr - exprs []ast.Expr - tok ast.Token - term ast.Token - terms ast.Token - opt_terms ast.Token -} - -const IDENT = 57346 -const NUMBER = 57347 -const STRING = 57348 -const EQEQ = 57349 -const NEQ = 57350 -const GE = 57351 -const LE = 57352 -const OROR = 57353 -const ANDAND = 57354 -const POW = 57355 -const SHIFTLEFT = 57356 -const SHIFTRIGHT = 57357 -const PLUSPLUS = 57358 -const MINUSMINUS = 57359 -const UNARY = 57360 - -var yyToknames = [...]string{ - "$end", - "error", - "$unk", - "IDENT", - "NUMBER", - "STRING", - "EQEQ", - "NEQ", - "GE", - "LE", - "OROR", - "ANDAND", - "POW", - "'='", - "'?'", - "':'", - "','", - "'>'", - "'<'", - "SHIFTLEFT", - "SHIFTRIGHT", - "'+'", - "'-'", - "PLUSPLUS", - "MINUSMINUS", - "'*'", - "'/'", - "'%'", - "UNARY", - "'!'", - "'^'", - "'('", - "')'", - "'|'", - "'&'", - "';'", - "'\\n'", -} -var yyStatenames = [...]string{} - -const yyEofCode = 1 -const yyErrCode = 2 -const yyInitialStackSize = 16 - -//line parser.go.y:213 - -//line yacctab:1 -var yyExca = [...]int{ - -1, 1, - 1, -1, - -2, 0, - -1, 50, - 7, 0, - 8, 0, - -2, 20, - -1, 51, - 7, 0, - 8, 0, - -2, 21, -} - -const yyNprod = 40 -const yyPrivate = 57344 - -var yyTokenNames []string -var yyStates []string - -const yyLast = 251 - -var yyAct = [...]int{ - - 9, 6, 7, 33, 35, 37, 22, 23, 60, 3, - 24, 25, 26, 38, 39, 40, 1, 41, 33, 35, - 8, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 61, 42, - 27, 28, 30, 32, 34, 36, 65, 0, 21, 63, - 4, 29, 31, 2, 18, 22, 23, 17, 0, 24, - 25, 26, 64, 0, 66, 0, 67, 33, 35, 27, - 28, 30, 32, 34, 36, 0, 0, 21, 0, 0, - 29, 31, 0, 0, 22, 23, 0, 0, 24, 25, - 26, 0, 0, 0, 0, 62, 33, 35, 27, 28, - 30, 32, 34, 36, 0, 20, 21, 0, 0, 29, - 31, 0, 0, 22, 23, 5, 0, 24, 25, 26, - 19, 0, 0, 0, 0, 33, 35, 27, 28, 30, - 32, 34, 36, 0, 19, 21, 0, 0, 29, 31, - 0, 0, 22, 23, 0, 0, 24, 25, 26, 0, - 0, 0, 0, 0, 33, 35, 27, 28, 30, 32, - 0, 36, 0, 0, 0, 0, 0, 29, 31, 0, - 0, 22, 23, 0, 0, 24, 25, 26, 27, 28, - 30, 32, 0, 33, 35, 0, 0, 0, 0, 29, - 31, 0, 0, 22, 23, 0, 0, 24, 25, 26, - 30, 32, 10, 11, 15, 33, 35, 0, 0, 29, - 31, 0, 0, 22, 23, 0, 0, 24, 25, 26, - 0, 12, 10, 11, 15, 33, 35, 0, 13, 14, - 16, 24, 25, 26, 6, 7, 0, 0, 0, 33, - 35, 12, 0, 0, 0, 0, 0, 0, 13, 14, - 16, -} -var yyPact = [...]int{ - - -35, -1000, 218, -35, -35, -1000, -1000, -1000, -1000, 91, - -27, -1000, 218, 218, 218, -1000, 218, -1000, 198, -1000, - 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, - 218, 218, 218, 218, 218, 218, 218, 218, -31, -31, - -31, 62, -1000, 120, 33, 205, 205, -31, -31, -31, - 191, 191, -16, -16, -16, -16, 120, 149, 120, 171, - 29, 120, -1000, 218, -1000, 218, 120, 120, -} -var yyPgo = [...]int{ - - 0, 16, 9, 20, 0, 8, 53, 50, 115, -} -var yyR1 = [...]int{ - - 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, -} -var yyR2 = [...]int{ - - 0, 1, 2, 2, 3, 3, 1, 1, 1, 2, - 2, 2, 1, 5, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 0, 1, 3, 0, 1, 1, 2, 1, 1, -} -var yyChk = [...]int{ - - -1000, -1, -6, -2, -7, -8, 36, 37, -3, -4, - 4, 5, 23, 30, 31, 6, 32, -6, -7, -8, - 14, 15, 22, 23, 26, 27, 28, 7, 8, 18, - 9, 19, 10, 34, 11, 35, 12, 32, -4, -4, - -4, -4, -3, -4, -4, -4, -4, -4, -4, -4, - -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, - -5, -4, 33, 16, 33, 17, -4, -4, -} -var yyDef = [...]int{ - - 34, -2, 1, 34, 35, 36, 38, 39, 3, 6, - 7, 8, 0, 0, 0, 12, 0, 2, 35, 37, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 31, 9, 10, - 11, 0, 4, 5, 0, 15, 16, 17, 18, 19, - -2, -2, 22, 23, 24, 25, 26, 27, 28, 29, - 0, 32, 14, 0, 30, 0, 13, 33, -} -var yyTok1 = [...]int{ - - 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 37, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 30, 3, 3, 3, 28, 35, 3, - 32, 33, 26, 22, 17, 23, 3, 27, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 16, 36, - 19, 14, 18, 15, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 31, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 34, -} -var yyTok2 = [...]int{ - - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 20, 21, 24, 25, 29, -} -var yyTok3 = [...]int{ - 0, -} - -var yyErrorMessages = [...]struct { - state int - token int - msg string -}{} - -//line yaccpar:1 - -/* parser for yacc output */ - -var ( - yyDebug = 0 - yyErrorVerbose = false -) - -type yyLexer interface { - Lex(lval *yySymType) int - Error(s string) -} - -type yyParser interface { - Parse(yyLexer) int - Lookahead() int -} - -type yyParserImpl struct { - lval yySymType - stack [yyInitialStackSize]yySymType - char int -} - -func (p *yyParserImpl) Lookahead() int { - return p.char -} - -func yyNewParser() yyParser { - return &yyParserImpl{} -} - -const yyFlag = -1000 - -func yyTokname(c int) string { - if c >= 1 && c-1 < len(yyToknames) { - if yyToknames[c-1] != "" { - return yyToknames[c-1] - } - } - return __yyfmt__.Sprintf("tok-%v", c) -} - -func yyStatname(s int) string { - if s >= 0 && s < len(yyStatenames) { - if yyStatenames[s] != "" { - return yyStatenames[s] - } - } - return __yyfmt__.Sprintf("state-%v", s) -} - -func yyErrorMessage(state, lookAhead int) string { - const TOKSTART = 4 - - if !yyErrorVerbose { - return "syntax error" - } - - for _, e := range yyErrorMessages { - if e.state == state && e.token == lookAhead { - return "syntax error: " + e.msg - } - } - - res := "syntax error: unexpected " + yyTokname(lookAhead) - - // To match Bison, suggest at most four expected tokens. - expected := make([]int, 0, 4) - - // Look for shiftable tokens. - base := yyPact[state] - for tok := TOKSTART; tok-1 < len(yyToknames); tok++ { - if n := base + tok; n >= 0 && n < yyLast && yyChk[yyAct[n]] == tok { - if len(expected) == cap(expected) { - return res - } - expected = append(expected, tok) - } - } - - if yyDef[state] == -2 { - i := 0 - for yyExca[i] != -1 || yyExca[i+1] != state { - i += 2 - } - - // Look for tokens that we accept or reduce. - for i += 2; yyExca[i] >= 0; i += 2 { - tok := yyExca[i] - if tok < TOKSTART || yyExca[i+1] == 0 { - continue - } - if len(expected) == cap(expected) { - return res - } - expected = append(expected, tok) - } - - // If the default action is to accept or reduce, give up. - if yyExca[i+1] != 0 { - return res - } - } - - for i, tok := range expected { - if i == 0 { - res += ", expecting " - } else { - res += " or " - } - res += yyTokname(tok) - } - return res -} - -func yylex1(lex yyLexer, lval *yySymType) (char, token int) { - token = 0 - char = lex.Lex(lval) - if char <= 0 { - token = yyTok1[0] - goto out - } - if char < len(yyTok1) { - token = yyTok1[char] - goto out - } - if char >= yyPrivate { - if char < yyPrivate+len(yyTok2) { - token = yyTok2[char-yyPrivate] - goto out - } - } - for i := 0; i < len(yyTok3); i += 2 { - token = yyTok3[i+0] - if token == char { - token = yyTok3[i+1] - goto out - } - } - -out: - if token == 0 { - token = yyTok2[1] /* unknown char */ - } - if yyDebug >= 3 { - __yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char)) - } - return char, token -} - -func yyParse(yylex yyLexer) int { - return yyNewParser().Parse(yylex) -} - -func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int { - var yyn int - var yyVAL yySymType - var yyDollar []yySymType - _ = yyDollar // silence set and not used - yyS := yyrcvr.stack[:] - - Nerrs := 0 /* number of errors */ - Errflag := 0 /* error recovery flag */ - yystate := 0 - yyrcvr.char = -1 - yytoken := -1 // yyrcvr.char translated into internal numbering - defer func() { - // Make sure we report no lookahead when not parsing. - yystate = -1 - yyrcvr.char = -1 - yytoken = -1 - }() - yyp := -1 - goto yystack - -ret0: - return 0 - -ret1: - return 1 - -yystack: - /* put a state and value onto the stack */ - if yyDebug >= 4 { - __yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate)) - } - - yyp++ - if yyp >= len(yyS) { - nyys := make([]yySymType, len(yyS)*2) - copy(nyys, yyS) - yyS = nyys - } - yyS[yyp] = yyVAL - yyS[yyp].yys = yystate - -yynewstate: - yyn = yyPact[yystate] - if yyn <= yyFlag { - goto yydefault /* simple state */ - } - if yyrcvr.char < 0 { - yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) - } - yyn += yytoken - if yyn < 0 || yyn >= yyLast { - goto yydefault - } - yyn = yyAct[yyn] - if yyChk[yyn] == yytoken { /* valid shift */ - yyrcvr.char = -1 - yytoken = -1 - yyVAL = yyrcvr.lval - yystate = yyn - if Errflag > 0 { - Errflag-- - } - goto yystack - } - -yydefault: - /* default state action */ - yyn = yyDef[yystate] - if yyn == -2 { - if yyrcvr.char < 0 { - yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) - } - - /* look through exception table */ - xi := 0 - for { - if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { - break - } - xi += 2 - } - for xi += 2; ; xi += 2 { - yyn = yyExca[xi+0] - if yyn < 0 || yyn == yytoken { - break - } - } - yyn = yyExca[xi+1] - if yyn < 0 { - goto ret0 - } - } - if yyn == 0 { - /* error ... attempt to resume parsing */ - switch Errflag { - case 0: /* brand new error */ - yylex.Error(yyErrorMessage(yystate, yytoken)) - Nerrs++ - if yyDebug >= 1 { - __yyfmt__.Printf("%s", yyStatname(yystate)) - __yyfmt__.Printf(" saw %s\n", yyTokname(yytoken)) - } - fallthrough - - case 1, 2: /* incompletely recovered error ... try again */ - Errflag = 3 - - /* find a state where "error" is a legal shift action */ - for yyp >= 0 { - yyn = yyPact[yyS[yyp].yys] + yyErrCode - if yyn >= 0 && yyn < yyLast { - yystate = yyAct[yyn] /* simulate a shift of "error" */ - if yyChk[yystate] == yyErrCode { - goto yystack - } - } - - /* the current p has no shift on "error", pop stack */ - if yyDebug >= 2 { - __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) - } - yyp-- - } - /* there is no state on the stack with an error shift ... abort */ - goto ret1 - - case 3: /* no shift yet; clobber input char */ - if yyDebug >= 2 { - __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken)) - } - if yytoken == yyEofCode { - goto ret1 - } - yyrcvr.char = -1 - yytoken = -1 - goto yynewstate /* try again in the same state */ - } - } - - /* reduction by production yyn */ - if yyDebug >= 2 { - __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) - } - - yynt := yyn - yypt := yyp - _ = yypt // guard against "declared and not used" - - yyp -= yyR2[yyn] - // yyp is now the index of $0. Perform the default action. Iff the - // reduced production is ε, $1 is possibly out of range. - if yyp+1 >= len(yyS) { - nyys := make([]yySymType, len(yyS)*2) - copy(nyys, yyS) - yyS = nyys - } - yyVAL = yyS[yyp+1] - - /* consult goto table to find next state */ - yyn = yyR1[yyn] - yyg := yyPgo[yyn] - yyj := yyg + yyS[yyp].yys + 1 - - if yyj >= yyLast { - yystate = yyAct[yyg] - } else { - yystate = yyAct[yyj] - if yyChk[yystate] != -yyn { - yystate = yyAct[yyg] - } - } - // dummy call; replaced with literal code - switch yynt { - - case 1: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:45 - { - yyVAL.compstmt = nil - } - case 2: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.go.y:49 - { - yyVAL.compstmt = yyDollar[1].stmts - } - case 3: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.go.y:55 - { - yyVAL.stmts = []ast.Stmt{yyDollar[2].stmt} - if l, ok := yylex.(*Lexer); ok { - l.stmts = yyVAL.stmts - } - } - case 4: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:62 - { - if yyDollar[3].stmt != nil { - yyVAL.stmts = append(yyDollar[1].stmts, yyDollar[3].stmt) - if l, ok := yylex.(*Lexer); ok { - l.stmts = yyVAL.stmts - } - } - } - case 5: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:73 - { - yyVAL.stmt = &ast.LetStmt{Lhs: yyDollar[1].expr, Operator: "=", Rhs: yyDollar[3].expr} - } - case 6: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:77 - { - yyVAL.stmt = &ast.ExprStmt{Expr: yyDollar[1].expr} - } - case 7: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:83 - { - yyVAL.expr = &ast.IdentExpr{Lit: yyDollar[1].tok.Lit} - } - case 8: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:87 - { - yyVAL.expr = &ast.NumberExpr{Lit: yyDollar[1].tok.Lit} - } - case 9: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.go.y:91 - { - yyVAL.expr = &ast.UnaryExpr{Operator: "-", Expr: yyDollar[2].expr} - } - case 10: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.go.y:95 - { - yyVAL.expr = &ast.UnaryExpr{Operator: "!", Expr: yyDollar[2].expr} - } - case 11: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.go.y:99 - { - yyVAL.expr = &ast.UnaryExpr{Operator: "^", Expr: yyDollar[2].expr} - } - case 12: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:103 - { - yyVAL.expr = &ast.StringExpr{Lit: yyDollar[1].tok.Lit} - } - case 13: - yyDollar = yyS[yypt-5 : yypt+1] - //line parser.go.y:107 - { - yyVAL.expr = &ast.TernaryOpExpr{Expr: yyDollar[1].expr, Lhs: yyDollar[3].expr, Rhs: yyDollar[5].expr} - } - case 14: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:111 - { - yyVAL.expr = &ast.ParenExpr{SubExpr: yyDollar[2].expr} - } - case 15: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:115 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "+", Rhs: yyDollar[3].expr} - } - case 16: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:119 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "-", Rhs: yyDollar[3].expr} - } - case 17: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:123 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "*", Rhs: yyDollar[3].expr} - } - case 18: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:127 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "/", Rhs: yyDollar[3].expr} - } - case 19: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:131 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "%", Rhs: yyDollar[3].expr} - } - case 20: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:135 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "==", Rhs: yyDollar[3].expr} - } - case 21: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:139 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "!=", Rhs: yyDollar[3].expr} - } - case 22: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:143 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: ">", Rhs: yyDollar[3].expr} - } - case 23: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:147 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: ">=", Rhs: yyDollar[3].expr} - } - case 24: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:151 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "<", Rhs: yyDollar[3].expr} - } - case 25: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:155 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "<=", Rhs: yyDollar[3].expr} - } - case 26: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:159 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "|", Rhs: yyDollar[3].expr} - } - case 27: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:163 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "||", Rhs: yyDollar[3].expr} - } - case 28: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:167 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "&", Rhs: yyDollar[3].expr} - } - case 29: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:171 - { - yyVAL.expr = &ast.BinOpExpr{Lhs: yyDollar[1].expr, Operator: "&&", Rhs: yyDollar[3].expr} - } - case 30: - yyDollar = yyS[yypt-4 : yypt+1] - //line parser.go.y:175 - { - yyVAL.expr = &ast.CallExpr{Name: yyDollar[1].tok.Lit, SubExprs: yyDollar[3].exprs} - } - case 31: - yyDollar = yyS[yypt-0 : yypt+1] - //line parser.go.y:180 - { - yyVAL.exprs = nil - } - case 32: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:184 - { - yyVAL.exprs = []ast.Expr{yyDollar[1].expr} - } - case 33: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.go.y:188 - { - yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) - } - case 36: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:198 - { - } - case 37: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.go.y:201 - { - } - case 38: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:206 - { - } - case 39: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.go.y:209 - { - } - } - goto yystack /* stack new state and value */ -} diff --git a/vendor/github.com/mattn/kinako/parser/parser.go.y b/vendor/github.com/mattn/kinako/parser/parser.go.y deleted file mode 100644 index 84086ac..0000000 --- a/vendor/github.com/mattn/kinako/parser/parser.go.y +++ /dev/null @@ -1,214 +0,0 @@ -%{ -package parser - -import ( - "github.com/mattn/kinako/ast" -) - -%} - -%type compstmt -%type stmts -%type stmt -%type expr -%type exprs - -%union{ - compstmt []ast.Stmt - stmts []ast.Stmt - stmt ast.Stmt - expr ast.Expr - exprs []ast.Expr - tok ast.Token - term ast.Token - terms ast.Token - opt_terms ast.Token -} - -%token IDENT NUMBER STRING EQEQ NEQ GE LE OROR ANDAND POW - -%right '=' -%right '?' ':' -%left OROR -%left ANDAND -%left IDENT -%nonassoc EQEQ NEQ ',' -%left '>' GE '<' LE SHIFTLEFT SHIFTRIGHT - -%left '+' '-' PLUSPLUS MINUSMINUS -%left '*' '/' '%' -%right UNARY - -%% - -compstmt : opt_terms - { - $$ = nil - } - | stmts opt_terms - { - $$ = $1 - } - -stmts : - opt_terms stmt - { - $$ = []ast.Stmt{$2} - if l, ok := yylex.(*Lexer); ok { - l.stmts = $$ - } - } - | stmts terms stmt - { - if $3 != nil { - $$ = append($1, $3) - if l, ok := yylex.(*Lexer); ok { - l.stmts = $$ - } - } - } - -stmt : - expr '=' expr - { - $$ = &ast.LetStmt{Lhs: $1, Operator: "=", Rhs: $3} - } - | expr - { - $$ = &ast.ExprStmt{Expr: $1} - } - -expr : - IDENT - { - $$ = &ast.IdentExpr{Lit: $1.Lit} - } - | NUMBER - { - $$ = &ast.NumberExpr{Lit: $1.Lit} - } - | '-' expr %prec UNARY - { - $$ = &ast.UnaryExpr{Operator: "-", Expr: $2} - } - | '!' expr %prec UNARY - { - $$ = &ast.UnaryExpr{Operator: "!", Expr: $2} - } - | '^' expr %prec UNARY - { - $$ = &ast.UnaryExpr{Operator: "^", Expr: $2} - } - | STRING - { - $$ = &ast.StringExpr{Lit: $1.Lit} - } - | expr '?' expr ':' expr - { - $$ = &ast.TernaryOpExpr{Expr: $1, Lhs: $3, Rhs: $5} - } - | '(' expr ')' - { - $$ = &ast.ParenExpr{SubExpr: $2} - } - | expr '+' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "+", Rhs: $3} - } - | expr '-' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "-", Rhs: $3} - } - | expr '*' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "*", Rhs: $3} - } - | expr '/' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "/", Rhs: $3} - } - | expr '%' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "%", Rhs: $3} - } - | expr EQEQ expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "==", Rhs: $3} - } - | expr NEQ expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "!=", Rhs: $3} - } - | expr '>' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: ">", Rhs: $3} - } - | expr GE expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: ">=", Rhs: $3} - } - | expr '<' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "<", Rhs: $3} - } - | expr LE expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "<=", Rhs: $3} - } - | expr '|' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "|", Rhs: $3} - } - | expr OROR expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "||", Rhs: $3} - } - | expr '&' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "&", Rhs: $3} - } - | expr ANDAND expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "&&", Rhs: $3} - } - | IDENT '(' exprs ')' - { - $$ = &ast.CallExpr{Name: $1.Lit, SubExprs: $3} - } - -exprs : - { - $$ = nil - } - | expr - { - $$ = []ast.Expr{$1} - } - | exprs ',' expr - { - $$ = append($1, $3) - } - -opt_terms : /* none */ - | terms - ; - - -terms : term - { - } - | terms term - { - } - ; - -term : ';' - { - } - | '\n' - { - } - ; - -%% - diff --git a/vendor/github.com/mattn/kinako/parser/y.output b/vendor/github.com/mattn/kinako/parser/y.output deleted file mode 100644 index 1a0f45e..0000000 --- a/vendor/github.com/mattn/kinako/parser/y.output +++ /dev/null @@ -1,1381 +0,0 @@ - -state 0 - $accept: .compstmt $end - opt_terms: . (34) - - ';' shift 6 - '\n' shift 7 - . reduce 34 (src line 192) - - compstmt goto 1 - stmts goto 3 - opt_terms goto 2 - terms goto 4 - term goto 5 - -state 1 - $accept: compstmt.$end - - $end accept - . error - - -state 2 - compstmt: opt_terms. (1) - stmts: opt_terms.stmt - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . reduce 1 (src line 44) - - stmt goto 8 - expr goto 9 - -state 3 - compstmt: stmts.opt_terms - stmts: stmts.terms stmt - opt_terms: . (34) - - ';' shift 6 - '\n' shift 7 - . reduce 34 (src line 192) - - opt_terms goto 17 - terms goto 18 - term goto 5 - -state 4 - opt_terms: terms. (35) - terms: terms.term - - ';' shift 6 - '\n' shift 7 - . reduce 35 (src line 193) - - term goto 19 - -state 5 - terms: term. (36) - - . reduce 36 (src line 197) - - -state 6 - term: ';'. (38) - - . reduce 38 (src line 205) - - -state 7 - term: '\n'. (39) - - . reduce 39 (src line 208) - - -state 8 - stmts: opt_terms stmt. (3) - - . reduce 3 (src line 53) - - -state 9 - stmt: expr.'=' expr - stmt: expr. (6) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '=' shift 20 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 6 (src line 76) - - -state 10 - expr: IDENT. (7) - expr: IDENT.'(' exprs ')' - - '(' shift 37 - . reduce 7 (src line 81) - - -state 11 - expr: NUMBER. (8) - - . reduce 8 (src line 86) - - -state 12 - expr: '-'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 38 - -state 13 - expr: '!'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 39 - -state 14 - expr: '^'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 40 - -state 15 - expr: STRING. (12) - - . reduce 12 (src line 102) - - -state 16 - expr: '('.expr ')' - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 41 - -state 17 - compstmt: stmts opt_terms. (2) - - . reduce 2 (src line 48) - - -state 18 - stmts: stmts terms.stmt - opt_terms: terms. (35) - terms: terms.term - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - ';' shift 6 - '\n' shift 7 - . reduce 35 (src line 193) - - stmt goto 42 - expr goto 9 - term goto 19 - -state 19 - terms: terms term. (37) - - . reduce 37 (src line 200) - - -state 20 - stmt: expr '='.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 43 - -state 21 - expr: expr '?'.expr ':' expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 44 - -state 22 - expr: expr '+'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 45 - -state 23 - expr: expr '-'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 46 - -state 24 - expr: expr '*'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 47 - -state 25 - expr: expr '/'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 48 - -state 26 - expr: expr '%'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 49 - -state 27 - expr: expr EQEQ.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 50 - -state 28 - expr: expr NEQ.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 51 - -state 29 - expr: expr '>'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 52 - -state 30 - expr: expr GE.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 53 - -state 31 - expr: expr '<'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 54 - -state 32 - expr: expr LE.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 55 - -state 33 - expr: expr '|'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 56 - -state 34 - expr: expr OROR.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 57 - -state 35 - expr: expr '&'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 58 - -state 36 - expr: expr ANDAND.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 59 - -state 37 - expr: IDENT '('.exprs ')' - exprs: . (31) - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . reduce 31 (src line 179) - - expr goto 61 - exprs goto 60 - -38: shift/reduce conflict (shift 33(0), red'n 9(10)) on '|' -38: shift/reduce conflict (shift 35(0), red'n 9(10)) on '&' -state 38 - expr: '-' expr. (9) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 9 (src line 90) - - -39: shift/reduce conflict (shift 33(0), red'n 10(10)) on '|' -39: shift/reduce conflict (shift 35(0), red'n 10(10)) on '&' -state 39 - expr: '!' expr. (10) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 10 (src line 94) - - -40: shift/reduce conflict (shift 33(0), red'n 11(10)) on '|' -40: shift/reduce conflict (shift 35(0), red'n 11(10)) on '&' -state 40 - expr: '^' expr. (11) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 11 (src line 98) - - -state 41 - expr: expr.'?' expr ':' expr - expr: '(' expr.')' - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - ')' shift 62 - '|' shift 33 - '&' shift 35 - . error - - -state 42 - stmts: stmts terms stmt. (4) - - . reduce 4 (src line 61) - - -state 43 - stmt: expr '=' expr. (5) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 5 (src line 71) - - -state 44 - expr: expr.'?' expr ':' expr - expr: expr '?' expr.':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - ':' shift 63 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . error - - -45: shift/reduce conflict (shift 33(0), red'n 15(8)) on '|' -45: shift/reduce conflict (shift 35(0), red'n 15(8)) on '&' -state 45 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr '+' expr. (15) - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 15 (src line 114) - - -46: shift/reduce conflict (shift 33(0), red'n 16(8)) on '|' -46: shift/reduce conflict (shift 35(0), red'n 16(8)) on '&' -state 46 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr '-' expr. (16) - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 16 (src line 118) - - -47: shift/reduce conflict (shift 33(0), red'n 17(9)) on '|' -47: shift/reduce conflict (shift 35(0), red'n 17(9)) on '&' -state 47 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr '*' expr. (17) - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 17 (src line 122) - - -48: shift/reduce conflict (shift 33(0), red'n 18(9)) on '|' -48: shift/reduce conflict (shift 35(0), red'n 18(9)) on '&' -state 48 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr '/' expr. (18) - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 18 (src line 126) - - -49: shift/reduce conflict (shift 33(0), red'n 19(9)) on '|' -49: shift/reduce conflict (shift 35(0), red'n 19(9)) on '&' -state 49 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr '%' expr. (19) - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 19 (src line 130) - - -50: shift/reduce conflict (shift 33(0), red'n 20(6)) on '|' -50: shift/reduce conflict (shift 35(0), red'n 20(6)) on '&' -state 50 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr EQEQ expr. (20) - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ error - NEQ error - GE shift 30 - LE shift 32 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 20 (src line 134) - - -51: shift/reduce conflict (shift 33(0), red'n 21(6)) on '|' -51: shift/reduce conflict (shift 35(0), red'n 21(6)) on '&' -state 51 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr NEQ expr. (21) - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ error - NEQ error - GE shift 30 - LE shift 32 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 21 (src line 138) - - -52: shift/reduce conflict (shift 33(0), red'n 22(7)) on '|' -52: shift/reduce conflict (shift 35(0), red'n 22(7)) on '&' -state 52 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr '>' expr. (22) - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 22 (src line 142) - - -53: shift/reduce conflict (shift 33(0), red'n 23(7)) on '|' -53: shift/reduce conflict (shift 35(0), red'n 23(7)) on '&' -state 53 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr GE expr. (23) - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 23 (src line 146) - - -54: shift/reduce conflict (shift 33(0), red'n 24(7)) on '|' -54: shift/reduce conflict (shift 35(0), red'n 24(7)) on '&' -state 54 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr '<' expr. (24) - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 24 (src line 150) - - -55: shift/reduce conflict (shift 33(0), red'n 25(7)) on '|' -55: shift/reduce conflict (shift 35(0), red'n 25(7)) on '&' -state 55 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr LE expr. (25) - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 25 (src line 154) - - -56: shift/reduce conflict (shift 27(6), red'n 26(0)) on EQEQ -56: shift/reduce conflict (shift 28(6), red'n 26(0)) on NEQ -56: shift/reduce conflict (shift 30(7), red'n 26(0)) on GE -56: shift/reduce conflict (shift 32(7), red'n 26(0)) on LE -56: shift/reduce conflict (shift 34(3), red'n 26(0)) on OROR -56: shift/reduce conflict (shift 36(4), red'n 26(0)) on ANDAND -56: shift/reduce conflict (shift 21(2), red'n 26(0)) on '?' -56: shift/reduce conflict (shift 29(7), red'n 26(0)) on '>' -56: shift/reduce conflict (shift 31(7), red'n 26(0)) on '<' -56: shift/reduce conflict (shift 22(8), red'n 26(0)) on '+' -56: shift/reduce conflict (shift 23(8), red'n 26(0)) on '-' -56: shift/reduce conflict (shift 24(9), red'n 26(0)) on '*' -56: shift/reduce conflict (shift 25(9), red'n 26(0)) on '/' -56: shift/reduce conflict (shift 26(9), red'n 26(0)) on '%' -56: shift/reduce conflict (shift 33(0), red'n 26(0)) on '|' -56: shift/reduce conflict (shift 35(0), red'n 26(0)) on '&' -state 56 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr '|' expr. (26) - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 26 (src line 158) - - -57: shift/reduce conflict (shift 33(0), red'n 27(3)) on '|' -57: shift/reduce conflict (shift 35(0), red'n 27(3)) on '&' -state 57 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr OROR expr. (27) - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - ANDAND shift 36 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 27 (src line 162) - - -58: shift/reduce conflict (shift 27(6), red'n 28(0)) on EQEQ -58: shift/reduce conflict (shift 28(6), red'n 28(0)) on NEQ -58: shift/reduce conflict (shift 30(7), red'n 28(0)) on GE -58: shift/reduce conflict (shift 32(7), red'n 28(0)) on LE -58: shift/reduce conflict (shift 34(3), red'n 28(0)) on OROR -58: shift/reduce conflict (shift 36(4), red'n 28(0)) on ANDAND -58: shift/reduce conflict (shift 21(2), red'n 28(0)) on '?' -58: shift/reduce conflict (shift 29(7), red'n 28(0)) on '>' -58: shift/reduce conflict (shift 31(7), red'n 28(0)) on '<' -58: shift/reduce conflict (shift 22(8), red'n 28(0)) on '+' -58: shift/reduce conflict (shift 23(8), red'n 28(0)) on '-' -58: shift/reduce conflict (shift 24(9), red'n 28(0)) on '*' -58: shift/reduce conflict (shift 25(9), red'n 28(0)) on '/' -58: shift/reduce conflict (shift 26(9), red'n 28(0)) on '%' -58: shift/reduce conflict (shift 33(0), red'n 28(0)) on '|' -58: shift/reduce conflict (shift 35(0), red'n 28(0)) on '&' -state 58 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr '&' expr. (28) - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 28 (src line 166) - - -59: shift/reduce conflict (shift 33(0), red'n 29(4)) on '|' -59: shift/reduce conflict (shift 35(0), red'n 29(4)) on '&' -state 59 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - expr: expr ANDAND expr. (29) - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 29 (src line 170) - - -state 60 - expr: IDENT '(' exprs.')' - exprs: exprs.',' expr - - ',' shift 65 - ')' shift 64 - . error - - -state 61 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - exprs: expr. (32) - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 32 (src line 183) - - -state 62 - expr: '(' expr ')'. (14) - - . reduce 14 (src line 110) - - -state 63 - expr: expr '?' expr ':'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 66 - -state 64 - expr: IDENT '(' exprs ')'. (30) - - . reduce 30 (src line 174) - - -state 65 - exprs: exprs ','.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 67 - -66: shift/reduce conflict (shift 33(0), red'n 13(2)) on '|' -66: shift/reduce conflict (shift 35(0), red'n 13(2)) on '&' -state 66 - expr: expr.'?' expr ':' expr - expr: expr '?' expr ':' expr. (13) - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 13 (src line 106) - - -state 67 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - exprs: exprs ',' expr. (33) - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 33 (src line 187) - - -37 terminals, 9 nonterminals -40 grammar rules, 68/2000 states -66 shift/reduce, 0 reduce/reduce conflicts reported -58 working sets used -memory: parser 38/30000 -49 extra closures -439 shift entries, 5 exceptions -37 goto entries -2 entries saved by goto default -Optimizer space used: output 251/30000 -251 table entries, 74 zero -maximum spread: 37, maximum offset: 65 diff --git a/vendor/github.com/mattn/kinako/vm/env.go b/vendor/github.com/mattn/kinako/vm/env.go deleted file mode 100644 index 08b6867..0000000 --- a/vendor/github.com/mattn/kinako/vm/env.go +++ /dev/null @@ -1,258 +0,0 @@ -package vm - -import ( - "fmt" - "reflect" - "strings" - "sync" - - "github.com/mattn/kinako/parser" -) - -// Env provides interface to run VM. This mean function scope and blocked-scope. -// If stack goes to blocked-scope, it will make new Env. -type Env struct { - name string - env map[string]reflect.Value - typ map[string]reflect.Type - parent *Env - interrupt *bool - sync.RWMutex -} - -// NewEnv creates new global scope. -func NewEnv() *Env { - b := false - - return &Env{ - env: make(map[string]reflect.Value), - typ: make(map[string]reflect.Type), - parent: nil, - interrupt: &b, - } -} - -// NewEnv creates new child scope. -func (e *Env) NewEnv() *Env { - return &Env{ - env: make(map[string]reflect.Value), - typ: make(map[string]reflect.Type), - parent: e, - name: e.name, - interrupt: e.interrupt, - } -} - -func NewPackage(n string) *Env { - b := false - - return &Env{ - env: make(map[string]reflect.Value), - typ: make(map[string]reflect.Type), - parent: nil, - name: n, - interrupt: &b, - } -} - -func (e *Env) NewPackage(n string) *Env { - return &Env{ - env: make(map[string]reflect.Value), - typ: make(map[string]reflect.Type), - parent: e, - name: n, - interrupt: e.interrupt, - } -} - -// Destroy deletes current scope. -func (e *Env) Destroy() { - e.Lock() - defer e.Unlock() - - if e.parent == nil { - return - } - for k, v := range e.parent.env { - if v.IsValid() && v.Interface() == e { - delete(e.parent.env, k) - } - } - e.parent = nil - e.env = nil -} - -// NewModule creates new module scope as global. -func (e *Env) NewModule(n string) *Env { - m := &Env{ - env: make(map[string]reflect.Value), - parent: e, - name: n, - } - e.Define(n, m) - return m -} - -// SetName sets a name of the scope. This means that the scope is module. -func (e *Env) SetName(n string) { - e.Lock() - e.name = n - e.Unlock() -} - -// GetName returns module name. -func (e *Env) GetName() string { - e.RLock() - defer e.RUnlock() - - return e.name -} - -// Addr returns pointer value which specified symbol. It goes to upper scope until -// found or returns error. -func (e *Env) Addr(k string) (reflect.Value, error) { - e.RLock() - defer e.RUnlock() - - if v, ok := e.env[k]; ok { - return v.Addr(), nil - } - if e.parent == nil { - return NilValue, fmt.Errorf("Undefined symbol '%s'", k) - } - return e.parent.Addr(k) -} - -// Type returns type which specified symbol. It goes to upper scope until -// found or returns error. -func (e *Env) Type(k string) (reflect.Type, error) { - e.RLock() - defer e.RUnlock() - - if v, ok := e.typ[k]; ok { - return v, nil - } - if e.parent == nil { - return NilType, fmt.Errorf("Undefined type '%s'", k) - } - return e.parent.Type(k) -} - -// Get returns value which specified symbol. It goes to upper scope until -// found or returns error. -func (e *Env) Get(k string) (reflect.Value, error) { - e.RLock() - defer e.RUnlock() - - if v, ok := e.env[k]; ok { - return v, nil - } - if e.parent == nil { - return NilValue, fmt.Errorf("Undefined symbol '%s'", k) - } - return e.parent.Get(k) -} - -// Set modifies value which specified as symbol. It goes to upper scope until -// found or returns error. -func (e *Env) Set(k string, v interface{}) error { - e.Lock() - defer e.Unlock() - - if _, ok := e.env[k]; ok { - val, ok := v.(reflect.Value) - if !ok { - val = reflect.ValueOf(v) - } - e.env[k] = val - return nil - } - if e.parent == nil { - return fmt.Errorf("Unknown symbol '%s'", k) - } - return e.parent.Set(k, v) -} - -// DefineGlobal defines symbol in global scope. -func (e *Env) DefineGlobal(k string, v interface{}) error { - if e.parent == nil { - return e.Define(k, v) - } - return e.parent.DefineGlobal(k, v) -} - -// DefineType defines type which specifis symbol in global scope. -func (e *Env) DefineType(k string, t interface{}) error { - if strings.Contains(k, ".") { - return fmt.Errorf("Unknown symbol '%s'", k) - } - global := e - keys := []string{k} - - e.RLock() - for global.parent != nil { - if global.name != "" { - keys = append(keys, global.name) - } - global = global.parent - } - e.RUnlock() - - for i, j := 0, len(keys)-1; i < j; i, j = i+1, j-1 { - keys[i], keys[j] = keys[j], keys[i] - } - - typ, ok := t.(reflect.Type) - if !ok { - typ = reflect.TypeOf(t) - } - - global.Lock() - global.typ[strings.Join(keys, ".")] = typ - global.Unlock() - - return nil -} - -// Define defines symbol in current scope. -func (e *Env) Define(k string, v interface{}) error { - if strings.Contains(k, ".") { - return fmt.Errorf("Unknown symbol '%s'", k) - } - val, ok := v.(reflect.Value) - if !ok { - val = reflect.ValueOf(v) - } - - e.Lock() - e.env[k] = val - e.Unlock() - - return nil -} - -// String return the name of current scope. -func (e *Env) String() string { - e.RLock() - defer e.RUnlock() - - return e.name -} - -// Dump show symbol values in the scope. -func (e *Env) Dump() { - e.RLock() - for k, v := range e.env { - fmt.Printf("%v = %#v\n", k, v) - } - e.RUnlock() -} - -// Execute parses and runs source in current scope. -func (e *Env) Execute(src string) (reflect.Value, error) { - stmts, err := parser.ParseSrc(src) - if err != nil { - return NilValue, err - } - return Run(stmts, e) -} diff --git a/vendor/github.com/mattn/kinako/vm/vm.go b/vendor/github.com/mattn/kinako/vm/vm.go deleted file mode 100644 index efbdb8c..0000000 --- a/vendor/github.com/mattn/kinako/vm/vm.go +++ /dev/null @@ -1,476 +0,0 @@ -package vm - -import ( - "errors" - "fmt" - "math" - "os" - "reflect" - "strconv" - "strings" - - "github.com/mattn/kinako/ast" -) - -var ( - NilValue = reflect.ValueOf((*interface{})(nil)) - NilType = reflect.TypeOf((*interface{})(nil)) - TrueValue = reflect.ValueOf(true) - FalseValue = reflect.ValueOf(false) -) - -// Error provides a convenient interface for handling runtime error. -// It can be Error interface with type cast which can call Pos(). -type Error struct { - Message string -} - -var ( - BreakError = errors.New("Unexpected break statement") - ContinueError = errors.New("Unexpected continue statement") - ReturnError = errors.New("Unexpected return statement") - InterruptError = errors.New("Execution interrupted") -) - -// Error returns the error message. -func (e *Error) Error() string { - return e.Message -} - -// Func is function interface to reflect functions internaly. -type Func func(args ...reflect.Value) (reflect.Value, error) - -// Run executes statements in the specified environment. -func Run(stmts []ast.Stmt, env *Env) (reflect.Value, error) { - rv := NilValue - var err error - for _, stmt := range stmts { - rv, err = RunSingleStmt(stmt, env) - if err != nil { - return rv, err - } - } - return rv, nil -} - -// Interrupts the execution of any running statements in the specified environment. -// -// Note that the execution is not instantly aborted: after a call to Interrupt, -// the current running statement will finish, but the next statement will not run, -// and instead will return a NilValue and an InterruptError. -func Interrupt(env *Env) { - env.Lock() - *(env.interrupt) = true - env.Unlock() -} - -// RunSingleStmt executes one statement in the specified environment. -func RunSingleStmt(stmt ast.Stmt, env *Env) (reflect.Value, error) { - env.Lock() - if *(env.interrupt) { - *(env.interrupt) = false - env.Unlock() - - return NilValue, InterruptError - } - env.Unlock() - - switch stmt := stmt.(type) { - case *ast.ExprStmt: - rv, err := invokeExpr(stmt.Expr, env) - if err != nil { - return rv, err - } - return rv, nil - case *ast.LetStmt: - rv := NilValue - var err error - rv, err = invokeExpr(stmt.Rhs, env) - if err != nil { - return rv, err - } - _, err = invokeLetExpr(stmt.Lhs, rv, env) - if err != nil { - return rv, err - } - return rv, nil - default: - return NilValue, errors.New("unknown statement") - } -} - -// toString converts all reflect.Value-s into string. -func toString(v reflect.Value) string { - if v.Kind() == reflect.Interface { - v = v.Elem() - } - if v.Kind() == reflect.String { - return v.String() - } - if !v.IsValid() { - return "nil" - } - return fmt.Sprint(v.Interface()) -} - -// toBool converts all reflect.Value-s into bool. -func toBool(v reflect.Value) bool { - if v.Kind() == reflect.Interface { - v = v.Elem() - } - - switch v.Kind() { - case reflect.Float32, reflect.Float64: - return v.Float() != 0.0 - case reflect.Int, reflect.Int32, reflect.Int64: - return v.Int() != 0 - case reflect.Bool: - return v.Bool() - case reflect.String: - if v.String() == "true" { - return true - } - if toInt64(v) != 0 { - return true - } - } - return false -} - -// toFloat64 converts all reflect.Value-s into float64. -func toFloat64(v reflect.Value) float64 { - if v.Kind() == reflect.Interface { - v = v.Elem() - } - switch v.Kind() { - case reflect.Float32, reflect.Float64: - return v.Float() - case reflect.Int, reflect.Int32, reflect.Int64: - return float64(v.Int()) - } - return 0.0 -} - -func isNil(v reflect.Value) bool { - if !v.IsValid() || v.Kind().String() == "unsafe.Pointer" { - return true - } - if (v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr) && v.IsNil() { - return true - } - return false -} - -func isNum(v reflect.Value) bool { - switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64: - return true - } - return false -} - -// equal returns true when lhsV and rhsV is same value. -func equal(lhsV, rhsV reflect.Value) bool { - lhsIsNil, rhsIsNil := isNil(lhsV), isNil(rhsV) - if lhsIsNil && rhsIsNil { - return true - } - if (!lhsIsNil && rhsIsNil) || (lhsIsNil && !rhsIsNil) { - return false - } - if lhsV.Kind() == reflect.Interface || lhsV.Kind() == reflect.Ptr { - lhsV = lhsV.Elem() - } - if rhsV.Kind() == reflect.Interface || rhsV.Kind() == reflect.Ptr { - rhsV = rhsV.Elem() - } - if !lhsV.IsValid() || !rhsV.IsValid() { - return true - } - if isNum(lhsV) && isNum(rhsV) { - if rhsV.Type().ConvertibleTo(lhsV.Type()) { - rhsV = rhsV.Convert(lhsV.Type()) - } - } - if lhsV.CanInterface() && rhsV.CanInterface() { - return reflect.DeepEqual(lhsV.Interface(), rhsV.Interface()) - } - return reflect.DeepEqual(lhsV, rhsV) -} - -// toInt64 converts all reflect.Value-s into int64. -func toInt64(v reflect.Value) int64 { - if v.Kind() == reflect.Interface { - v = v.Elem() - } - switch v.Kind() { - case reflect.Float32, reflect.Float64: - return int64(v.Float()) - case reflect.Int, reflect.Int32, reflect.Int64: - return v.Int() - case reflect.String: - s := v.String() - var i int64 - var err error - if strings.HasPrefix(s, "0x") { - i, err = strconv.ParseInt(s, 16, 64) - } else { - i, err = strconv.ParseInt(s, 10, 64) - } - if err == nil { - return int64(i) - } - } - return 0 -} - -func invokeLetExpr(expr ast.Expr, rv reflect.Value, env *Env) (reflect.Value, error) { - switch lhs := expr.(type) { - case *ast.IdentExpr: - if env.Set(lhs.Lit, rv) != nil { - if strings.Contains(lhs.Lit, ".") { - return NilValue, fmt.Errorf("Undefined symbol '%s'", lhs.Lit) - } - env.Define(lhs.Lit, rv) - } - return rv, nil - } - return NilValue, errors.New("Invalid operation") -} - -// invokeExpr evaluates one expression. -func invokeExpr(expr ast.Expr, env *Env) (reflect.Value, error) { - switch e := expr.(type) { - case *ast.NumberExpr: - if strings.Contains(e.Lit, ".") || strings.Contains(e.Lit, "e") { - v, err := strconv.ParseFloat(e.Lit, 64) - if err != nil { - return NilValue, err - } - return reflect.ValueOf(float64(v)), nil - } - var i int64 - var err error - if strings.HasPrefix(e.Lit, "0x") { - i, err = strconv.ParseInt(e.Lit[2:], 16, 64) - } else { - i, err = strconv.ParseInt(e.Lit, 10, 64) - } - if err != nil { - return NilValue, err - } - return reflect.ValueOf(i), nil - case *ast.IdentExpr: - return env.Get(e.Lit) - case *ast.StringExpr: - return reflect.ValueOf(e.Lit), nil - case *ast.UnaryExpr: - v, err := invokeExpr(e.Expr, env) - if err != nil { - return v, err - } - switch e.Operator { - case "-": - if v.Kind() == reflect.Float64 { - return reflect.ValueOf(-v.Float()), nil - } - return reflect.ValueOf(-v.Int()), nil - case "^": - return reflect.ValueOf(^toInt64(v)), nil - case "!": - return reflect.ValueOf(!toBool(v)), nil - default: - return NilValue, errors.New("Unknown operator ''") - } - case *ast.ParenExpr: - v, err := invokeExpr(e.SubExpr, env) - if err != nil { - return v, err - } - return v, nil - case *ast.BinOpExpr: - lhsV := NilValue - rhsV := NilValue - var err error - - lhsV, err = invokeExpr(e.Lhs, env) - if err != nil { - return lhsV, err - } - if lhsV.Kind() == reflect.Interface { - lhsV = lhsV.Elem() - } - if e.Rhs != nil { - rhsV, err = invokeExpr(e.Rhs, env) - if err != nil { - return rhsV, err - } - if rhsV.Kind() == reflect.Interface { - rhsV = rhsV.Elem() - } - } - switch e.Operator { - case "+": - if lhsV.Kind() == reflect.String || rhsV.Kind() == reflect.String { - return reflect.ValueOf(toString(lhsV) + toString(rhsV)), nil - } - if (lhsV.Kind() == reflect.Array || lhsV.Kind() == reflect.Slice) && (rhsV.Kind() != reflect.Array && rhsV.Kind() != reflect.Slice) { - return reflect.Append(lhsV, rhsV), nil - } - if (lhsV.Kind() == reflect.Array || lhsV.Kind() == reflect.Slice) && (rhsV.Kind() == reflect.Array || rhsV.Kind() == reflect.Slice) { - return reflect.AppendSlice(lhsV, rhsV), nil - } - if lhsV.Kind() == reflect.Float64 || rhsV.Kind() == reflect.Float64 { - return reflect.ValueOf(toFloat64(lhsV) + toFloat64(rhsV)), nil - } - return reflect.ValueOf(toInt64(lhsV) + toInt64(rhsV)), nil - case "-": - if lhsV.Kind() == reflect.Float64 || rhsV.Kind() == reflect.Float64 { - return reflect.ValueOf(toFloat64(lhsV) - toFloat64(rhsV)), nil - } - return reflect.ValueOf(toInt64(lhsV) - toInt64(rhsV)), nil - case "*": - if lhsV.Kind() == reflect.String && (rhsV.Kind() == reflect.Int || rhsV.Kind() == reflect.Int32 || rhsV.Kind() == reflect.Int64) { - return reflect.ValueOf(strings.Repeat(toString(lhsV), int(toInt64(rhsV)))), nil - } - if lhsV.Kind() == reflect.Float64 || rhsV.Kind() == reflect.Float64 { - return reflect.ValueOf(toFloat64(lhsV) * toFloat64(rhsV)), nil - } - return reflect.ValueOf(toInt64(lhsV) * toInt64(rhsV)), nil - case "/": - return reflect.ValueOf(toFloat64(lhsV) / toFloat64(rhsV)), nil - case "%": - return reflect.ValueOf(toInt64(lhsV) % toInt64(rhsV)), nil - case "==": - return reflect.ValueOf(equal(lhsV, rhsV)), nil - case "!=": - return reflect.ValueOf(equal(lhsV, rhsV) == false), nil - case ">": - return reflect.ValueOf(toFloat64(lhsV) > toFloat64(rhsV)), nil - case ">=": - return reflect.ValueOf(toFloat64(lhsV) >= toFloat64(rhsV)), nil - case "<": - return reflect.ValueOf(toFloat64(lhsV) < toFloat64(rhsV)), nil - case "<=": - return reflect.ValueOf(toFloat64(lhsV) <= toFloat64(rhsV)), nil - case "|": - return reflect.ValueOf(toInt64(lhsV) | toInt64(rhsV)), nil - case "||": - if toBool(lhsV) { - return lhsV, nil - } - return rhsV, nil - case "&": - return reflect.ValueOf(toInt64(lhsV) & toInt64(rhsV)), nil - case "&&": - if toBool(lhsV) { - return rhsV, nil - } - return lhsV, nil - case "**": - if lhsV.Kind() == reflect.Float64 { - return reflect.ValueOf(math.Pow(toFloat64(lhsV), toFloat64(rhsV))), nil - } - return reflect.ValueOf(int64(math.Pow(toFloat64(lhsV), toFloat64(rhsV)))), nil - case ">>": - return reflect.ValueOf(toInt64(lhsV) >> uint64(toInt64(rhsV))), nil - case "<<": - return reflect.ValueOf(toInt64(lhsV) << uint64(toInt64(rhsV))), nil - default: - return NilValue, errors.New("Unknown operator") - } - case *ast.CallExpr: - f, err := env.Get(e.Name) - if err != nil { - return f, err - } - - args := []reflect.Value{} - for i, expr := range e.SubExprs { - arg, err := invokeExpr(expr, env) - if err != nil { - return arg, err - } - - if i < f.Type().NumIn() { - if !f.Type().IsVariadic() { - it := f.Type().In(i) - if arg.Kind().String() == "unsafe.Pointer" { - arg = reflect.New(it).Elem() - } - if arg.Kind() != it.Kind() && arg.IsValid() && arg.Type().ConvertibleTo(it) { - arg = arg.Convert(it) - } else if arg.Kind() == reflect.Func { - if _, isFunc := arg.Interface().(Func); isFunc { - rfunc := arg - arg = reflect.MakeFunc(it, func(args []reflect.Value) []reflect.Value { - for i := range args { - args[i] = reflect.ValueOf(args[i]) - } - return rfunc.Call(args)[:it.NumOut()] - }) - } - } else if !arg.IsValid() { - arg = reflect.Zero(it) - } - } - } - if !arg.IsValid() { - arg = NilValue - } - - args = append(args, arg) - } - ret := NilValue - fnc := func() { - defer func() { - if os.Getenv("KINAKO_DEBUG") == "" { - if ex := recover(); ex != nil { - if e, ok := ex.(error); ok { - err = e - } else { - err = errors.New(fmt.Sprint(ex)) - } - } - } - }() - if f.Kind() == reflect.Interface { - f = f.Elem() - } - rets := f.Call(args) - if f.Type().NumOut() == 1 { - ret = rets[0] - } else { - var result []interface{} - for _, r := range rets { - result = append(result, r.Interface()) - } - ret = reflect.ValueOf(result) - } - } - fnc() - if err != nil { - return ret, err - } - return ret, nil - case *ast.TernaryOpExpr: - rv, err := invokeExpr(e.Expr, env) - if err != nil { - return rv, err - } - if toBool(rv) { - lhsV, err := invokeExpr(e.Lhs, env) - if err != nil { - return lhsV, err - } - return lhsV, nil - } - rhsV, err := invokeExpr(e.Rhs, env) - if err != nil { - return rhsV, err - } - return rhsV, nil - default: - return NilValue, errors.New("Unknown expression") - } -} diff --git a/vendor/github.com/mattn/kinako/vm/vm_test.go b/vendor/github.com/mattn/kinako/vm/vm_test.go deleted file mode 100644 index 929d23f..0000000 --- a/vendor/github.com/mattn/kinako/vm/vm_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package vm - -import ( - "reflect" - "testing" -) - -func TestExecute(t *testing.T) { - e := NewEnv() - e.Define("foo", int64(1)) - e.Define("bar", int64(2)) - e.Define("baz", int64(3)) - - tests := []struct { - input string - want interface{} - }{ - { - input: "foo+bar", - want: int64(3), - }, - { - input: "foo-bar", - want: int64(-1), - }, - { - input: "foo*bar", - want: int64(2), - }, - { - input: "foo/bar", - want: float64(0.5), - }, - { - input: "baz*(foo+bar)", - want: int64(9), - }, - { - input: "baz > 2 ? foo : bar", - want: int64(1), - }, - } - - for _, tt := range tests { - r, err := e.Execute(tt.input) - if err != nil { - t.Fatal(err) - } - got := r.Interface() - if !reflect.DeepEqual(got, tt.want) { - t.Fatalf("want %v, but %v:", tt.want, got) - } - } -}