php2go/main.go

113 lines
2.2 KiB
Go

package main
import (
"errors"
"flag"
"fmt"
"go/format"
"io/ioutil"
"os"
"github.com/z7zmey/php-parser/parser"
"github.com/z7zmey/php-parser/visitor"
"php2go/parseutil"
)
const (
phpVersionMajor = 7
phpVersionMinor = 4
phpVersionPatch = 0
phpVersionExtra = `-php2go`
)
func ConvertFile(filename string) (string, error) {
inputFile, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
namespaces := visitor.NewNamespaceResolver()
// scope := NewScope()
state := conversionState{
importPackages: make(map[string]struct{}),
}
p, err := parser.NewParser([]byte(inputFile), fmt.Sprintf("%d.%d", phpVersionMajor, phpVersionMinor))
if err != nil {
panic(err)
}
// Enable comments extraction
p.WithFreeFloating()
// Parse PHP content
p.Parse()
for _, err := range p.GetErrors() {
return "", errors.New(err.String())
}
n := p.GetRootNode()
// Debug pass: Walk and print JSON...
if fh, err := os.OpenFile(filename+`.parse.json`, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err == nil {
v := visitor.NewPrettyJsonDumper(fh, namespaces)
n.Walk(v)
fh.Close()
}
// Pass 1: Normalise Alt** Stmt types
normaliser := parseutil.MutatingWalker{
EnterNode: normaliseAltCb,
LeaveNode: parseutil.MutatingWalkerNoop,
}
err = normaliser.Walk(&n)
if err != nil {
return "", err
}
// Pass 1.5: Hoist some expressions out of rvalue contexts
err = runHoistPass(&n)
if err != nil {
return "", err
}
// Debug pass: Walk and print JSON...
if fh, err := os.OpenFile(filename+`.parse2.json`, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err == nil {
v := visitor.NewPrettyJsonDumper(fh, namespaces)
n.Walk(v)
fh.Close()
}
// Pass 2: Walk and print (converted)
ret, err := state.convert(n)
if err != nil {
return "", err
}
// Pass 3: Gofmt output
// TODO pass flags to get -s/-r equivalent for more agressive simplification
formatted, err := format.Source([]byte(ret))
if err != nil {
ret += "// Gofmt failed: " + err.Error()
return ret, nil
}
// Done
return string(formatted), nil
}
func main() {
filename := flag.String("InFile", "", "Select file to convert")
flag.Parse()
ret, err := ConvertFile(*filename)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Println(ret)
}