Adds receivers to filter and point structs
This commit is contained in:
parent
5a85f9cc8f
commit
e2b5936197
|
@ -12,3 +12,5 @@
|
|||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Binary from `go build`
|
||||
filtress
|
||||
|
|
|
@ -77,13 +77,6 @@ MOD [op]int
|
|||
|
||||
. . .
|
||||
|
||||
Set fade time:
|
||||
# If set below zero, becomes zero
|
||||
|
||||
FAD [op]int
|
||||
|
||||
. . .
|
||||
|
||||
Doing loops:
|
||||
# The int after BEG represents the number of times to loop
|
||||
# At present, loops may not be nested
|
||||
|
|
69
main.go
69
main.go
|
@ -1,5 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"tildegit.org/sloum/filtress/parser"
|
||||
)
|
||||
|
||||
type point struct {
|
||||
x int
|
||||
y int
|
||||
|
@ -7,21 +16,61 @@ type point struct {
|
|||
maxY int
|
||||
}
|
||||
|
||||
type color int
|
||||
type mode int
|
||||
type filter struct {
|
||||
max int
|
||||
min int
|
||||
val int
|
||||
}
|
||||
|
||||
type filterState struct {
|
||||
red color
|
||||
green color
|
||||
blue color
|
||||
alpha color
|
||||
red filter
|
||||
green filter
|
||||
blue filter
|
||||
alpha filter
|
||||
location point
|
||||
mod mode
|
||||
register int
|
||||
fade uint
|
||||
loop uint
|
||||
mode filter
|
||||
}
|
||||
|
||||
var variables = map[string]int{}
|
||||
|
||||
func openFileFromPath(path string) *os.File {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Handle checking filter file argument
|
||||
flag.Parse()
|
||||
posArgs := flag.Args()
|
||||
if len(posArgs) > 1 || len(posArgs) < 1 {
|
||||
panic(fmt.Sprintf("Input error: Too many positional arguments. Expected one, received %d", len(flag.Args())))
|
||||
}
|
||||
fpath := posArgs[0]
|
||||
fext := strings.ToUpper(filepath.Ext(fpath))
|
||||
_, fname := filepath.Split(fpath)
|
||||
|
||||
if fext != ".FRS" {
|
||||
panic(fmt.Sprintf("Input error: Incorrect filetype. Expected .FRS, received \".%s\"", fext))
|
||||
}
|
||||
|
||||
// Open file and parse
|
||||
fmt.Println("Filtress v0.2.0")
|
||||
filterFile := openFileFromPath(fpath)
|
||||
parser := parser.NewParser(filterFile)
|
||||
fmt.Printf("Parsing file: %s ...\n", fname)
|
||||
tree := parser.Parse()
|
||||
if len(tree.Loops) > 0 {
|
||||
fmt.Printf("File has %d procedures\n", len(tree.Loops))
|
||||
fmt.Println("File is valid")
|
||||
} else {
|
||||
fmt.Println("Invalid input file")
|
||||
}
|
||||
|
||||
fmt.Print(tree)
|
||||
fmt.Println()
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package parse
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -48,11 +48,12 @@ func (s *scanner) unread() {
|
|||
|
||||
|
||||
func (s *scanner) scan() Token {
|
||||
for {
|
||||
char := s.read()
|
||||
|
||||
if isWhitespace(char) {
|
||||
s.unread()
|
||||
return s.scanWhitespace()
|
||||
s.scanWhitespace()
|
||||
} else if isLetter(char) {
|
||||
s.unread()
|
||||
return s.scanText()
|
||||
|
@ -61,19 +62,20 @@ func (s *scanner) scan() Token {
|
|||
return s.scanNumber()
|
||||
} else if char == '#' {
|
||||
s.unread()
|
||||
return s.scanComment()
|
||||
s.scanComment()
|
||||
} else if isOpperator(char) {
|
||||
return Token{Opperator, string(char)}
|
||||
} else if char == '\n' {
|
||||
return Token{Newline,""}
|
||||
return Token{Newline,"New Line"}
|
||||
} else if char == ':' {
|
||||
return Token{Separator,""}
|
||||
return Token{Separator,":"}
|
||||
} else if char == eof {
|
||||
return Token{End, ""}
|
||||
}
|
||||
|
||||
return Token{End, "eof"}
|
||||
} else {
|
||||
return Token{Illegal, string(char)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (s *scanner) scanWhitespace() Token {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package parse
|
||||
package parser
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
@ -45,11 +45,6 @@ func (p *Parser) scan() (current Token) {
|
|||
return p.buffer.token
|
||||
}
|
||||
|
||||
for {
|
||||
if current = p.s.scan(); current.kind != Whitespace && current.kind != Comment {
|
||||
break
|
||||
}
|
||||
}
|
||||
current = p.s.scan()
|
||||
p.buffer.token = current
|
||||
return
|
||||
|
@ -70,8 +65,13 @@ func (p *Parser) parseExpressions(equals bool) []Expression {
|
|||
if t.kind == Opperator {
|
||||
ex.Opperator = rune(t.val[0])
|
||||
t = p.scan()
|
||||
} else {
|
||||
} else if t.kind == Number || t.kind == Text {
|
||||
ex.Opperator = '='
|
||||
} else if t.kind == Newline {
|
||||
p.unscan()
|
||||
break
|
||||
} else {
|
||||
panic(fmt.Sprintf("Parse error: Invalid token %q on \033[1mline %d\033[0m", t.val, p.row))
|
||||
}
|
||||
|
||||
if t.kind == Number {
|
||||
|
@ -86,6 +86,7 @@ func (p *Parser) parseExpressions(equals bool) []Expression {
|
|||
|
||||
exprs = append(exprs, ex)
|
||||
|
||||
t = p.scan()
|
||||
if t.kind == Separator {
|
||||
continue
|
||||
}
|
||||
|
@ -133,17 +134,12 @@ func (p *Parser) parseLoop() Loop {
|
|||
t := p.scan()
|
||||
l := Loop{}
|
||||
|
||||
if strings.ToUpper(t.val) == "LOOP" {
|
||||
t = p.scan()
|
||||
if t.kind == Number {
|
||||
l.Counter, _ = strconv.Atoi(t.val)
|
||||
} else {
|
||||
panic(fmt.Sprintf("Parse error: Loop declared, but not followed by a number on \033[1mline %d\033[0m", p.row))
|
||||
}
|
||||
} else {
|
||||
p.unscan()
|
||||
l.Counter = 1
|
||||
}
|
||||
|
||||
l.Procedures = make([]Procedure,0, 5)
|
||||
|
||||
L:
|
||||
|
@ -163,6 +159,9 @@ func (p *Parser) parseLoop() Loop {
|
|||
case Number:
|
||||
panic(fmt.Sprintf("Parse error: Number %q outside of procedure call on \033[1mline %d\033[0m", t.val, p.row))
|
||||
case Text:
|
||||
if strings.ToUpper(t.val) == "END" {
|
||||
break L
|
||||
}
|
||||
p.unscan()
|
||||
procedure := p.parseProcedure()
|
||||
l.Procedures = append(l.Procedures, procedure)
|
||||
|
@ -193,8 +192,15 @@ func (p *Parser) Parse() AST {
|
|||
case Number:
|
||||
panic(fmt.Sprintf("Parse error: Number %q outside of procedure call on \033[1mline %d\033[0m", t.val, p.row))
|
||||
case Text:
|
||||
var loop Loop
|
||||
if strings.ToUpper(t.val) == "BEG" {
|
||||
loop = p.parseLoop()
|
||||
} else {
|
||||
p.unscan()
|
||||
loop := p.parseLoop()
|
||||
loop = Loop{1, make([]Procedure, 0, 1)}
|
||||
procedure := p.parseProcedure()
|
||||
loop.Procedures = append(loop.Procedures, procedure)
|
||||
}
|
||||
tree.Loops = append(tree.Loops, loop)
|
||||
}
|
||||
}
|
||||
|
@ -205,8 +211,7 @@ func (p *Parser) Parse() AST {
|
|||
func isValidProcedure(p string) bool {
|
||||
switch p {
|
||||
case "REG", "LOC", "BEG", "END", "RED",
|
||||
"GRN", "BLU", "APH", "COL", "APY", "MOD",
|
||||
"FAD":
|
||||
"GRN", "BLU", "APH", "COL", "APY", "MOD":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -224,3 +229,5 @@ func isVariable(v string) bool {
|
|||
func NewParser(r io.Reader) *Parser {
|
||||
return &Parser{s: NewScanner(r)}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"tildegit.org/sloum/filtress/parser"
|
||||
)
|
||||
|
||||
func (f *filter) update(change parser.Expression, vars map[string]int) {
|
||||
opand := change.Opperand
|
||||
if change.Variable != "" {
|
||||
if val, ok := vars[change.Variable]; ok {
|
||||
opand = val
|
||||
} else {
|
||||
panic(fmt.Sprintf("Runtime error: Encountered unknown variable %q", val))
|
||||
}
|
||||
}
|
||||
|
||||
switch change.Opperator {
|
||||
case '+':
|
||||
f.val += opand
|
||||
case '-':
|
||||
f.val -= opand
|
||||
case '*':
|
||||
f.val *= opand
|
||||
case '/':
|
||||
if opand == 0 {
|
||||
f.val = 1
|
||||
} else {
|
||||
f.val /= opand
|
||||
}
|
||||
case '=':
|
||||
f.val = opand
|
||||
}
|
||||
if f.val > f.max {
|
||||
f.val %= f.max
|
||||
}
|
||||
if f.val < f.min {
|
||||
f.val = f.max - f.val%f.max
|
||||
}
|
||||
}
|
||||
|
||||
func (p *point) update(change []parser.Expression, vars map[string]int) {
|
||||
var totalX, totalY, val, opand, max int
|
||||
var target *int
|
||||
|
||||
for i, e := range change {
|
||||
if i == 0 {
|
||||
target = &totalX
|
||||
val = p.x
|
||||
max = p.maxX
|
||||
} else if i == 1 {
|
||||
target = &totalY
|
||||
val = p.y
|
||||
max = p.maxY
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
if e.Variable != "" {
|
||||
if val, ok := vars[e.Variable]; ok {
|
||||
opand = val
|
||||
} else {
|
||||
panic(fmt.Sprintf("Runtime error: Encountered unknown variable %q", val))
|
||||
}
|
||||
} else {
|
||||
opand = e.Opperand
|
||||
}
|
||||
|
||||
switch e.Opperator {
|
||||
case '+':
|
||||
*target = val + opand
|
||||
case '-':
|
||||
*target = val - opand
|
||||
case '*':
|
||||
*target = val * opand
|
||||
case '/':
|
||||
if opand == 0 {
|
||||
*target = 1
|
||||
} else {
|
||||
*target = val / opand
|
||||
}
|
||||
case '=':
|
||||
*target = opand
|
||||
}
|
||||
|
||||
if *target > max {
|
||||
*target %= max
|
||||
}
|
||||
|
||||
if *target < 0 {
|
||||
*target = max - *target%max
|
||||
}
|
||||
}
|
||||
p.x = totalX
|
||||
p.y = totalY
|
||||
}
|
Loading…
Reference in New Issue