This repository has been archived on 2026-05-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
sfdl/parser/semantices.go
2025-12-04 18:44:37 +08:00

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)))
}
}