Skip to content

Commit

Permalink
Some more work on Wren parser
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkleiny committed Nov 12, 2024
1 parent 86b7e31 commit e27163d
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 6 deletions.
2 changes: 2 additions & 0 deletions core/scripting/assets/scripts/wren/test01.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Hello, world!
System.print("Hello, world!")
10 changes: 10 additions & 0 deletions core/scripting/assets/scripts/wren/test02.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Compute the fibonacci number at position n
fn fib(n) {
if (n <= 1) return n
return fib(n - 1) + fib(n - 2)
}

System.print("Fibonacci sequence:")
for (i in 0..10) {
System.print("fib(%(_i)) = %(fib(i))")
}
81 changes: 81 additions & 0 deletions core/scripting/assets/scripts/wren/test03.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Conway's Game of Life
class GameOfLife {
construct new(width, height) {
_width = width
_height = height
_grid = List.filled(width * height, false)
}

// Get cell at x,y coordinates
cell(x, y) {
if (x < 0 || x >= _width || y < 0 || y >= _height) return false
return _grid[y * _width + x]
}

// Set cell at x,y coordinates
setCell(x, y, value) {
if (x < 0 || x >= _width || y < 0 || y >= _height) return
_grid[y * _width + x] = value
}

// Count live neighbors for cell at x,y
countNeighbors(x, y) {
var count = 0
for (dy in -1..2) {
for (dx in -1..2) {
if (dx == 0 && dy == 0) continue
if (cell(x + dx, y + dy)) count = count + 1
}
}
return count
}

// Update the grid according to Game of Life rules
step() {
var newGrid = List.filled(_width * _height, false)

for (y in 0..._height) {
for (x in 0..._width) {
var neighbors = countNeighbors(x, y)
var alive = cell(x, y)

if (alive && (neighbors == 2 || neighbors == 3)) {
newGrid[y * _width + x] = true
} else if (!alive && neighbors == 3) {
newGrid[y * _width + x] = true
}
}
}

_grid = newGrid
}

// Display the current state
display() {
for (y in 0..._height) {
var line = ""
for (x in 0..._width) {
line = line + (cell(x, y) ? "■ " : "□ ")
}
System.print(line)
}
System.print("")
}
}

// Create a 10x10 game board
var game = GameOfLife.new(10, 10)

// Set up a simple glider pattern
game.setCell(1, 0, true)
game.setCell(2, 1, true)
game.setCell(0, 2, true)
game.setCell(1, 2, true)
game.setCell(2, 2, true)

// Run for 10 generations
for (i in 0...10) {
System.print("Generation %(i):")
game.display()
game.step()
}
59 changes: 53 additions & 6 deletions core/scripting/src/lang/wren.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,6 @@ pub enum Keyword {
Super,
}

/// Parses a list of tokens into an AST [`Expression`].
pub fn parse(code: &str) -> Result<Expression, ParseError> {
Parser::from_code(code).parse_expression()
}

/// A parser for Wren code.
struct Parser {
tokens: Vec<Token>,
Expand Down Expand Up @@ -181,6 +176,11 @@ impl Parser {
}
}

/// Parses a string of Wren code into an AST [`Expression`].
pub fn parse(code: &str) -> Result<Expression, ParseError> {
Parser::from_code(code).parse_expression()
}

/// Tokenises a string of Wren code into a list of [`Token`]s.
fn tokenise(code: &str) -> Vec<Token> {
let mut tokens = Vec::new();
Expand Down Expand Up @@ -214,7 +214,30 @@ fn tokenise(code: &str) -> Vec<Token> {
}
continue;
}
None => Token::Operator(Operator::Divide),
None => match characters.next_if_eq(&(position + 1, '*')) {
Some(_) => {
// ignore block comments
let mut depth = 1;
while depth > 0 {
match characters.next() {
Some((_, '*')) => {
if let Some((_, '/')) = characters.next() {
depth -= 1;
}
}
Some((_, '/')) => {
if let Some((_, '*')) = characters.next() {
depth += 1;
}
}
None => break, // Unterminated block comment
_ => {}
}
}
continue;
}
None => Token::Operator(Operator::Divide),
},
},
'<' => match characters.next_if_eq(&(position + 1, '=')) {
Some(_) => Token::Operator(Operator::LessThanOrEqual),
Expand Down Expand Up @@ -458,4 +481,28 @@ mod tests {
))
)
);

macro_rules! parse_file_test {
($name:ident, $path:expr) => {
#[test]
fn $name() {
use std::fs;
let contents = fs::read_to_string($path).expect("Failed to read file");
let result = parse(&contents);

assert!(
result.is_ok(),
"Failed to parse file {}: {:?}",
$path,
result.err()
);
}
};
}

// parse_file_test!(it_should_parse_test01,
// "assets/scripts/wren/test01.wren"); parse_file_test!
// (it_should_parse_test02, "assets/scripts/wren/test02.wren");
// parse_file_test!(it_should_parse_test03,
// "assets/scripts/wren/test03.wren");
}

0 comments on commit e27163d

Please sign in to comment.