Initial Commit

This commit is contained in:
Kyler 2024-04-03 08:30:01 -06:00
commit 1098b3b3f0
5 changed files with 2918 additions and 0 deletions

2398
compiler.py Normal file

File diff suppressed because it is too large Load Diff

53
equation.py Normal file
View File

@ -0,0 +1,53 @@
class Equation:
def __init__(self, xf, yf, cf=(255,255,255), wf=1):
self.xf = xf
self.yf = yf
self.cf = cf
self.wf = wf
def _xf(self, t):
if callable(self.xf):
return self.xf(t)
else:
return t
def _yf(self, t):
if callable(self.yf):
return self.yf(t)
else:
return t
def _cf(self, t, r):
if callable(self.cf):
return self.cf(t, r)
else:
return self.cf
def _wf(self, t, r):
if callable(self.wf):
return self.wf(t, r)
else:
return self.wf
def plot(self, r=(0, 12, 0.1), scale=(1,1)):
t = r[0]
prev_x = self._xf(t)
prev_y = self._yf(t)
while t <= r[1]:
x = self._xf(t)
y = self._yf(t)
c = self._cf(t, r)
w = self._wf(t, r)
yield (
int(prev_x * scale[0]),
int(prev_y * scale[1]),
int(x * scale[0]),
int(y * scale[1]),
c,
w,
)
prev_x, prev_y = x, y
t += r[2]

23
example.graph Normal file
View File

@ -0,0 +1,23 @@
# Kyler Olsen
# Apr 2024
# Hypotrochoid Example
SCREEN {
Width Scale: 100,
Height Scale: 100,
FPS: 60,
}
R = 7;
r = 4;
d = 1;
ANIM offset {R:0 <= x <= 8*pi,S:π/128}
GRAPH {
X: (R - r) * cos(t) + d * cos(((R - r) / r) * t),
Y: (R - r) * sin(t) - d * sin(((R - r) / r) * t),
T: ANIM {R:0+offset <= x <= 8*pi+offset,S:π/32},
C_w: ((t - r[0]) / (r[1] - r[0]))
}

82
main.py Normal file
View File

@ -0,0 +1,82 @@
import pygame
import sys
import math
from equation import Equation
# Initialize Pygame
pygame.init()
# Screen dimensions
# Screen setup
# screen = pygame.display.set_mode((800, 600))
screen = pygame.display.set_mode()
pygame.display.set_caption("Equation Plotter")
class Hypotrochoid(Equation):
def __init__(self, R, r, d, c=(255,255,255)):
self.R = R
self.r = r
self.d = d
super().__init__(self._h_xf, self._h_yf, self._h_cf, 5)
def _h_xf(self, t):
return (self.R - self.r) * math.cos(t) + self.d * math.cos(((self.R - self.r) / self.r) * t)
def _h_yf(self, t):
return (self.R - self.r) * math.sin(t) - self.d * math.sin(((self.R - self.r) / self.r) * t)
def _h_cf(self, t, r):
c = int(((t - r[0]) / (r[1] - r[0])) * 255)
return c, c, c
# def _h_wf(self, t, r):
# return int(((t - r[0]) / (r[1] - r[0])) * 5)
def main(equ):
SCREEN_WIDTH = screen.get_width()
SCREEN_HEIGHT = screen.get_height()
HALF_WIDTH = SCREEN_WIDTH // 2
HALF_HEIGHT = SCREEN_HEIGHT // 2
# Main loop
off = 0
mouse_x_last, mouse_y_last = pygame.mouse.get_pos()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Clear the screen
screen.fill((0,0,0))
for prev_x, prev_y, x, y, c, w in equ.plot((0 + off, (8 * math.pi) + off, math.pi/32), (100, 100)):
pygame.draw.line(screen, c, (prev_x + HALF_WIDTH, HALF_HEIGHT - prev_y), (x + HALF_WIDTH, HALF_HEIGHT - y), w)
pygame.display.flip()
pygame.time.Clock().tick(60)
off += math.pi/128
# if direction:
# equ.R += 0.1
# equ.r += 0.05
# if equ.R >= 20:
# direction = False
# else:
# equ.R -= 0.1
# equ.r -= 0.05
# if equ.R <= 6:
# direction = True
mouse_x, mouse_y = pygame.mouse.get_pos()
if 5 < math.sqrt(pow(mouse_x_last - mouse_x, 2) + pow(mouse_y_last - mouse_y, 2)):
running = False
pygame.quit()
sys.exit()
# main(Equation(None, lambda t: math.sin(t)))
# main(Hypotrochoid(6, 4, 1))
main(Hypotrochoid(7, 4, 1))
# main(Hypotrochoid(15, 14, 1))

