102 lines
2.0 KiB
Go
102 lines
2.0 KiB
Go
package parser
|
|
|
|
import (
|
|
"math"
|
|
|
|
"sfdl/scanner"
|
|
"sfdl/semantices"
|
|
)
|
|
|
|
var (
|
|
Parameter float64 // T
|
|
OriginX, OriginY float64
|
|
ScaleX, ScaleY float64 = 1, 1
|
|
RotAngle float64 // 弧度
|
|
)
|
|
|
|
func ResetState() {
|
|
Parameter = 0
|
|
OriginX, OriginY = 0, 0
|
|
ScaleX, ScaleY = 1, 1
|
|
RotAngle = 0
|
|
}
|
|
|
|
func evalExpr(root *ExprNode) float64 {
|
|
if root == nil {
|
|
return 0
|
|
}
|
|
switch root.Op {
|
|
case scanner.PLUS:
|
|
return evalExpr(root.Left) + evalExpr(root.Right)
|
|
case scanner.MINUS:
|
|
return evalExpr(root.Left) - evalExpr(root.Right)
|
|
case scanner.MUL:
|
|
return evalExpr(root.Left) * evalExpr(root.Right)
|
|
case scanner.DIV:
|
|
return evalExpr(root.Left) / evalExpr(root.Right)
|
|
case scanner.POWER:
|
|
return math.Pow(evalExpr(root.Left), evalExpr(root.Right))
|
|
case scanner.FUNC:
|
|
return root.Func(evalExpr(root.Left))
|
|
case scanner.CONST_ID:
|
|
return root.Value
|
|
case scanner.T:
|
|
return Parameter
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func calcCoord(xExpr, yExpr *ExprNode) (float64, float64) {
|
|
x := evalExpr(xExpr)
|
|
y := evalExpr(yExpr)
|
|
|
|
// scale
|
|
x *= ScaleX
|
|
y *= ScaleY
|
|
|
|
// rotate
|
|
tx := x*math.Cos(RotAngle) + y*math.Sin(RotAngle)
|
|
ty := y*math.Cos(RotAngle) - x*math.Sin(RotAngle)
|
|
x, y = tx, ty
|
|
|
|
// translate
|
|
x += OriginX
|
|
y += OriginY
|
|
|
|
return x, y
|
|
}
|
|
|
|
// ORIGIN IS (x, y)
|
|
func originStatement(xExpr, yExpr *ExprNode) {
|
|
OriginX = evalExpr(xExpr)
|
|
OriginY = evalExpr(yExpr)
|
|
}
|
|
|
|
// SCALE IS (sx, sy)
|
|
func scaleStatement(xExpr, yExpr *ExprNode) {
|
|
ScaleX = evalExpr(xExpr)
|
|
ScaleY = evalExpr(yExpr)
|
|
}
|
|
|
|
// ROT IS angle
|
|
func rotStatement(angleExpr *ExprNode) {
|
|
RotAngle = evalExpr(angleExpr)
|
|
}
|
|
|
|
// FOR T FROM start TO end STEP step DRAW (xExpr, yExpr)
|
|
func forStatement(startExpr, endExpr, stepExpr, xExpr, yExpr *ExprNode) {
|
|
start := evalExpr(startExpr)
|
|
end := evalExpr(endExpr)
|
|
step := evalExpr(stepExpr)
|
|
|
|
if step <= 1e-9 {
|
|
return
|
|
}
|
|
|
|
for Parameter = start; Parameter <= end; Parameter += step {
|
|
x, y := calcCoord(xExpr, yExpr)
|
|
semantices.DrawPixel(int(math.Round(x)), int(math.Round(y)))
|
|
}
|
|
}
|