Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d86bb66fe | ||
|
|
50cdb4e058 | ||
|
|
1fc8dec04d | ||
|
|
1bb93891f4 | ||
|
|
1e28907f7a | ||
|
|
4b94e83723 |
@@ -4,6 +4,7 @@ go:
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- tip
|
||||
|
||||
before_install:
|
||||
|
||||
18
Godeps/Godeps.json
generated
18
Godeps/Godeps.json
generated
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"ImportPath": "github.com/leonelquinteros/gotext",
|
||||
"GoVersion": "devel +be9d7f6d87 Fri Jun 16 00:31:25 2017 +0000",
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/mattn/kinako/ast",
|
||||
"Rev": "fbc18625ec69b28ae03b4eea4c349f215840ee09"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mattn/kinako/parser",
|
||||
"Rev": "fbc18625ec69b28ae03b4eea4c349f215840ee09"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mattn/kinako/vm",
|
||||
"Rev": "fbc18625ec69b28ae03b4eea4c349f215840ee09"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
Godeps/Readme
generated
5
Godeps/Readme
generated
@@ -1,5 +0,0 @@
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
||||
15
Gopkg.lock
generated
Normal file
15
Gopkg.lock
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
# 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"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
26
Gopkg.toml
Normal file
26
Gopkg.toml
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/mattn/kinako"
|
||||
76
README.md
76
README.md
@@ -116,39 +116,6 @@ A library directory structure can look like:
|
||||
And so on...
|
||||
|
||||
|
||||
|
||||
# About translation function names
|
||||
|
||||
The standard GNU gettext defines helper functions that maps to the `gettext()` function and it's widely adopted by most implementations.
|
||||
|
||||
The basic translation function is usually `_()` in the form:
|
||||
|
||||
```
|
||||
_("Translate this")
|
||||
```
|
||||
|
||||
In Go, this can't be implemented by a reusable package as the function name has to start with a capital letter in order to be exported.
|
||||
|
||||
Each implementation of this package can declare this helper functions inside their own packages if this function naming are desired/needed:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
|
||||
func _(str string, vars ...interface{}) string {
|
||||
return gotext.Get(str, vars...)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This is valid and can be used within a package.
|
||||
|
||||
In normal conditions the Go compiler will optimize the calls to `_()` by replacing its content in place of the function call to reduce the function calling overhead.
|
||||
This is a normal Go compiler behavior.
|
||||
|
||||
|
||||
|
||||
# Usage examples
|
||||
|
||||
## Using package for single language/domain settings
|
||||
@@ -156,17 +123,20 @@ This is a normal Go compiler behavior.
|
||||
For quick/simple translations you can use the package level functions directly.
|
||||
|
||||
```go
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Configure package
|
||||
gotext.Configure("/path/to/locales/root/dir", "en_UK", "domain-name")
|
||||
|
||||
// Translate text from default domain
|
||||
println(gotext.Get("My text on 'domain-name' domain"))
|
||||
fmt.Println(gotext.Get("My text on 'domain-name' domain"))
|
||||
|
||||
// Translate text from a different domain without reconfigure
|
||||
println(gotext.GetD("domain2", "Another text on a different domain"))
|
||||
fmt.Println(gotext.GetD("domain2", "Another text on a different domain"))
|
||||
}
|
||||
|
||||
```
|
||||
@@ -177,7 +147,10 @@ All translation strings support dynamic variables to be inserted without transla
|
||||
Use the fmt.Printf syntax (from Go's "fmt" package) to specify how to print the non-translated variable inside the translation string.
|
||||
|
||||
```go
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Configure package
|
||||
@@ -187,7 +160,7 @@ func main() {
|
||||
name := "John"
|
||||
|
||||
// Translate text with variables
|
||||
println(gotext.Get("Hi, my name is %s", name))
|
||||
fmt.Println(gotext.Get("Hi, my name is %s", name))
|
||||
}
|
||||
|
||||
```
|
||||
@@ -199,7 +172,10 @@ When having multiple languages/domains/libraries at the same time, you can creat
|
||||
so you can handle each settings on their own.
|
||||
|
||||
```go
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create Locale with library path and language code
|
||||
@@ -209,13 +185,13 @@ func main() {
|
||||
l.AddDomain("default")
|
||||
|
||||
// Translate text from default domain
|
||||
println(l.Get("Translate this"))
|
||||
fmt.Println(l.Get("Translate this"))
|
||||
|
||||
// Load different domain
|
||||
l.AddDomain("translations")
|
||||
|
||||
// Translate text from domain
|
||||
println(l.GetD("translations", "Translate this"))
|
||||
fmt.Println(l.GetD("translations", "Translate this"))
|
||||
}
|
||||
```
|
||||
|
||||
@@ -233,7 +209,10 @@ For when you need to work with PO files and strings,
|
||||
you can directly use the Po object to parse it and access the translations in there in the same way.
|
||||
|
||||
```go
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Set PO content
|
||||
@@ -249,10 +228,10 @@ msgstr "This one sets the var: %s"
|
||||
`
|
||||
|
||||
// Create Po object
|
||||
po := new(Po)
|
||||
po := new(gotext.Po)
|
||||
po.Parse(str)
|
||||
|
||||
println(po.Get("Translate this"))
|
||||
fmt.Println(po.Get("Translate this"))
|
||||
}
|
||||
```
|
||||
|
||||
@@ -266,7 +245,10 @@ as defined in (https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_no
|
||||
Plural formulas are parsed and evaluated using [Kinako](https://github.com/mattn/kinako)
|
||||
|
||||
```go
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Set PO content
|
||||
@@ -290,10 +272,10 @@ msgstr[1] "This one is the plural: %s"
|
||||
`
|
||||
|
||||
// Create Po object
|
||||
po := new(Po)
|
||||
po := new(gotext.Po)
|
||||
po.Parse(str)
|
||||
|
||||
println(po.GetN("One with var: %s", "Several with vars: %s", 54, v))
|
||||
fmt.Println(po.GetN("One with var: %s", "Several with vars: %s", 54, v))
|
||||
// "This one is the plural: Variable"
|
||||
}
|
||||
```
|
||||
|
||||
20
gotext.go
20
gotext.go
@@ -3,22 +3,27 @@ Package gotext implements GNU gettext utilities.
|
||||
|
||||
For quick/simple translations you can use the package level functions directly.
|
||||
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Configure package
|
||||
gotext.Configure("/path/to/locales/root/dir", "en_UK", "domain-name")
|
||||
|
||||
// Translate text from default domain
|
||||
println(gotext.Get("My text on 'domain-name' domain"))
|
||||
fmt.Println(gotext.Get("My text on 'domain-name' domain"))
|
||||
|
||||
// Translate text from a different domain without reconfigure
|
||||
println(gotext.GetD("domain2", "Another text on a different domain"))
|
||||
fmt.Println(gotext.GetD("domain2", "Another text on a different domain"))
|
||||
}
|
||||
|
||||
*/
|
||||
package gotext
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Global environment variables
|
||||
var (
|
||||
// Default domain to look at when no domain is specified. Used by package level functions.
|
||||
@@ -149,3 +154,12 @@ func GetNDC(dom, str, plural string, n int, ctx string, vars ...interface{}) str
|
||||
// Return translation
|
||||
return storage.GetNDC(dom, str, plural, n, ctx, vars...)
|
||||
}
|
||||
|
||||
// printf applies text formatting only when needed to parse variables.
|
||||
func printf(str string, vars ...interface{}) string {
|
||||
if len(vars) > 0 {
|
||||
return fmt.Sprintf(str, vars...)
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
128
gotext_test.go
128
gotext_test.go
@@ -3,6 +3,7 @@ package gotext
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -32,10 +33,12 @@ func TestGettersSetters(t *testing.T) {
|
||||
func TestPackageFunctions(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
# msgid ""
|
||||
# msgstr ""
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: %s\n"
|
||||
"Report-Msgid-Bugs-To: %s\n"
|
||||
|
||||
# Initial comment
|
||||
# Headers below
|
||||
# More Headers below
|
||||
"Language: en\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -55,14 +58,6 @@ msgstr[0] "This one is the singular: %s"
|
||||
msgstr[1] "This one is the plural: %s"
|
||||
msgstr[2] "And this is the second plural form: %s"
|
||||
|
||||
msgid "This one has invalid syntax translations"
|
||||
msgid_plural "Plural index"
|
||||
msgstr[abc] "Wrong index"
|
||||
msgstr[1 "Forgot to close brackets"
|
||||
msgstr[0] "Badly formatted string'
|
||||
|
||||
msgid "Invalid formatted id[] with no translations
|
||||
|
||||
msgctxt "Ctx"
|
||||
msgid "One with var: %s"
|
||||
msgid_plural "Several with vars: %s"
|
||||
@@ -79,6 +74,11 @@ msgstr "Some random translation in a context"
|
||||
msgid "More"
|
||||
msgstr "More translation"
|
||||
|
||||
msgid "Untranslated"
|
||||
msgid_plural "Several untranslated"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
`
|
||||
|
||||
// Create Locales directory on default location
|
||||
@@ -141,6 +141,79 @@ msgstr "More translation"
|
||||
}
|
||||
}
|
||||
|
||||
func TestUntranslated(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
msgid "Untranslated"
|
||||
msgid_plural "Several untranslated"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
`
|
||||
|
||||
// Create Locales directory on default location
|
||||
dirname := path.Clean("/tmp" + string(os.PathSeparator) + "en_US")
|
||||
err := os.MkdirAll(dirname, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't create test directory: %s", err.Error())
|
||||
}
|
||||
|
||||
// Write PO content to default domain file
|
||||
filename := path.Clean(dirname + string(os.PathSeparator) + "default.po")
|
||||
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't create test file: %s", err.Error())
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = f.WriteString(str)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't write to test file: %s", err.Error())
|
||||
}
|
||||
|
||||
// Set package configuration
|
||||
Configure("/tmp", "en_US", "default")
|
||||
|
||||
// Test untranslated
|
||||
tr := Get("Untranslated")
|
||||
if tr != "Untranslated" {
|
||||
t.Errorf("Expected 'Untranslated' but got '%s'", tr)
|
||||
}
|
||||
tr = GetN("Untranslated", "Several untranslated", 1)
|
||||
if tr != "Untranslated" {
|
||||
t.Errorf("Expected 'Untranslated' but got '%s'", tr)
|
||||
}
|
||||
|
||||
tr = GetN("Untranslated", "Several untranslated", 2)
|
||||
if tr != "Several untranslated" {
|
||||
t.Errorf("Expected 'Several untranslated' but got '%s'", tr)
|
||||
}
|
||||
|
||||
tr = GetD("default", "Untranslated")
|
||||
if tr != "Untranslated" {
|
||||
t.Errorf("Expected 'Untranslated' but got '%s'", tr)
|
||||
}
|
||||
tr = GetND("default", "Untranslated", "Several untranslated", 1)
|
||||
if tr != "Untranslated" {
|
||||
t.Errorf("Expected 'Untranslated' but got '%s'", tr)
|
||||
}
|
||||
|
||||
tr = GetND("default", "Untranslated", "Several untranslated", 2)
|
||||
if tr != "Several untranslated" {
|
||||
t.Errorf("Expected 'Several untranslated' but got '%s'", tr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageRace(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `# Some comment
|
||||
@@ -180,20 +253,29 @@ msgstr[2] "And this is the second plural form: %s"
|
||||
t.Fatalf("Can't write to test file: %s", err.Error())
|
||||
}
|
||||
|
||||
// Init sync channels
|
||||
c1 := make(chan bool)
|
||||
c2 := make(chan bool)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
wg.Add(1)
|
||||
// Test translations
|
||||
go func(done chan bool) {
|
||||
Get("My text")
|
||||
done <- true
|
||||
}(c1)
|
||||
|
||||
go func(done chan bool) {
|
||||
Get("My text")
|
||||
done <- true
|
||||
}(c2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
Get("My text")
|
||||
GetN("One with var: %s", "Several with vars: %s", 0, "test")
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
Get("My text")
|
||||
GetN("One with var: %s", "Several with vars: %s", 1, "test")
|
||||
}()
|
||||
|
||||
Get("My text")
|
||||
GetN("One with var: %s", "Several with vars: %s", 2, "test")
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
14
locale.go
14
locale.go
@@ -1,7 +1,6 @@
|
||||
package gotext
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
@@ -14,7 +13,10 @@ multiple languages at the same time by working with this object.
|
||||
|
||||
Example:
|
||||
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create Locale with library path and language code
|
||||
@@ -24,13 +26,13 @@ Example:
|
||||
l.AddDomain("default")
|
||||
|
||||
// Translate text from default domain
|
||||
println(l.Get("Translate this"))
|
||||
fmt.Println(l.Get("Translate this"))
|
||||
|
||||
// Load different domain ('/path/to/i18n/dir/en_US/LC_MESSAGES/extras.po')
|
||||
l.AddDomain("extras")
|
||||
|
||||
// Translate text from domain
|
||||
println(l.GetD("extras", "Translate this"))
|
||||
fmt.Println(l.GetD("extras", "Translate this"))
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -135,7 +137,7 @@ func (l *Locale) GetND(dom, str, plural string, n int, vars ...interface{}) stri
|
||||
}
|
||||
|
||||
// Return the same we received by default
|
||||
return fmt.Sprintf(plural, vars...)
|
||||
return printf(plural, vars...)
|
||||
}
|
||||
|
||||
// GetC uses a domain "default" to return the corresponding translation of the given string in the given context.
|
||||
@@ -172,5 +174,5 @@ func (l *Locale) GetNDC(dom, str, plural string, n int, ctx string, vars ...inte
|
||||
}
|
||||
|
||||
// Return the same we received by default
|
||||
return fmt.Sprintf(plural, vars...)
|
||||
return printf(plural, vars...)
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
func TestLocale(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
# msgid ""
|
||||
# msgstr ""
|
||||
msgid ""
|
||||
msgstr ""
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
@@ -38,8 +38,6 @@ msgstr[abc] "Wrong index"
|
||||
msgstr[1 "Forgot to close brackets"
|
||||
msgstr[0] "Badly formatted string'
|
||||
|
||||
msgid "Invalid formatted id[] with no translations
|
||||
|
||||
msgctxt "Ctx"
|
||||
msgid "One with var: %s"
|
||||
msgid_plural "Several with vars: %s"
|
||||
|
||||
120
po.go
120
po.go
@@ -2,7 +2,6 @@ package gotext
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/textproto"
|
||||
"os"
|
||||
@@ -46,7 +45,12 @@ func (t *translation) getN(n int) string {
|
||||
}
|
||||
}
|
||||
|
||||
// Return unstranlated plural by default
|
||||
// Return unstranlated singular if corresponding
|
||||
if n == 0 {
|
||||
return t.id
|
||||
}
|
||||
|
||||
// Return untranslated plural by default
|
||||
return t.pluralID
|
||||
}
|
||||
|
||||
@@ -57,7 +61,10 @@ And it's safe for concurrent use by multiple goroutines by using the sync packag
|
||||
|
||||
Example:
|
||||
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create po object
|
||||
@@ -67,13 +74,13 @@ Example:
|
||||
po.ParseFile("/path/to/po/file/translations.po")
|
||||
|
||||
// Get translation
|
||||
println(po.Get("Translate this"))
|
||||
fmt.Println(po.Get("Translate this"))
|
||||
}
|
||||
|
||||
*/
|
||||
type Po struct {
|
||||
// Headers
|
||||
RawHeaders string
|
||||
// Headers storage
|
||||
Headers textproto.MIMEHeader
|
||||
|
||||
// Language header
|
||||
Language string
|
||||
@@ -133,7 +140,6 @@ func (po *Po) ParseFile(f string) {
|
||||
func (po *Po) Parse(str string) {
|
||||
// Lock while parsing
|
||||
po.Lock()
|
||||
defer po.Unlock()
|
||||
|
||||
// Init storage
|
||||
if po.translations == nil {
|
||||
@@ -188,7 +194,7 @@ func (po *Po) Parse(str string) {
|
||||
|
||||
// Multi line strings and headers
|
||||
if strings.HasPrefix(l, "\"") && strings.HasSuffix(l, "\"") {
|
||||
state = po.parseString(l, state)
|
||||
po.parseString(l, state)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -196,6 +202,9 @@ func (po *Po) Parse(str string) {
|
||||
// Save last translation buffer.
|
||||
po.saveBuffer()
|
||||
|
||||
// Unlock to parse headers
|
||||
po.Unlock()
|
||||
|
||||
// Parse headers
|
||||
po.parseHeaders()
|
||||
}
|
||||
@@ -203,8 +212,6 @@ func (po *Po) Parse(str string) {
|
||||
// saveBuffer takes the context and translation buffers
|
||||
// and saves it on the translations collection
|
||||
func (po *Po) saveBuffer() {
|
||||
// If we have something to save...
|
||||
if po.trBuffer.id != "" {
|
||||
// With no context...
|
||||
if po.ctxBuffer == "" {
|
||||
po.translations[po.trBuffer.id] = po.trBuffer
|
||||
@@ -214,14 +221,17 @@ func (po *Po) saveBuffer() {
|
||||
po.contexts[po.ctxBuffer] = make(map[string]*translation)
|
||||
}
|
||||
po.contexts[po.ctxBuffer][po.trBuffer.id] = po.trBuffer
|
||||
}
|
||||
|
||||
// Flush buffer
|
||||
po.trBuffer = newTranslation()
|
||||
// Cleanup current context buffer if needed
|
||||
if po.trBuffer.id != "" {
|
||||
po.ctxBuffer = ""
|
||||
}
|
||||
}
|
||||
|
||||
// Flush translation buffer
|
||||
po.trBuffer = newTranslation()
|
||||
}
|
||||
|
||||
// parseContext takes a line starting with "msgctxt",
|
||||
// saves the current translation buffer and creates a new context.
|
||||
func (po *Po) parseContext(l string) {
|
||||
@@ -279,70 +289,72 @@ func (po *Po) parseMessage(l string) {
|
||||
|
||||
// parseString takes a well formatted string without prefix
|
||||
// and creates headers or attach multi-line strings when corresponding
|
||||
func (po *Po) parseString(l string, state parseState) parseState {
|
||||
func (po *Po) parseString(l string, state parseState) {
|
||||
clean, _ := strconv.Unquote(l)
|
||||
|
||||
switch state {
|
||||
case msgStr:
|
||||
// Check for multiline from previously set msgid
|
||||
if po.trBuffer.id != "" {
|
||||
// Append to last translation found
|
||||
uq, _ := strconv.Unquote(l)
|
||||
po.trBuffer.trs[len(po.trBuffer.trs)-1] += uq
|
||||
po.trBuffer.trs[len(po.trBuffer.trs)-1] += clean
|
||||
|
||||
}
|
||||
case msgID:
|
||||
// Multiline msgid - Append to current id
|
||||
uq, _ := strconv.Unquote(l)
|
||||
po.trBuffer.id += uq
|
||||
po.trBuffer.id += clean
|
||||
|
||||
case msgIDPlural:
|
||||
// Multiline msgid - Append to current id
|
||||
uq, _ := strconv.Unquote(l)
|
||||
po.trBuffer.pluralID += uq
|
||||
po.trBuffer.pluralID += clean
|
||||
|
||||
case msgCtxt:
|
||||
// Multiline context - Append to current context
|
||||
ctxt, _ := strconv.Unquote(l)
|
||||
po.ctxBuffer += ctxt
|
||||
default:
|
||||
// Otherwise is a header
|
||||
h, _ := strconv.Unquote(strings.TrimSpace(l))
|
||||
po.RawHeaders += h
|
||||
return head
|
||||
}
|
||||
po.ctxBuffer += clean
|
||||
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
// isValidLine checks for line prefixes to detect valid syntax.
|
||||
func (po *Po) isValidLine(l string) bool {
|
||||
// Skip empty lines
|
||||
if l == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check prefix
|
||||
if !strings.HasPrefix(l, "\"") && !strings.HasPrefix(l, "msgctxt") && !strings.HasPrefix(l, "msgid") && !strings.HasPrefix(l, "msgid_plural") && !strings.HasPrefix(l, "msgstr") {
|
||||
return false
|
||||
valid := []string{
|
||||
"\"",
|
||||
"msgctxt",
|
||||
"msgid",
|
||||
"msgid_plural",
|
||||
"msgstr",
|
||||
}
|
||||
|
||||
for _, v := range valid {
|
||||
if strings.HasPrefix(l, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// parseHeaders retrieves data from previously parsed headers
|
||||
func (po *Po) parseHeaders() {
|
||||
// Make sure we end with 2 carriage returns.
|
||||
po.RawHeaders += "\n\n"
|
||||
raw := po.Get("") + "\n\n"
|
||||
|
||||
// Read
|
||||
reader := bufio.NewReader(strings.NewReader(po.RawHeaders))
|
||||
reader := bufio.NewReader(strings.NewReader(raw))
|
||||
tp := textproto.NewReader(reader)
|
||||
|
||||
mimeHeader, err := tp.ReadMIMEHeader()
|
||||
var err error
|
||||
|
||||
// Sync Headers write.
|
||||
po.Lock()
|
||||
defer po.Unlock()
|
||||
|
||||
po.Headers, err = tp.ReadMIMEHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Get/save needed headers
|
||||
po.Language = mimeHeader.Get("Language")
|
||||
po.PluralForms = mimeHeader.Get("Plural-Forms")
|
||||
po.Language = po.Headers.Get("Language")
|
||||
po.PluralForms = po.Headers.Get("Plural-Forms")
|
||||
|
||||
// Parse Plural-Forms formula
|
||||
if po.PluralForms == "" {
|
||||
@@ -415,12 +427,12 @@ func (po *Po) Get(str string, vars ...interface{}) string {
|
||||
|
||||
if po.translations != nil {
|
||||
if _, ok := po.translations[str]; ok {
|
||||
return fmt.Sprintf(po.translations[str].get(), vars...)
|
||||
return printf(po.translations[str].get(), vars...)
|
||||
}
|
||||
}
|
||||
|
||||
// Return the same we received by default
|
||||
return fmt.Sprintf(str, vars...)
|
||||
return printf(str, vars...)
|
||||
}
|
||||
|
||||
// GetN retrieves the (N)th plural form of translation for the given string.
|
||||
@@ -432,14 +444,14 @@ func (po *Po) GetN(str, plural string, n int, vars ...interface{}) string {
|
||||
|
||||
if po.translations != nil {
|
||||
if _, ok := po.translations[str]; ok {
|
||||
return fmt.Sprintf(po.translations[str].getN(po.pluralForm(n)), vars...)
|
||||
return printf(po.translations[str].getN(po.pluralForm(n)), vars...)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return fmt.Sprintf(str, vars...)
|
||||
return printf(str, vars...)
|
||||
}
|
||||
return fmt.Sprintf(plural, vars...)
|
||||
return printf(plural, vars...)
|
||||
}
|
||||
|
||||
// GetC retrieves the corresponding translation for a given string in the given context.
|
||||
@@ -453,14 +465,14 @@ func (po *Po) GetC(str, ctx string, vars ...interface{}) string {
|
||||
if _, ok := po.contexts[ctx]; ok {
|
||||
if po.contexts[ctx] != nil {
|
||||
if _, ok := po.contexts[ctx][str]; ok {
|
||||
return fmt.Sprintf(po.contexts[ctx][str].get(), vars...)
|
||||
return printf(po.contexts[ctx][str].get(), vars...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the string we received by default
|
||||
return fmt.Sprintf(str, vars...)
|
||||
return printf(str, vars...)
|
||||
}
|
||||
|
||||
// GetNC retrieves the (N)th plural form of translation for the given string in the given context.
|
||||
@@ -474,14 +486,14 @@ func (po *Po) GetNC(str, plural string, n int, ctx string, vars ...interface{})
|
||||
if _, ok := po.contexts[ctx]; ok {
|
||||
if po.contexts[ctx] != nil {
|
||||
if _, ok := po.contexts[ctx][str]; ok {
|
||||
return fmt.Sprintf(po.contexts[ctx][str].getN(po.pluralForm(n)), vars...)
|
||||
return printf(po.contexts[ctx][str].getN(po.pluralForm(n)), vars...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return fmt.Sprintf(str, vars...)
|
||||
return printf(str, vars...)
|
||||
}
|
||||
return fmt.Sprintf(plural, vars...)
|
||||
return printf(plural, vars...)
|
||||
}
|
||||
|
||||
86
po_test.go
86
po_test.go
@@ -9,6 +9,9 @@ import (
|
||||
func TestPo(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
@@ -48,14 +51,6 @@ msgstr[0] "This one is the singular: %s"
|
||||
msgstr[1] "This one is the plural: %s"
|
||||
msgstr[2] "And this is the second plural form: %s"
|
||||
|
||||
msgid "This one has invalid syntax translations"
|
||||
msgid_plural "Plural index"
|
||||
msgstr[abc] "Wrong index"
|
||||
msgstr[1 "Forgot to close brackets"
|
||||
msgstr[0] "Badly formatted string'
|
||||
|
||||
msgid "Invalid formatted id[] with no translations
|
||||
|
||||
msgctxt "Ctx"
|
||||
msgid "One with var: %s"
|
||||
msgid_plural "Several with vars: %s"
|
||||
@@ -75,11 +70,11 @@ msgstr ""
|
||||
msgid "Empty plural form singular"
|
||||
msgid_plural "Empty plural form"
|
||||
msgstr[0] "Singular translated"
|
||||
msgstr[1] "
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "More"
|
||||
msgstr "More translation"
|
||||
"
|
||||
|
||||
`
|
||||
|
||||
// Write PO content to file
|
||||
@@ -152,17 +147,6 @@ msgstr "More translation"
|
||||
t.Errorf("Expected 'This are tests' but got '%s'", tr)
|
||||
}
|
||||
|
||||
// Test syntax error parsed translations
|
||||
tr = po.Get("This one has invalid syntax translations")
|
||||
if tr != "This one has invalid syntax translations" {
|
||||
t.Errorf("Expected 'This one has invalid syntax translations' but got '%s'", tr)
|
||||
}
|
||||
|
||||
tr = po.GetN("This one has invalid syntax translations", "This are tests", 4)
|
||||
if tr != "Plural index" {
|
||||
t.Errorf("Expected 'Plural index' but got '%s'", tr)
|
||||
}
|
||||
|
||||
// Test context translations
|
||||
v = "Test"
|
||||
tr = po.GetC("One with var: %s", "Ctx", v)
|
||||
@@ -214,9 +198,42 @@ msgstr "More translation"
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlural(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
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)
|
||||
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 TestPoHeaders(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
@@ -246,9 +263,30 @@ msgstr "Translated example"
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingPoHeadersSupport(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid "Example"
|
||||
msgstr "Translated example"
|
||||
`
|
||||
|
||||
// Create po object
|
||||
po := new(Po)
|
||||
|
||||
// Parse
|
||||
po.Parse(str)
|
||||
|
||||
// Check translation expected
|
||||
if po.Get("Example") != "Translated example" {
|
||||
t.Errorf("Expected 'Translated example' but got '%s'", po.Get("Example"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluralFormsSingle(t *testing.T) {
|
||||
// Single form
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=1; plural=0;"
|
||||
|
||||
# Some comment
|
||||
@@ -292,6 +330,8 @@ msgstr[3] "Plural form 3"
|
||||
func TestPluralForms2(t *testing.T) {
|
||||
// 2 forms
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;"
|
||||
|
||||
# Some comment
|
||||
@@ -331,6 +371,8 @@ msgstr[3] "Plural form 3"
|
||||
func TestPluralForms3(t *testing.T) {
|
||||
// 3 forms
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;"
|
||||
|
||||
# Some comment
|
||||
@@ -378,6 +420,8 @@ msgstr[3] "Plural form 3"
|
||||
func TestPluralFormsSpecial(t *testing.T) {
|
||||
// 3 forms special
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=3;"
|
||||
"plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
|
||||
|
||||
|
||||
37
vendor/github.com/mattn/kinako/README.md
generated
vendored
Normal file
37
vendor/github.com/mattn/kinako/README.md
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# kinako
|
||||
|
||||
Kinako is small VM written in Go.
|
||||
|
||||

|
||||
|
||||
(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)
|
||||
18
vendor/github.com/mattn/kinako/_example/main.go
generated
vendored
Normal file
18
vendor/github.com/mattn/kinako/_example/main.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
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)
|
||||
}
|
||||
8
vendor/github.com/mattn/kinako/ast/expr.go
generated
vendored
8
vendor/github.com/mattn/kinako/ast/expr.go
generated
vendored
@@ -75,6 +75,14 @@ type TernaryOpExpr struct {
|
||||
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
|
||||
|
||||
BIN
vendor/github.com/mattn/kinako/kinako.png
generated
vendored
Normal file
BIN
vendor/github.com/mattn/kinako/kinako.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 450 KiB |
196
vendor/github.com/mattn/kinako/parser/parser.go
generated
vendored
196
vendor/github.com/mattn/kinako/parser/parser.go
generated
vendored
@@ -8,13 +8,14 @@ import (
|
||||
"github.com/mattn/kinako/ast"
|
||||
)
|
||||
|
||||
//line parser.go.y:15
|
||||
//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
|
||||
@@ -82,106 +83,107 @@ const yyEofCode = 1
|
||||
const yyErrCode = 2
|
||||
const yyInitialStackSize = 16
|
||||
|
||||
//line parser.go.y:194
|
||||
//line parser.go.y:213
|
||||
|
||||
//line yacctab:1
|
||||
var yyExca = [...]int{
|
||||
-1, 1,
|
||||
1, -1,
|
||||
-2, 0,
|
||||
-1, 49,
|
||||
-1, 50,
|
||||
7, 0,
|
||||
8, 0,
|
||||
-2, 20,
|
||||
-1, 50,
|
||||
-1, 51,
|
||||
7, 0,
|
||||
8, 0,
|
||||
-2, 21,
|
||||
}
|
||||
|
||||
const yyNprod = 36
|
||||
const yyNprod = 40
|
||||
const yyPrivate = 57344
|
||||
|
||||
var yyTokenNames []string
|
||||
var yyStates []string
|
||||
|
||||
const yyLast = 249
|
||||
const yyLast = 251
|
||||
|
||||
var yyAct = [...]int{
|
||||
|
||||
9, 6, 7, 33, 35, 4, 22, 23, 3, 18,
|
||||
24, 25, 26, 37, 38, 39, 2, 40, 33, 35,
|
||||
17, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
||||
51, 52, 53, 54, 55, 56, 57, 58, 27, 28,
|
||||
30, 32, 34, 36, 8, 1, 21, 60, 0, 29,
|
||||
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, 61, 0, 41, 0, 33, 35, 27, 28, 30,
|
||||
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, 59, 33, 35, 27, 28, 30, 32,
|
||||
34, 36, 0, 20, 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, 34,
|
||||
36, 0, 0, 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,
|
||||
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, 216, -35, -35, -1000, -1000, -1000, -1000, 89,
|
||||
-1000, -1000, 216, 216, 216, -1000, 216, -1000, 196, -1000,
|
||||
216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
|
||||
216, 216, 216, 216, 216, 216, 216, -31, -31, -31,
|
||||
60, -1000, 118, 31, 203, 203, -31, -31, -31, 189,
|
||||
189, -16, -16, -16, -16, 118, 147, 118, 169, -1000,
|
||||
216, 118,
|
||||
-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, 45, 8, 44, 0, 16, 5, 55,
|
||||
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,
|
||||
5, 5, 6, 6, 7, 7,
|
||||
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,
|
||||
0, 1, 1, 2, 1, 1,
|
||||
4, 0, 1, 3, 0, 1, 1, 2, 1, 1,
|
||||
}
|
||||
var yyChk = [...]int{
|
||||
|
||||
-1000, -1, -5, -2, -6, -7, 36, 37, -3, -4,
|
||||
4, 5, 23, 30, 31, 6, 32, -5, -6, -7,
|
||||
-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, -4, -4, -4,
|
||||
-4, -3, -4, -4, -4, -4, -4, -4, -4, -4,
|
||||
-4, -4, -4, -4, -4, -4, -4, -4, -4, 33,
|
||||
16, -4,
|
||||
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{
|
||||
|
||||
30, -2, 1, 30, 31, 32, 34, 35, 3, 6,
|
||||
7, 8, 0, 0, 0, 12, 0, 2, 31, 33,
|
||||
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, 9, 10, 11,
|
||||
0, 4, 5, 0, 15, 16, 17, 18, 19, -2,
|
||||
-2, 22, 23, 24, 25, 26, 27, 28, 29, 14,
|
||||
0, 13,
|
||||
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{
|
||||
|
||||
@@ -547,19 +549,19 @@ yydefault:
|
||||
|
||||
case 1:
|
||||
yyDollar = yyS[yypt-1 : yypt+1]
|
||||
//line parser.go.y:43
|
||||
//line parser.go.y:45
|
||||
{
|
||||
yyVAL.compstmt = nil
|
||||
}
|
||||
case 2:
|
||||
yyDollar = yyS[yypt-2 : yypt+1]
|
||||
//line parser.go.y:47
|
||||
//line parser.go.y:49
|
||||
{
|
||||
yyVAL.compstmt = yyDollar[1].stmts
|
||||
}
|
||||
case 3:
|
||||
yyDollar = yyS[yypt-2 : yypt+1]
|
||||
//line parser.go.y:53
|
||||
//line parser.go.y:55
|
||||
{
|
||||
yyVAL.stmts = []ast.Stmt{yyDollar[2].stmt}
|
||||
if l, ok := yylex.(*Lexer); ok {
|
||||
@@ -568,7 +570,7 @@ yydefault:
|
||||
}
|
||||
case 4:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
//line parser.go.y:60
|
||||
//line parser.go.y:62
|
||||
{
|
||||
if yyDollar[3].stmt != nil {
|
||||
yyVAL.stmts = append(yyDollar[1].stmts, yyDollar[3].stmt)
|
||||
@@ -579,172 +581,196 @@ yydefault:
|
||||
}
|
||||
case 5:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
//line parser.go.y:71
|
||||
//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:75
|
||||
//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:81
|
||||
//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:85
|
||||
//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:89
|
||||
//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:93
|
||||
//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:97
|
||||
//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:101
|
||||
//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:105
|
||||
//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:109
|
||||
//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:113
|
||||
//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:117
|
||||
//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:121
|
||||
//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:125
|
||||
//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:129
|
||||
//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:133
|
||||
//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:137
|
||||
//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:141
|
||||
//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:145
|
||||
//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:149
|
||||
//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:153
|
||||
//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:157
|
||||
//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:161
|
||||
//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:165
|
||||
//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:169
|
||||
//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:179
|
||||
//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:182
|
||||
//line parser.go.y:201
|
||||
{
|
||||
}
|
||||
case 34:
|
||||
case 38:
|
||||
yyDollar = yyS[yypt-1 : yypt+1]
|
||||
//line parser.go.y:187
|
||||
//line parser.go.y:206
|
||||
{
|
||||
}
|
||||
case 35:
|
||||
case 39:
|
||||
yyDollar = yyS[yypt-1 : yypt+1]
|
||||
//line parser.go.y:190
|
||||
//line parser.go.y:209
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
19
vendor/github.com/mattn/kinako/parser/parser.go.y
generated
vendored
19
vendor/github.com/mattn/kinako/parser/parser.go.y
generated
vendored
@@ -11,12 +11,14 @@ import (
|
||||
%type<stmts> stmts
|
||||
%type<stmt> stmt
|
||||
%type<expr> expr
|
||||
%type<exprs> 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
|
||||
@@ -169,6 +171,23 @@ 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
|
||||
|
||||
469
vendor/github.com/mattn/kinako/parser/y.output
generated
vendored
469
vendor/github.com/mattn/kinako/parser/y.output
generated
vendored
@@ -1,11 +1,11 @@
|
||||
|
||||
state 0
|
||||
$accept: .compstmt $end
|
||||
opt_terms: . (30)
|
||||
opt_terms: . (34)
|
||||
|
||||
';' shift 6
|
||||
'\n' shift 7
|
||||
. reduce 30 (src line 173)
|
||||
. reduce 34 (src line 192)
|
||||
|
||||
compstmt goto 1
|
||||
stmts goto 3
|
||||
@@ -31,7 +31,7 @@ state 2
|
||||
'!' shift 13
|
||||
'^' shift 14
|
||||
'(' shift 16
|
||||
. reduce 1 (src line 42)
|
||||
. reduce 1 (src line 44)
|
||||
|
||||
stmt goto 8
|
||||
expr goto 9
|
||||
@@ -39,48 +39,48 @@ state 2
|
||||
state 3
|
||||
compstmt: stmts.opt_terms
|
||||
stmts: stmts.terms stmt
|
||||
opt_terms: . (30)
|
||||
opt_terms: . (34)
|
||||
|
||||
';' shift 6
|
||||
'\n' shift 7
|
||||
. reduce 30 (src line 173)
|
||||
. reduce 34 (src line 192)
|
||||
|
||||
opt_terms goto 17
|
||||
terms goto 18
|
||||
term goto 5
|
||||
|
||||
state 4
|
||||
opt_terms: terms. (31)
|
||||
opt_terms: terms. (35)
|
||||
terms: terms.term
|
||||
|
||||
';' shift 6
|
||||
'\n' shift 7
|
||||
. reduce 31 (src line 174)
|
||||
. reduce 35 (src line 193)
|
||||
|
||||
term goto 19
|
||||
|
||||
state 5
|
||||
terms: term. (32)
|
||||
terms: term. (36)
|
||||
|
||||
. reduce 32 (src line 178)
|
||||
. reduce 36 (src line 197)
|
||||
|
||||
|
||||
state 6
|
||||
term: ';'. (34)
|
||||
term: ';'. (38)
|
||||
|
||||
. reduce 34 (src line 186)
|
||||
. reduce 38 (src line 205)
|
||||
|
||||
|
||||
state 7
|
||||
term: '\n'. (35)
|
||||
term: '\n'. (39)
|
||||
|
||||
. reduce 35 (src line 189)
|
||||
. reduce 39 (src line 208)
|
||||
|
||||
|
||||
state 8
|
||||
stmts: opt_terms stmt. (3)
|
||||
|
||||
. reduce 3 (src line 51)
|
||||
. reduce 3 (src line 53)
|
||||
|
||||
|
||||
state 9
|
||||
@@ -120,19 +120,21 @@ state 9
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 6 (src line 74)
|
||||
. reduce 6 (src line 76)
|
||||
|
||||
|
||||
state 10
|
||||
expr: IDENT. (7)
|
||||
expr: IDENT.'(' exprs ')'
|
||||
|
||||
. reduce 7 (src line 79)
|
||||
'(' shift 37
|
||||
. reduce 7 (src line 81)
|
||||
|
||||
|
||||
state 11
|
||||
expr: NUMBER. (8)
|
||||
|
||||
. reduce 8 (src line 84)
|
||||
. reduce 8 (src line 86)
|
||||
|
||||
|
||||
state 12
|
||||
@@ -147,7 +149,7 @@ state 12
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 37
|
||||
expr goto 38
|
||||
|
||||
state 13
|
||||
expr: '!'.expr
|
||||
@@ -161,7 +163,7 @@ state 13
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 38
|
||||
expr goto 39
|
||||
|
||||
state 14
|
||||
expr: '^'.expr
|
||||
@@ -175,12 +177,12 @@ state 14
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 39
|
||||
expr goto 40
|
||||
|
||||
state 15
|
||||
expr: STRING. (12)
|
||||
|
||||
. reduce 12 (src line 100)
|
||||
. reduce 12 (src line 102)
|
||||
|
||||
|
||||
state 16
|
||||
@@ -195,17 +197,17 @@ state 16
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 40
|
||||
expr goto 41
|
||||
|
||||
state 17
|
||||
compstmt: stmts opt_terms. (2)
|
||||
|
||||
. reduce 2 (src line 46)
|
||||
. reduce 2 (src line 48)
|
||||
|
||||
|
||||
state 18
|
||||
stmts: stmts terms.stmt
|
||||
opt_terms: terms. (31)
|
||||
opt_terms: terms. (35)
|
||||
terms: terms.term
|
||||
|
||||
IDENT shift 10
|
||||
@@ -217,16 +219,16 @@ state 18
|
||||
'(' shift 16
|
||||
';' shift 6
|
||||
'\n' shift 7
|
||||
. reduce 31 (src line 174)
|
||||
. reduce 35 (src line 193)
|
||||
|
||||
stmt goto 41
|
||||
stmt goto 42
|
||||
expr goto 9
|
||||
term goto 19
|
||||
|
||||
state 19
|
||||
terms: terms term. (33)
|
||||
terms: terms term. (37)
|
||||
|
||||
. reduce 33 (src line 181)
|
||||
. reduce 37 (src line 200)
|
||||
|
||||
|
||||
state 20
|
||||
@@ -241,7 +243,7 @@ state 20
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 42
|
||||
expr goto 43
|
||||
|
||||
state 21
|
||||
expr: expr '?'.expr ':' expr
|
||||
@@ -255,7 +257,7 @@ state 21
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 43
|
||||
expr goto 44
|
||||
|
||||
state 22
|
||||
expr: expr '+'.expr
|
||||
@@ -269,7 +271,7 @@ state 22
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 44
|
||||
expr goto 45
|
||||
|
||||
state 23
|
||||
expr: expr '-'.expr
|
||||
@@ -283,7 +285,7 @@ state 23
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 45
|
||||
expr goto 46
|
||||
|
||||
state 24
|
||||
expr: expr '*'.expr
|
||||
@@ -297,7 +299,7 @@ state 24
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 46
|
||||
expr goto 47
|
||||
|
||||
state 25
|
||||
expr: expr '/'.expr
|
||||
@@ -311,7 +313,7 @@ state 25
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 47
|
||||
expr goto 48
|
||||
|
||||
state 26
|
||||
expr: expr '%'.expr
|
||||
@@ -325,7 +327,7 @@ state 26
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 48
|
||||
expr goto 49
|
||||
|
||||
state 27
|
||||
expr: expr EQEQ.expr
|
||||
@@ -339,7 +341,7 @@ state 27
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 49
|
||||
expr goto 50
|
||||
|
||||
state 28
|
||||
expr: expr NEQ.expr
|
||||
@@ -353,7 +355,7 @@ state 28
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 50
|
||||
expr goto 51
|
||||
|
||||
state 29
|
||||
expr: expr '>'.expr
|
||||
@@ -367,7 +369,7 @@ state 29
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 51
|
||||
expr goto 52
|
||||
|
||||
state 30
|
||||
expr: expr GE.expr
|
||||
@@ -381,7 +383,7 @@ state 30
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 52
|
||||
expr goto 53
|
||||
|
||||
state 31
|
||||
expr: expr '<'.expr
|
||||
@@ -395,7 +397,7 @@ state 31
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 53
|
||||
expr goto 54
|
||||
|
||||
state 32
|
||||
expr: expr LE.expr
|
||||
@@ -409,7 +411,7 @@ state 32
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 54
|
||||
expr goto 55
|
||||
|
||||
state 33
|
||||
expr: expr '|'.expr
|
||||
@@ -423,7 +425,7 @@ state 33
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 55
|
||||
expr goto 56
|
||||
|
||||
state 34
|
||||
expr: expr OROR.expr
|
||||
@@ -437,7 +439,7 @@ state 34
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 56
|
||||
expr goto 57
|
||||
|
||||
state 35
|
||||
expr: expr '&'.expr
|
||||
@@ -451,7 +453,7 @@ state 35
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 57
|
||||
expr goto 58
|
||||
|
||||
state 36
|
||||
expr: expr ANDAND.expr
|
||||
@@ -465,11 +467,27 @@ state 36
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 58
|
||||
expr goto 59
|
||||
|
||||
37: shift/reduce conflict (shift 33(0), red'n 9(10)) on '|'
|
||||
37: shift/reduce conflict (shift 35(0), red'n 9(10)) on '&'
|
||||
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
|
||||
@@ -490,12 +508,12 @@ state 37
|
||||
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 9 (src line 88)
|
||||
. reduce 9 (src line 90)
|
||||
|
||||
|
||||
38: shift/reduce conflict (shift 33(0), red'n 10(10)) on '|'
|
||||
38: shift/reduce conflict (shift 35(0), red'n 10(10)) on '&'
|
||||
state 38
|
||||
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
|
||||
@@ -516,12 +534,12 @@ state 38
|
||||
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 10 (src line 92)
|
||||
. reduce 10 (src line 94)
|
||||
|
||||
|
||||
39: shift/reduce conflict (shift 33(0), red'n 11(10)) on '|'
|
||||
39: shift/reduce conflict (shift 35(0), red'n 11(10)) on '&'
|
||||
state 39
|
||||
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
|
||||
@@ -542,10 +560,10 @@ state 39
|
||||
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 11 (src line 96)
|
||||
. reduce 11 (src line 98)
|
||||
|
||||
|
||||
state 40
|
||||
state 41
|
||||
expr: expr.'?' expr ':' expr
|
||||
expr: '(' expr.')'
|
||||
expr: expr.'+' expr
|
||||
@@ -578,19 +596,19 @@ state 40
|
||||
'*' shift 24
|
||||
'/' shift 25
|
||||
'%' shift 26
|
||||
')' shift 59
|
||||
')' shift 62
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. error
|
||||
|
||||
|
||||
state 41
|
||||
state 42
|
||||
stmts: stmts terms stmt. (4)
|
||||
|
||||
. reduce 4 (src line 59)
|
||||
. reduce 4 (src line 61)
|
||||
|
||||
|
||||
state 42
|
||||
state 43
|
||||
stmt: expr '=' expr. (5)
|
||||
expr: expr.'?' expr ':' expr
|
||||
expr: expr.'+' expr
|
||||
@@ -625,10 +643,10 @@ state 42
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 5 (src line 69)
|
||||
. reduce 5 (src line 71)
|
||||
|
||||
|
||||
state 43
|
||||
state 44
|
||||
expr: expr.'?' expr ':' expr
|
||||
expr: expr '?' expr.':' expr
|
||||
expr: expr.'+' expr
|
||||
@@ -654,7 +672,7 @@ state 43
|
||||
OROR shift 34
|
||||
ANDAND shift 36
|
||||
'?' shift 21
|
||||
':' shift 60
|
||||
':' shift 63
|
||||
'>' shift 29
|
||||
'<' shift 31
|
||||
'+' shift 22
|
||||
@@ -667,9 +685,9 @@ state 43
|
||||
. error
|
||||
|
||||
|
||||
44: shift/reduce conflict (shift 33(0), red'n 15(8)) on '|'
|
||||
44: shift/reduce conflict (shift 35(0), red'n 15(8)) on '&'
|
||||
state 44
|
||||
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)
|
||||
@@ -693,12 +711,12 @@ state 44
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 15 (src line 112)
|
||||
. reduce 15 (src line 114)
|
||||
|
||||
|
||||
45: shift/reduce conflict (shift 33(0), red'n 16(8)) on '|'
|
||||
45: shift/reduce conflict (shift 35(0), red'n 16(8)) on '&'
|
||||
state 45
|
||||
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
|
||||
@@ -722,12 +740,12 @@ state 45
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 16 (src line 116)
|
||||
. reduce 16 (src line 118)
|
||||
|
||||
|
||||
46: shift/reduce conflict (shift 33(0), red'n 17(9)) on '|'
|
||||
46: shift/reduce conflict (shift 35(0), red'n 17(9)) on '&'
|
||||
state 46
|
||||
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
|
||||
@@ -748,12 +766,12 @@ state 46
|
||||
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 17 (src line 120)
|
||||
. reduce 17 (src line 122)
|
||||
|
||||
|
||||
47: shift/reduce conflict (shift 33(0), red'n 18(9)) on '|'
|
||||
47: shift/reduce conflict (shift 35(0), red'n 18(9)) on '&'
|
||||
state 47
|
||||
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
|
||||
@@ -774,12 +792,12 @@ state 47
|
||||
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 18 (src line 124)
|
||||
. reduce 18 (src line 126)
|
||||
|
||||
|
||||
48: shift/reduce conflict (shift 33(0), red'n 19(9)) on '|'
|
||||
48: shift/reduce conflict (shift 35(0), red'n 19(9)) on '&'
|
||||
state 48
|
||||
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
|
||||
@@ -800,12 +818,12 @@ state 48
|
||||
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 19 (src line 128)
|
||||
. reduce 19 (src line 130)
|
||||
|
||||
|
||||
49: shift/reduce conflict (shift 33(0), red'n 20(6)) on '|'
|
||||
49: shift/reduce conflict (shift 35(0), red'n 20(6)) on '&'
|
||||
state 49
|
||||
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
|
||||
@@ -837,12 +855,12 @@ state 49
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 20 (src line 132)
|
||||
. reduce 20 (src line 134)
|
||||
|
||||
|
||||
50: shift/reduce conflict (shift 33(0), red'n 21(6)) on '|'
|
||||
50: shift/reduce conflict (shift 35(0), red'n 21(6)) on '&'
|
||||
state 50
|
||||
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
|
||||
@@ -874,12 +892,12 @@ state 50
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 21 (src line 136)
|
||||
. reduce 21 (src line 138)
|
||||
|
||||
|
||||
51: shift/reduce conflict (shift 33(0), red'n 22(7)) on '|'
|
||||
51: shift/reduce conflict (shift 35(0), red'n 22(7)) on '&'
|
||||
state 51
|
||||
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
|
||||
@@ -905,12 +923,12 @@ state 51
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 22 (src line 140)
|
||||
. reduce 22 (src line 142)
|
||||
|
||||
|
||||
52: shift/reduce conflict (shift 33(0), red'n 23(7)) on '|'
|
||||
52: shift/reduce conflict (shift 35(0), red'n 23(7)) on '&'
|
||||
state 52
|
||||
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
|
||||
@@ -936,12 +954,12 @@ state 52
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 23 (src line 144)
|
||||
. reduce 23 (src line 146)
|
||||
|
||||
|
||||
53: shift/reduce conflict (shift 33(0), red'n 24(7)) on '|'
|
||||
53: shift/reduce conflict (shift 35(0), red'n 24(7)) on '&'
|
||||
state 53
|
||||
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
|
||||
@@ -967,12 +985,12 @@ state 53
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 24 (src line 148)
|
||||
. reduce 24 (src line 150)
|
||||
|
||||
|
||||
54: shift/reduce conflict (shift 33(0), red'n 25(7)) on '|'
|
||||
54: shift/reduce conflict (shift 35(0), red'n 25(7)) on '&'
|
||||
state 54
|
||||
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
|
||||
@@ -998,26 +1016,26 @@ state 54
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 25 (src line 152)
|
||||
. reduce 25 (src line 154)
|
||||
|
||||
|
||||
55: shift/reduce conflict (shift 27(6), red'n 26(0)) on EQEQ
|
||||
55: shift/reduce conflict (shift 28(6), red'n 26(0)) on NEQ
|
||||
55: shift/reduce conflict (shift 30(7), red'n 26(0)) on GE
|
||||
55: shift/reduce conflict (shift 32(7), red'n 26(0)) on LE
|
||||
55: shift/reduce conflict (shift 34(3), red'n 26(0)) on OROR
|
||||
55: shift/reduce conflict (shift 36(4), red'n 26(0)) on ANDAND
|
||||
55: shift/reduce conflict (shift 21(2), red'n 26(0)) on '?'
|
||||
55: shift/reduce conflict (shift 29(7), red'n 26(0)) on '>'
|
||||
55: shift/reduce conflict (shift 31(7), red'n 26(0)) on '<'
|
||||
55: shift/reduce conflict (shift 22(8), red'n 26(0)) on '+'
|
||||
55: shift/reduce conflict (shift 23(8), red'n 26(0)) on '-'
|
||||
55: shift/reduce conflict (shift 24(9), red'n 26(0)) on '*'
|
||||
55: shift/reduce conflict (shift 25(9), red'n 26(0)) on '/'
|
||||
55: shift/reduce conflict (shift 26(9), red'n 26(0)) on '%'
|
||||
55: shift/reduce conflict (shift 33(0), red'n 26(0)) on '|'
|
||||
55: shift/reduce conflict (shift 35(0), red'n 26(0)) on '&'
|
||||
state 55
|
||||
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
|
||||
@@ -1052,12 +1070,12 @@ state 55
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 26 (src line 156)
|
||||
. reduce 26 (src line 158)
|
||||
|
||||
|
||||
56: shift/reduce conflict (shift 33(0), red'n 27(3)) on '|'
|
||||
56: shift/reduce conflict (shift 35(0), red'n 27(3)) on '&'
|
||||
state 56
|
||||
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
|
||||
@@ -1090,26 +1108,26 @@ state 56
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 27 (src line 160)
|
||||
. reduce 27 (src line 162)
|
||||
|
||||
|
||||
57: shift/reduce conflict (shift 27(6), red'n 28(0)) on EQEQ
|
||||
57: shift/reduce conflict (shift 28(6), red'n 28(0)) on NEQ
|
||||
57: shift/reduce conflict (shift 30(7), red'n 28(0)) on GE
|
||||
57: shift/reduce conflict (shift 32(7), red'n 28(0)) on LE
|
||||
57: shift/reduce conflict (shift 34(3), red'n 28(0)) on OROR
|
||||
57: shift/reduce conflict (shift 36(4), red'n 28(0)) on ANDAND
|
||||
57: shift/reduce conflict (shift 21(2), red'n 28(0)) on '?'
|
||||
57: shift/reduce conflict (shift 29(7), red'n 28(0)) on '>'
|
||||
57: shift/reduce conflict (shift 31(7), red'n 28(0)) on '<'
|
||||
57: shift/reduce conflict (shift 22(8), red'n 28(0)) on '+'
|
||||
57: shift/reduce conflict (shift 23(8), red'n 28(0)) on '-'
|
||||
57: shift/reduce conflict (shift 24(9), red'n 28(0)) on '*'
|
||||
57: shift/reduce conflict (shift 25(9), red'n 28(0)) on '/'
|
||||
57: shift/reduce conflict (shift 26(9), red'n 28(0)) on '%'
|
||||
57: shift/reduce conflict (shift 33(0), red'n 28(0)) on '|'
|
||||
57: shift/reduce conflict (shift 35(0), red'n 28(0)) on '&'
|
||||
state 57
|
||||
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
|
||||
@@ -1144,12 +1162,12 @@ state 57
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 28 (src line 164)
|
||||
. reduce 28 (src line 166)
|
||||
|
||||
|
||||
58: shift/reduce conflict (shift 33(0), red'n 29(4)) on '|'
|
||||
58: shift/reduce conflict (shift 35(0), red'n 29(4)) on '&'
|
||||
state 58
|
||||
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
|
||||
@@ -1181,16 +1199,63 @@ state 58
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 29 (src line 168)
|
||||
|
||||
|
||||
state 59
|
||||
expr: '(' expr ')'. (14)
|
||||
|
||||
. reduce 14 (src line 108)
|
||||
. 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
|
||||
@@ -1202,11 +1267,31 @@ state 60
|
||||
'(' shift 16
|
||||
. error
|
||||
|
||||
expr goto 61
|
||||
expr goto 66
|
||||
|
||||
61: shift/reduce conflict (shift 33(0), red'n 13(2)) on '|'
|
||||
61: shift/reduce conflict (shift 35(0), red'n 13(2)) on '&'
|
||||
state 61
|
||||
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
|
||||
@@ -1241,18 +1326,56 @@ state 61
|
||||
'%' shift 26
|
||||
'|' shift 33
|
||||
'&' shift 35
|
||||
. reduce 13 (src line 104)
|
||||
. reduce 13 (src line 106)
|
||||
|
||||
|
||||
37 terminals, 8 nonterminals
|
||||
36 grammar rules, 62/8000 states
|
||||
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
|
||||
57 working sets used
|
||||
memory: parser 35/120000
|
||||
46 extra closures
|
||||
390 shift entries, 5 exceptions
|
||||
34 goto entries
|
||||
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 249/120000
|
||||
249 table entries, 78 zero
|
||||
maximum spread: 37, maximum offset: 60
|
||||
Optimizer space used: output 251/30000
|
||||
251 table entries, 74 zero
|
||||
maximum spread: 37, maximum offset: 65
|
||||
|
||||
83
vendor/github.com/mattn/kinako/vm/vm.go
generated
vendored
83
vendor/github.com/mattn/kinako/vm/vm.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -39,14 +40,6 @@ func (e *Error) Error() string {
|
||||
// Func is function interface to reflect functions internaly.
|
||||
type Func func(args ...reflect.Value) (reflect.Value, error)
|
||||
|
||||
func (f Func) String() string {
|
||||
return fmt.Sprintf("[Func: %p]", f)
|
||||
}
|
||||
|
||||
func ToFunc(f Func) reflect.Value {
|
||||
return reflect.ValueOf(f)
|
||||
}
|
||||
|
||||
// Run executes statements in the specified environment.
|
||||
func Run(stmts []ast.Stmt, env *Env) (reflect.Value, error) {
|
||||
rv := NilValue
|
||||
@@ -386,6 +379,80 @@ func invokeExpr(expr ast.Expr, env *Env) (reflect.Value, error) {
|
||||
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 {
|
||||
|
||||
54
vendor/github.com/mattn/kinako/vm/vm_test.go
generated
vendored
Normal file
54
vendor/github.com/mattn/kinako/vm/vm_test.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user