362
readme.md Normal file
View File

@ -0,0 +1,362 @@
# YTD Graphing Language
## Lexical Definition
### Comments
Comments can either be single-line comments or multi-line comments.
Single-line comments start with `#` and end at the end of a line.
### Identifiers
Can be up to 31 characters in length, and are case sensitive.
They cannot be a keyword.
```
Identifier ::= ID_Start*
ID_Start ::= <Any latin alphabet ligature: "A"-"Z", "a"-"z">
```
### Keywords
Keywords are not case sensitive.
```
screen graph anim img
sum pi alpha beta
theta inf product integral
```
### Literals
```
number ::= decinteger | pointfloat | exponentfloat
decinteger ::= nonzerodigit (["_"] digit)* | "0"+ (["_"] "0")*
nonzerodigit ::= "1"..."9"
digit ::= "0"..."9"
pointfloat ::= ([digitpart] fraction) | (digitpart ".")
exponentfloat ::= (digitpart | pointfloat) exponent
digitpart ::= digit (["_"] digit)*
fraction ::= "." digitpart
exponent ::= ("e" | "E") ["+" | "-"] digitpart
```
### Punctuation
```
+ - * / % ^
= ! < <= > >=
{ } [ ] ( )
_ -> , ; : ∑
∏ ∞ ≠ ≤ ≥ ∫
α β π → θ
```
#### Punctuation Conversions
| Original | New |
| -- | -- |
| <= | ≤ |
| >= | ≥ |
| -> | → |
#### Keyword Conversions
| Original | New |
| -- | -- |
| sum | ∑ |
| pi | π |
| alpha | α |
| beta | β |
| inf | ∞ |
| product | ∏ |
| integral | ∫ |
| theta | θ |
## Syntax
The syntactical structure starts with a `file` at the root.
### File
A `file` can contain any number of the following elements:
- *Screen*
- *Graph*
- *Animation*
<!-- - *Image* -->
### Screen
A *screen* begins with the `screen` keyword. It then has a comma (`,`)
separated list enclosed in curly braces (`{` and `}`) of *screen parameters*.
At most only one screen block is allowed per `file`.
#### Screen parameter
A *screen parameter* begins with its parameter name then a colon (`:`) followed
by its value.
Listed bellow are the possible parameters.
**Top**
- Role:
Sets the Y-Coordinate of the top of the screen to the given value.
- Required:
False
- Default:
`Unset`
- Possible Values: Integers, `Unset`
**Bottom**
- Role:
Sets the Y-Coordinate of the bottom of the screen to the given value.
- Required:
False
- Default:
`Unset`
- Possible Values: Integers, `Unset`
**Right**
- Role:
Sets the X-Coordinate of the right of the screen to the given value.
- Required:
False
- Default:
`Unset`
- Possible Values: Integers, `Unset`
**Left**
- Role:
Sets the X-Coordinate of the left of the screen to the given value
- Required:
False
- Default:
`Unset`
- Possible Values: Integers, `Unset`
**Width**
- Role:
Sets the X-Coordinate range of the screen to the given value
- Required:
False
- Default:
`Unset`
- Possible Values: Natural Numbers, `Unset`
- Note:
Centered on zero if `right` and `left` are unset.
Has no affect if `right` and `left` are set.
**Height**
- Role:
Sets the Y-Coordinate range of the screen to the given value
- Required:
False
- Default:
`Unset`
- Possible Values: Natural Numbers, `Unset`
- Note:
Centered on zero if `top` and `bottom` are unset.
Has no affect if `top` and `bottom` are set.
**Width Scale**
- Role:
Sets the X-Coordinate range of the screen to the screen pixel
width divided by the given value
- Required:
False
- Default:
`20`
- Possible Values: Positive Real Numbers
- Note:
Centered on zero if `right` and `left` are unset.
Has no affect if `right` and `left` are set or if `width` are set.
**Height Scale**
- Role:
Sets the Y-Coordinate range of the screen to the screen pixel
height divided by the given value
- Required:
False
- Default:
`20`
- Possible Values: Positive Real Numbers
- Note:
Centered on zero if `top` and `bottom` are unset.
Has no affect if `top` and `bottom` are set or if `height` are set.
**FPS**
- Role:
Sets the refresh rate of the screen
- Required:
False
- Default:
`30`
- Possible Values: Natural Numbers
### Graph
A *graph* begins with the `graph` keyword. It then has a comma (`,`)
separated list enclosed in curly braces (`{` and `}`) of *graph parameters*.
A graph block defines a graph to be drawn.
#### Graph parameter
A *graph parameter* begins with its parameter name then a colon (`:`) followed
by an `expression`.
Listed bellow are the possible parameters and their possible roles.
Any ranges can be the `identifier` of an *animation* or an *inline animation*.
**X**
- The `x = f(y)` function for `y` independent cartesian equations.
- The `x = f(t)` function for parametric equations.
- The `x` range (animation) for `x` independent cartesian equations.
**Y**
- The `y = f(x)` function for `x` independent cartesian equations.
- The `y = f(t)` function for parametric equations.
- The `y` range (animation) for `y` independent cartesian equations.
**T**
- The `t` range (animation) for parametric equations.
**R**
- The `r = f(θ)` function for polar equations.
**θ**
- The `θ` range (animation) for polar equations.
*Color functions*
- The `c = f(x)` function for `x` independent cartesian equations.
- The `c = f(y)` function for `y` independent cartesian equations.
- The `c = f(t)` function for parametric equations.
- The `c = f(θ)` function for polar equations.
#### Color Functions
*Color function* parameter names are **C_x** where the *x* is color space part
subscript.
Only one color space can be used in each graph.
If only alpha is set the default color space is **Grey-scale**.
Listed bellow are the available color spaces and their subscripts.
Default value in parenthesis for the unused subscripts of the color spaces.
- **Grey-scale**: `wa` - Grey-scale (1), Alpha (1)
- **RGB**: `rgba` - Red (0), Green (0), Blue (0), Alpha (1)
- **HSL**: `hsla` - Hue (0), Saturation (1), Luminosity (0.5), Alpha (1)
All values can be a real number between 0 and 1 inclusive.
Values bellow this range will be interpreted as 0.
Values above this range will be interpreted as 1.
### Animation
An *animation* begins with the `anim` keyword. Unless it is an
*inline animation* block, the keyword is followed by its `identifier`. It then
has a comma (`,`) separated list enclosed in curly braces (`{` and `}`)
of *animation parameters*.
When an animation is used in an expression, the value it is evaluated as is in
the range defined, changing by the step every frame.
#### Animation parameter
An *animation parameter* begins with its parameter name then a colon (`:`)
followed by an `expression`. If it is the only parameter the parameter name for
the range is optional.
Listed bellow are the possible parameters. Only the *range* parameter is
required.
**R** Range: `R:` *expression* `≤ x ≤` *expression*
**S** Step: `S:` *expression*
- Default is `1/10` unless a range expression is multiplied by `π` then it
is `π/32`.
**D** Direction: `D:` *direction*
- `increase` (default)
- `decrease`
- `bounce`
### Expressions
#### Unary Expression
A `unary expression` is made up of one `expression` and one `unary operator`.
The operator may come before or after the expression.
#### Binary Expression
A `binary expression` is made up of one `expression`, then one
`binary operator`, then another `expression`.
#### Function
A `function` starts with an `identifier` followed by a comma (`,`)
separated list enclosed in parentheses (`(` and `)`) of *function arguments*.
##### Function Argument
A *function argument* is an `expression`.
#### Enclosed Expression
An `enclosed expression` is simply an `expression` enclosed in parentheses
(`(` and `)`).
#### Operator
Here are all operators and their types and names in order of precedence.
| Operator | Type | Name |
| -- | -- | -- |
| `-` | Unary (Prefix) | Negate *Operator* |
| `!` | Unary (Postfix) | Factorial *Operator* |
| `^` | Binary | Exponential *Operator* |
| `_` | Binary | Subscript *Operator* |
| `/` | Binary | Division *Operator* |
| `%` | Binary | Modulus *Operator* |
| `*` | Binary | Multiplication *Operator* |
| `-` | Binary | Subtraction *Operator* |
| `+` | Binary | Addition *Operator* |
| `=` | Binary | Assignment *Operator* |
#### Literal
A `literal` is just simply the content of the literal.
#### Identifier
A `identifier` is just simply the name of the identifier.
#### Statement
A `statement` is made up of an `expression` followed by a semicolon (`;`).
## Semantics
### Screen Block
### Graph Block
<!-- ### Image Block
Defines a background image.
Additional image blocks will stack on top of the previous one in the order they
are in the file.
- **X**: The `x` range (animation) for the background.
- **Y**: The `y` range (animation) for the background.
- **R**: The `r` range (animation) for the background.
- **A or Theta**: The `theta` range (animation) for the background.
- **C_x**: The color function of the background. -->
### Animation Block