why not literals

This commit is contained in:
nothendev 2023-05-04 19:50:17 +03:00
parent 836445d5e2
commit d89faedfb1
11 changed files with 132 additions and 9 deletions

View file

@ -1,4 +1,5 @@
Type Byte = U8; Type Byte = U8;
Type Int = U32;
Type String = Vector<Byte>; Type String = Vector<Byte>;
Enumurate Boolean { Enumurate Boolean {

View file

@ -1,7 +1,7 @@
// core provides lots of useful types like String and Byte // core provides lots of useful types like String and Byte
Use core; Use core;
Constant VERSION Version { Constant VERSION = Version {
major: 1, major: 1,
minor: 0, minor: 0,
patch: 0, patch: 0,

View file

@ -1,4 +1,5 @@
Use core.Byte; Use core.Byte;
Use core.Int; Use core.Int;
Alias Thing = Byte; Constant Hi = "WHY???/\n";
Alias Yo = Byte;

View file

@ -40,6 +40,7 @@ pub struct ItemAlias {
#[derive(Debug)] #[derive(Debug)]
pub struct ItemConstant { pub struct ItemConstant {
pub name: String, pub name: String,
pub expr: Expr
} }
#[derive(Debug)] #[derive(Debug)]
@ -56,6 +57,7 @@ pub enum Expr {
pub enum Literal { pub enum Literal {
String(String), String(String),
Number(NumberLiteral), Number(NumberLiteral),
Char(char)
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -41,6 +41,19 @@ pub enum Token {
#[token(".")] #[token(".")]
Dot, Dot,
// why
#[regex("\"(?s:[^\"\\\\]|\\\\.)*\"", |lex| dbg!(lex.slice()).strip_prefix('"')?.strip_suffix('"').map(ToOwned::to_owned))]
StringLiteral(String),
#[regex(r"'.'", |lex| lex.slice().strip_prefix('\'')?.strip_suffix('\'')?.parse().ok())]
CharLiteral(char),
#[regex(r#"(-)?\d+"#, |lex| lex.slice().parse().ok())]
NumberLiteral(i64),
#[regex(r"(ptr|u8|i8|u16|i16|u32|i32|u64|i64|f32|f64)", |lex| NumberSuffix::lexer(lex.slice()).next().and_then(Result::ok))]
NumberSuffix(NumberSuffix),
#[regex(r#"[a-zA-Z_][a-zA-Z\d_]*"#, |lex| Ident::lexer(lex.slice()).next().and_then(Result::ok))] #[regex(r#"[a-zA-Z_][a-zA-Z\d_]*"#, |lex| Ident::lexer(lex.slice()).next().and_then(Result::ok))]
Ident(Ident), Ident(Ident),
@ -62,10 +75,36 @@ pub enum Ident {
Alias, Alias,
#[token("Use")] #[token("Use")]
Use, Use,
#[regex(r"[A-z]+", |lex| lex.slice().parse().ok())] #[regex(r"[a-zA-Z_][a-zA-Z\d_]*", |lex| lex.slice().parse().ok())]
Other(String), Other(String),
} }
#[derive(Logos, Debug, PartialEq, Eq)]
pub enum NumberSuffix {
#[token("Ptr")]
Ptr,
#[token("u8")]
U8,
#[token("i8")]
I8,
#[token("u16")]
U16,
#[token("i16")]
I16,
#[token("u32")]
U32,
#[token("i32")]
I32,
#[token("u64")]
U64,
#[token("i64")]
I64,
#[token("f32")]
F32,
#[token("f64")]
F64,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Span(pub Range<usize>); pub struct Span(pub Range<usize>);
impl Span { impl Span {

View file

@ -1,5 +1,8 @@
#![feature(result_option_inspect)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
use lexer::Token;
use logos::Logos;
use parser::Parser; use parser::Parser;
mod ast; mod ast;

View file

@ -0,0 +1,51 @@
use crate::{
ast::{Expr, Literal, NumberLiteral},
lexer::{NumberSuffix, Spanned, Token},
unwrap_match,
};
use super::{Parser, ParserError};
impl<'a> Parser<'a> {
pub fn ask_expr(&mut self) -> Result<Spanned<Expr>, ParserError> {
let Spanned(token, _) = self.tokens.peek()?;
Ok(match token {
Token::StringLiteral(_) | Token::NumberLiteral(_) | Token::CharLiteral(_) => {
self._ask_literal()?.map(Expr::Literal)
}
_ => return Err(self.expected("an expression")),
})
}
fn _ask_literal(&mut self) -> Result<Spanned<Literal>, ParserError> {
let Spanned(token, mut span) = self.tokens.next()?;
Ok(match token {
Token::StringLiteral(string) => Spanned(Literal::String(string), span),
Token::CharLiteral(chr) => Spanned(Literal::Char(chr), span),
Token::NumberLiteral(number) => {
let lit = if let Spanned(Token::NumberSuffix(_), sp) = self.tokens.peek()? {
span = span + sp;
use NumberLiteral::*;
Literal::Number(
match unwrap_match!(
self.tokens.next()?, Spanned(Token::NumberSuffix(suffering), _) => suffering) // eat suffix
{
NumberSuffix::Ptr => Ptr(number as usize),
NumberSuffix::U8 => U8(number as u8),
NumberSuffix::I8 => I8(number as i8),
NumberSuffix::U16 => U16(number as u16),
NumberSuffix::I16 => I16(number as i16),
_ => todo!(),
},
)
} else {
Literal::Number(NumberLiteral::Infer(number))
};
Spanned(lit, span)
}
_ => return Err(self.expected("a literal")),
})
}
}

View file

View file

@ -1,12 +1,14 @@
use logos::{Lexer, Logos, SpannedIter}; mod expr;
mod interface;
mod structure;
use logos::{Lexer, Logos};
use crate::{ use crate::{
ast::{IDLModule, Item, ItemAlias, ItemConstant, ItemInterface, ModulePath, UseDecl}, ast::{IDLModule, Item, ItemAlias, ItemConstant, ItemInterface, ModulePath, UseDecl},
lexer::{Ident, Span, Spanned, Token}, lexer::{Ident, Span, Spanned, Token},
}; };
use std::iter::{Filter, Iterator, Peekable}; use std::iter::Iterator;
type Wtf<'a> = Peekable<Filter<&'a mut Lexer<'a, Token>, Box<dyn Fn(&Result<Token, ()>) -> bool>>>;
struct TokenIterator<'a> { struct TokenIterator<'a> {
lexer: Lexer<'a, Token>, lexer: Lexer<'a, Token>,
@ -54,7 +56,7 @@ impl<'a> TokenIterator<'a> {
} }
} }
pub struct Parser<'a> { pub(crate) struct Parser<'a> {
tokens: TokenIterator<'a>, tokens: TokenIterator<'a>,
} }
@ -65,6 +67,10 @@ impl<'a> Parser<'a> {
} }
} }
fn eat(&mut self) {
let _ = self.tokens.next();
}
fn get_real( fn get_real(
&mut self, &mut self,
matcher: impl Fn(&Token) -> bool, matcher: impl Fn(&Token) -> bool,
@ -163,7 +169,15 @@ impl<'a> Parser<'a> {
} }
fn ask_constant(&mut self) -> Result<Spanned<ItemConstant>, ParserError> { fn ask_constant(&mut self) -> Result<Spanned<ItemConstant>, ParserError> {
Err(self.expected("the constant to be implemented")) let Spanned(_, kSp) = self.get_real(
|token| matches!(token, Token::Ident(Ident::Constant)),
"`Constant`",
)?;
let Spanned(name, nSp) = self.ask_ident()?;
let Spanned(_, eqSp) = self.get_real(|token| matches!(token, Token::Equals), "`=`")?;
let Spanned(expr, exprSp) = self.ask_expr()?;
Ok(Spanned::new(ItemConstant { name, expr }, [kSp, nSp, eqSp, exprSp, self.semi()?]))
} }
fn ask_item(&mut self) -> Result<Spanned<Item>, ParserError> { fn ask_item(&mut self) -> Result<Spanned<Item>, ParserError> {
@ -228,6 +242,10 @@ fn fill_while<T>(
Ok(real) Ok(real)
} }
pub fn parse(source: &str) -> Result<IDLModule, ParserError> {
Parser::new(source).parse()
}
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ParserError { pub enum ParserError {
// expected, got // expected, got

View file

8
programs/aidl/status.md Normal file
View file

@ -0,0 +1,8 @@
# aidl status
## parser
[x] `Use module.thing`
[x] `Alias Thing = OtherThing`
## codegen
TODO!