From 1460d09f9582a02ae6f9a4c10aa101658414b62b Mon Sep 17 00:00:00 2001 From: nothendev Date: Thu, 4 May 2023 19:50:17 +0300 Subject: [PATCH] why not literals --- programs/aidl/assets/core.idl | 1 + programs/aidl/assets/vfs.idl | 2 +- programs/aidl/assets/why.idl | 3 +- programs/aidl/src/ast.rs | 2 + programs/aidl/src/lexer.rs | 41 ++++++++++++++- programs/aidl/src/main.rs | 3 ++ programs/aidl/src/parser/expr.rs | 51 +++++++++++++++++++ programs/aidl/src/parser/interface.rs | 0 .../aidl/src/{parser.rs => parser/mod.rs} | 30 ++++++++--- programs/aidl/src/parser/structure.rs | 0 programs/aidl/status.md | 8 +++ 11 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 programs/aidl/src/parser/expr.rs create mode 100644 programs/aidl/src/parser/interface.rs rename programs/aidl/src/{parser.rs => parser/mod.rs} (91%) create mode 100644 programs/aidl/src/parser/structure.rs create mode 100644 programs/aidl/status.md diff --git a/programs/aidl/assets/core.idl b/programs/aidl/assets/core.idl index 2049a70..508ba9c 100644 --- a/programs/aidl/assets/core.idl +++ b/programs/aidl/assets/core.idl @@ -1,4 +1,5 @@ Type Byte = U8; +Type Int = U32; Type String = Vector; Enumurate Boolean { diff --git a/programs/aidl/assets/vfs.idl b/programs/aidl/assets/vfs.idl index 7b97604..c9131ad 100644 --- a/programs/aidl/assets/vfs.idl +++ b/programs/aidl/assets/vfs.idl @@ -1,7 +1,7 @@ // core provides lots of useful types like String and Byte Use core; -Constant VERSION Version { +Constant VERSION = Version { major: 1, minor: 0, patch: 0, diff --git a/programs/aidl/assets/why.idl b/programs/aidl/assets/why.idl index d2edc1e..b2e858e 100644 --- a/programs/aidl/assets/why.idl +++ b/programs/aidl/assets/why.idl @@ -1,4 +1,5 @@ Use core.Byte; Use core.Int; -Alias Thing = Byte; +Constant Hi = "WHY???/\n"; +Alias Yo = Byte; diff --git a/programs/aidl/src/ast.rs b/programs/aidl/src/ast.rs index 364f4e4..d763528 100644 --- a/programs/aidl/src/ast.rs +++ b/programs/aidl/src/ast.rs @@ -40,6 +40,7 @@ pub struct ItemAlias { #[derive(Debug)] pub struct ItemConstant { pub name: String, + pub expr: Expr } #[derive(Debug)] @@ -56,6 +57,7 @@ pub enum Expr { pub enum Literal { String(String), Number(NumberLiteral), + Char(char) } #[derive(Debug)] diff --git a/programs/aidl/src/lexer.rs b/programs/aidl/src/lexer.rs index 7ec404c..c6999b5 100644 --- a/programs/aidl/src/lexer.rs +++ b/programs/aidl/src/lexer.rs @@ -41,6 +41,19 @@ pub enum Token { #[token(".")] 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))] Ident(Ident), @@ -62,10 +75,36 @@ pub enum Ident { Alias, #[token("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), } +#[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)] pub struct Span(pub Range); impl Span { diff --git a/programs/aidl/src/main.rs b/programs/aidl/src/main.rs index e331ad8..4cde877 100644 --- a/programs/aidl/src/main.rs +++ b/programs/aidl/src/main.rs @@ -1,5 +1,8 @@ +#![feature(result_option_inspect)] #![allow(non_snake_case)] +use lexer::Token; +use logos::Logos; use parser::Parser; mod ast; diff --git a/programs/aidl/src/parser/expr.rs b/programs/aidl/src/parser/expr.rs new file mode 100644 index 0000000..51b9295 --- /dev/null +++ b/programs/aidl/src/parser/expr.rs @@ -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, 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, 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")), + }) + } +} diff --git a/programs/aidl/src/parser/interface.rs b/programs/aidl/src/parser/interface.rs new file mode 100644 index 0000000..e69de29 diff --git a/programs/aidl/src/parser.rs b/programs/aidl/src/parser/mod.rs similarity index 91% rename from programs/aidl/src/parser.rs rename to programs/aidl/src/parser/mod.rs index 8586682..82e37d2 100644 --- a/programs/aidl/src/parser.rs +++ b/programs/aidl/src/parser/mod.rs @@ -1,12 +1,14 @@ -use logos::{Lexer, Logos, SpannedIter}; +mod expr; +mod interface; +mod structure; + +use logos::{Lexer, Logos}; use crate::{ ast::{IDLModule, Item, ItemAlias, ItemConstant, ItemInterface, ModulePath, UseDecl}, lexer::{Ident, Span, Spanned, Token}, }; -use std::iter::{Filter, Iterator, Peekable}; - -type Wtf<'a> = Peekable, Box) -> bool>>>; +use std::iter::Iterator; struct TokenIterator<'a> { lexer: Lexer<'a, Token>, @@ -54,7 +56,7 @@ impl<'a> TokenIterator<'a> { } } -pub struct Parser<'a> { +pub(crate) struct Parser<'a> { tokens: TokenIterator<'a>, } @@ -65,6 +67,10 @@ impl<'a> Parser<'a> { } } + fn eat(&mut self) { + let _ = self.tokens.next(); + } + fn get_real( &mut self, matcher: impl Fn(&Token) -> bool, @@ -163,7 +169,15 @@ impl<'a> Parser<'a> { } fn ask_constant(&mut self) -> Result, 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, ParserError> { @@ -228,6 +242,10 @@ fn fill_while( Ok(real) } +pub fn parse(source: &str) -> Result { + Parser::new(source).parse() +} + #[derive(thiserror::Error, Debug)] pub enum ParserError { // expected, got diff --git a/programs/aidl/src/parser/structure.rs b/programs/aidl/src/parser/structure.rs new file mode 100644 index 0000000..e69de29 diff --git a/programs/aidl/status.md b/programs/aidl/status.md new file mode 100644 index 0000000..9c0e882 --- /dev/null +++ b/programs/aidl/status.md @@ -0,0 +1,8 @@ +# aidl status + +## parser +[x] `Use module.thing` +[x] `Alias Thing = OtherThing` + +## codegen +TODO!