-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathmain.go
155 lines (134 loc) · 4.32 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"strings"
"github.com/huderlem/poryscript/emitter"
"github.com/huderlem/poryscript/lexer"
"github.com/huderlem/poryscript/parser"
)
const version = "3.5.1"
type mapOption map[string]string
func (opt mapOption) String() string {
return ""
}
func (opt mapOption) Set(value string) error {
result := strings.SplitN(value, "=", 2)
if len(result) != 2 {
return fmt.Errorf("expected key-value option to be separate by '=', but got '%s' instead", value)
}
opt[result[0]] = result[1]
return nil
}
type options struct {
inputFilepath string
outputFilepath string
commandConfigFilepath string
fontConfigFilepath string
defaultFontID string
maxLineLength int
optimize bool
enableLineMarkers bool
compileSwitches map[string]string
}
func parseOptions() options {
helpPtr := flag.Bool("h", false, "show poryscript help information")
versionPtr := flag.Bool("v", false, "show version of poryscript")
inputPtr := flag.String("i", "", "input poryscript file (leave empty to read from standard input)")
outputPtr := flag.String("o", "", "output script file (leave empty to write to standard output)")
commandConfigPtr := flag.String("cc", "command_config.json", "command config JSON file")
fontsPtr := flag.String("fc", "font_config.json", "font config JSON file")
fontIDPtr := flag.String("f", "", "set default font id (leave empty to use default defined in font config file)")
lengthPtr := flag.Int("l", 0, "set default line length in pixels for formatted text (uses font config file for default)")
optimizePtr := flag.Bool("optimize", true, "optimize compiled script size (To disable, use '-optimize=false')")
enableLineMarkersPtr := flag.Bool("lm", true, "include line markers in output (enables more helpful error messages when compiling the ROM). (To disable, use '-lm=false')")
compileSwitches := make(mapOption)
flag.Var(compileSwitches, "s", "set a compile-time switch. Multiple -s options can be set. Example: -s VERSION=RUBY -s LANGUAGE=GERMAN")
flag.Parse()
if *helpPtr {
flag.Usage()
os.Exit(0)
}
if *versionPtr {
fmt.Printf("%s\n", version)
os.Exit(0)
}
return options{
inputFilepath: *inputPtr,
outputFilepath: *outputPtr,
commandConfigFilepath: *commandConfigPtr,
fontConfigFilepath: *fontsPtr,
defaultFontID: *fontIDPtr,
maxLineLength: *lengthPtr,
optimize: *optimizePtr,
enableLineMarkers: *enableLineMarkersPtr,
compileSwitches: compileSwitches,
}
}
func getInput(filepath string) (string, error) {
var bytes []byte
var err error
if filepath == "" {
bytes, err = ioutil.ReadAll(os.Stdin)
} else {
bytes, err = ioutil.ReadFile(filepath)
}
return string(bytes), err
}
func writeOutput(output string, filepath string) error {
if filepath == "" {
fmt.Print(output)
} else {
f, err := os.Create(filepath)
if err != nil {
return err
}
_, err = io.WriteString(f, output)
if err != nil {
return err
}
}
return nil
}
func readCommandConfig(filepath string) parser.CommandConfig {
var config parser.CommandConfig
if len(filepath) == 0 {
return config
}
bytes, err := ioutil.ReadFile(filepath)
if err != nil {
log.Fatalf("PORYSCRIPT ERROR: Failed to read command config file: %s\n", err.Error())
}
if err := json.Unmarshal(bytes, &config); err != nil {
log.Fatalf("PORYSCRIPT ERROR: Failed to load command config file: %s\n", err.Error())
}
return config
}
func main() {
log.SetFlags(0)
options := parseOptions()
input, err := getInput(options.inputFilepath)
if err != nil {
log.Fatalf("PORYSCRIPT ERROR: %s\n", err.Error())
}
commandConfig := readCommandConfig(options.commandConfigFilepath)
parser := parser.New(lexer.New(input), commandConfig, options.fontConfigFilepath, options.defaultFontID, options.maxLineLength, options.compileSwitches)
program, err := parser.ParseProgram()
if err != nil {
log.Fatalf("PORYSCRIPT ERROR: %s\n", err.Error())
}
emitter := emitter.New(program, options.optimize, options.enableLineMarkers, options.inputFilepath)
result, err := emitter.Emit()
if err != nil {
log.Fatalf("PORYSCRIPT ERROR: %s\n", err.Error())
}
err = writeOutput(result, options.outputFilepath)
if err != nil {
log.Fatalf("PORYSCRIPT ERROR: %s\n", err.Error())
}
}