Initial commit
This commit is contained in:
commit
3d4fd06bba
10 changed files with 254 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
25
Cargo.lock
generated
Normal file
25
Cargo.lock
generated
Normal file
|
@ -0,0 +1,25 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aeapa"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"deborrow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deborrow"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5f99cc7a6632788aab2c734a6e1e1d8302658f70fb45d99a6e32154a24cc2a2"
|
||||
dependencies = [
|
||||
"deborrow-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deborrow-macro"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "551a13c0871ba8964b30d2407fdfd4c9b8e5f289950c152ff3d0d8de5be6b948"
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "aeapa"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
deborrow = "0.3.1"
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Advanced Easily Parsable Language
|
||||
|
||||
/æepa/
|
13
src/main.rs
Normal file
13
src/main.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use std::fs;
|
||||
|
||||
use crate::tokenizer::Tokenizer;
|
||||
|
||||
pub mod parser;
|
||||
pub mod tokenizer;
|
||||
pub mod value;
|
||||
pub mod word;
|
||||
|
||||
fn main() {
|
||||
let tokens = Tokenizer::tokenize(fs::read_to_string("std.aea").unwrap()).unwrap();
|
||||
println!("{tokens:?}");
|
||||
}
|
12
src/parser.rs
Normal file
12
src/parser.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
#[derive(Debug)]
|
||||
pub struct CodePos {
|
||||
pub file: Option<String>,
|
||||
pub char_in_file: Option<usize>,
|
||||
pub line: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseError {
|
||||
InvalidToken(CodePos, char),
|
||||
StringInIdent(CodePos),
|
||||
}
|
124
src/tokenizer.rs
Normal file
124
src/tokenizer.rs
Normal file
|
@ -0,0 +1,124 @@
|
|||
use deborrow::deborrow;
|
||||
|
||||
use std::str::Chars;
|
||||
|
||||
use crate::{
|
||||
parser::{CodePos, ParseError},
|
||||
word::Token,
|
||||
};
|
||||
|
||||
pub struct Tokenizer<'a> {
|
||||
char_iter: Chars<'a>,
|
||||
string: String,
|
||||
}
|
||||
|
||||
impl<'a> Tokenizer<'a> {
|
||||
pub fn tokenize(string: String) -> Result<Vec<Token>, ParseError> {
|
||||
let mut parser = Tokenizer {
|
||||
// SAFETY: string will not be dropped while Parser is in scope
|
||||
char_iter: unsafe { deborrow(&string).chars() },
|
||||
string,
|
||||
};
|
||||
parser.read_tokens()
|
||||
}
|
||||
|
||||
fn tpos(&self, tokens: &[Token]) -> CodePos {
|
||||
CodePos {
|
||||
file: None,
|
||||
char_in_file: Some(self.string.len() - self.char_iter.as_str().len()),
|
||||
line: Some(
|
||||
tokens
|
||||
.iter()
|
||||
.filter(|x| matches!(x, Token::Newline(_)))
|
||||
.count()
|
||||
+ 1,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_tokens(&mut self) -> Result<Vec<Token>, ParseError> {
|
||||
let mut ret = Vec::new();
|
||||
|
||||
let mut accum = String::new();
|
||||
let mut in_string = false;
|
||||
let mut in_escape = false;
|
||||
let mut line = 0;
|
||||
while let Some(char) = self.char_iter.next() {
|
||||
if in_string {
|
||||
if in_escape {
|
||||
match char {
|
||||
'n' => accum.push('\n'),
|
||||
'r' => accum.push('\r'),
|
||||
'\\' => accum.push('\\'),
|
||||
'"' => accum.push('"'),
|
||||
char => return Err(ParseError::InvalidToken(self.tpos(&ret), char)),
|
||||
}
|
||||
in_escape = false;
|
||||
continue;
|
||||
}
|
||||
match char {
|
||||
'"' => {
|
||||
in_string = false;
|
||||
ret.push(Token::String(accum));
|
||||
accum = String::new();
|
||||
}
|
||||
'\\' => in_escape = true,
|
||||
char => accum.push(char),
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let symbol = match char {
|
||||
' ' => Some(Token::Space),
|
||||
'\t' => Some(Token::Space),
|
||||
'|' => Some(Token::Bar),
|
||||
'!' => Some(Token::Exclam),
|
||||
';' => Some(Token::Semicolon),
|
||||
':' => Some(Token::Colon),
|
||||
'(' => Some(Token::Open),
|
||||
')' => Some(Token::Close),
|
||||
'{' => Some(Token::Begin),
|
||||
'}' => Some(Token::End),
|
||||
'^' => Some(Token::Return),
|
||||
'\n' => {
|
||||
line += 1;
|
||||
Some(Token::Newline(line))
|
||||
}
|
||||
'"' => {
|
||||
in_string = true;
|
||||
if !accum.is_empty() {
|
||||
ret.push(Token::Ident(accum));
|
||||
accum = String::new();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if symbol.is_none() {
|
||||
accum.push(char);
|
||||
} else if accum.is_empty() {
|
||||
match symbol {
|
||||
Some(Token::Space) => (),
|
||||
Some(symbol) => ret.push(symbol),
|
||||
None => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
match symbol {
|
||||
Some(symbol) => {
|
||||
ret.push(Token::Ident(accum));
|
||||
if symbol != Token::Space {
|
||||
ret.push(symbol);
|
||||
}
|
||||
accum = String::new();
|
||||
}
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
if accum.is_empty() {
|
||||
return Ok(ret);
|
||||
}
|
||||
ret.push(Token::Ident(accum));
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
16
src/value.rs
Normal file
16
src/value.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Value {
|
||||
Null,
|
||||
U8(u8),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
I128(i128),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
U128(u128),
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
//Func(AFunc),
|
||||
//Array(Vec<AMObject>),
|
||||
Str(String),
|
||||
}
|
27
src/word.rs
Normal file
27
src/word.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use crate::value::Value;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Word {
|
||||
Const(Value),
|
||||
StartCall(String),
|
||||
StartObjCall(String),
|
||||
ConfirmCall,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Token {
|
||||
Space,
|
||||
Bar,
|
||||
Exclam,
|
||||
Semicolon,
|
||||
Colon,
|
||||
Open,
|
||||
Close,
|
||||
Begin,
|
||||
End,
|
||||
Return,
|
||||
String(String),
|
||||
Ident(String),
|
||||
|
||||
Newline(usize),
|
||||
}
|
24
std.aea
Normal file
24
std.aea
Normal file
|
@ -0,0 +1,24 @@
|
|||
!aea:exclam_mode!
|
||||
|
||||
fn main | args:Array:String ! ret:int {
|
||||
print "Hello world!" ;
|
||||
if args:length :== 0 !! {
|
||||
ret= 0 ^
|
||||
}
|
||||
print "I got " :+ String:of args:length ! ! :+ " arguments." ! ;
|
||||
ret= 0
|
||||
}
|
||||
|
||||
!aea:paren_mode!
|
||||
|
||||
fn main(args:Array:String) ret:int {
|
||||
print("Hello world!");
|
||||
if(args:length :== (0)) {
|
||||
ret=(0) ^
|
||||
}
|
||||
print("I got " :+(String:of(args:length)) :+(" arguments."));
|
||||
ret=(0)
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue