Skip to content

Commit

Permalink
More parsing code
Browse files Browse the repository at this point in the history
  • Loading branch information
3top1a committed Jan 15, 2025
1 parent 398c0b5 commit c89bfdb
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 34 deletions.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ array = [ 1 2 3 4 { + ( 3 2 ) } ]
array_empty = [ 0 ; 3 ]
// Strings are arrays
string = "Hello, World!"
// This string is four characters wide!
// This string is four characters long!
beer = "🍺"

// Operators
Expand All @@ -53,7 +53,7 @@ math = +( 5 *(5 two))
input_array = [0;16]
// Get user input
// Maximum length is 16
input(input_array, 16)
input(input_array 16)

// Print
print("Hello ")
Expand All @@ -75,25 +75,26 @@ basm("<>+-")
for ch in input_array {
// Indents are 8 wide tabs
printf(ch);
printf('\n');
// \n prints out a new line, a single \ does not need to be escaped
print('\n');
}

// Example foobar implementation
hit = false
for i in 0..254 {
if %(i, 5) == 0 {
if %(i 5) == 0 {
hit = true
printf("Foo")
print("Foo")
}
if %(i, 7) == 0 {
if %(i 7) == 0 {
hit = true
printf("Bar")
print("Bar")
}
if hit == true {
printf("\n")
print("\n")
} else {
printf(i)
printf('\n')
print('\n')
}
}

Expand Down
54 changes: 42 additions & 12 deletions examples/basic.🍺
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,25 @@ named_char = 'c'
// false is 0, true is 1
// In comparison, 0 is false, everything else is true
bool = true
// ! negates the value
// Since it's just numbers, it's simply |(0 - x)|
bool = !bool

// Fixed size arrays
// Arrays are denoted by the * symbol as they work like pointers
array = [ 1 2 3 4 {+ (3 2) } ]
// Expressions can be used inside anything
array = [ 1 2 3 4 { + ( 3 2 ) } ]
// An array can also be created this way, substituting memset
array_empty = [0; 3]
array_empty = [ 0 ; 3 ]
// Strings are arrays
string = "Hello, World!"
// This string is four characters long!
beer = "🍺"

// Operators
// Math with priority
two = 2
// I'm too lazy to make actual math
math = +( 5 *( 5 two ) )
// I'm too lazy to make actual math so enjoy reversed reverse polish notation
math = +( 5 *(5 two))

// Functions
input_array = [0; 16]
input_array = [0;16]
// Get user input
// Maximum length is 16
input(input_array 16)
Expand All @@ -45,9 +43,41 @@ input(input_array 16)
print("Hello ")
print(input_array)
print("!\n")
// Printf is used for printing strings and numbers in decimal
// This prints `c`
print(c)
// This prints `99`
printf(c)

// Raw Brainfuck
// This should only be used in the standard library, e.g. input(), not in user code
// If this project succeeds it's ultimate goal, basm will be the only function from the compiler except math,
// and all other functions will be written in alkoholiq
asm("<>+-")
// If this project succeeds it's ultimate goal, basm will be the only function from
// the compiler except math, and all other functions will be written in alkoholiq
basm("<>+-")

// Iterators work like in Rust
for ch in input_array {
// Indents are 8 wide tabs
printf(ch);
// \n prints out a new line,
print('\n');
}

// Example foobar implementation
hit = false
for i in 0..254 {
if %(i 5) == 0 {
hit = true
print("Foo")
}
if %(i 7) == 0 {
hit = true
print("Bar")
}
if hit == true {
print("\n")
} else {
printf(i)
print('\n')
}
}
10 changes: 10 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ pub enum Expression {
/// Body
body: Vec<Expression>,
},

/// For loop
For {
/// Variable name
name: String,
/// Range
range: (Box<Expression>, Box<Expression>),
/// Body
body: Vec<Expression>,
},
}

#[derive(Debug, PartialEq, Clone)]
Expand Down
14 changes: 8 additions & 6 deletions src/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::ops::Range;
use logos::Logos;
use std::ops::Range;

#[derive(Logos, Debug, PartialEq, Clone)]
#[logos(skip r"[ \t\f\n]+")] // Skip whitespace
Expand Down Expand Up @@ -66,7 +66,7 @@ pub enum Token {
#[regex(r"[0-9]+", |lex| lex.slice().parse().ok())]
Integer(u8),

#[regex(r"'.'", |lex| lex.slice().chars().nth(1).map(|c| c as u8))]
#[regex(r"'(.|\\n|\\d)'", |lex| lex.slice().chars().nth(1).map(|c| c as u8))]
Char(u8),

#[regex(r#""[^"]*""#, |lex| {
Expand All @@ -77,7 +77,7 @@ pub enum Token {

// Identifiers
#[regex(r"[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice().to_string())]
#[regex(r"\+|\-|\*|\/", |lex| lex.slice().to_string())]
#[regex(r"\+|\-|\*|\/|%", |lex| lex.slice().to_string())]
Identifier(String),
}

Expand All @@ -96,7 +96,10 @@ impl Into<Token> for IndexedToken {
}

pub fn tokenize_indexed(input: &str) -> Vec<IndexedToken> {
let output = Token::lexer(input).spanned().into_iter().map(|(x, span)| {
// Add newline so line_text_after doesn't panic
let input = input.to_owned() + "\n";
let input = input.replace("\t", &*" ".repeat(8));
let output = Token::lexer(&*input).spanned().into_iter().map(|(x, span)| {
let line_number = input[..span.end].chars().filter(|&x| x == '\n').count() + 1;
let line_text_before = input[..span.end].lines().last().unwrap();
let line_text_after = input[span.end..].lines().next().unwrap();
Expand Down Expand Up @@ -162,13 +165,12 @@ mod tests {

#[test]
fn test_array() {
let input = "array* = [1 2 3]";
let input = "array = [1 2 3]";
let tokens = tokenize(input);
assert_eq!(
tokens,
vec![
Token::Identifier("array".to_string()),
Token::Identifier("*".to_string()),
Token::Assign,
Token::SquareOpen,
Token::Integer(1),
Expand Down
12 changes: 5 additions & 7 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ impl Parser {
self.tokens.get(self.current).map_or(None, |x| Some(x.clone()))
}

fn check(&self, token: &Token) -> bool {
self.peek() == Some(token.clone())
fn check(&self, token: Token) -> bool {
self.peek() == Some(token)
}

fn is_at_end(&self) -> bool {
Expand Down Expand Up @@ -139,13 +139,11 @@ impl Parser {
}

let mut elements = vec![first];
while !self.check(&Token::SquareClose) {
if !self.check(&Token::SquareClose) {
while !self.check(Token::SquareClose) {
if self.check(Token::SquareClose) {
break;
}
if !self.check(&Token::SquareClose) {
elements.push(self.parse_expression()?);
}
elements.push(self.parse_expression()?);
}

self.consume(Token::SquareClose)?;
Expand Down

0 comments on commit c89bfdb

Please sign in to comment.