1
0
Fork 0

feat(trixy-lang_parser): Add support for Type

This includes rust like generic types like:
```
Option<T>
Result<T, E>
```
This commit is contained in:
Benedikt Peetz 2023-12-19 17:27:13 +01:00
parent be066afe23
commit 370aac4395
Signed by: bpeetz
GPG Key ID: A5E94010C3A642AD
9 changed files with 51 additions and 10 deletions

View File

@ -11,8 +11,9 @@ Function = "fn" Identifier "(" [NamedType {"," NamedType }] ")" [ "->" Type ] ";
Namespace = "nasp" Identifier "{" {Function | Namespace | Enumeration | Structure} "}" ; Namespace = "nasp" Identifier "{" {Function | Namespace | Enumeration | Structure} "}" ;
Structure = "struct" Identifier "{" [NamedType {"," NamedType } [","]] "}" ";"; Structure = "struct" Identifier "{" [NamedType {"," NamedType } [","]] "}" ";";
Enumeration = "enum" Identifier "{" [Identifier {"," Identifier} [","]] "}" ";"; Enumeration = "enum" Identifier "{" [Identifier {"," Identifier} [","]] "}" ";";
Identifier = CHARACTER { NUMBER | CHARACTER } ; Identifier = (CHARACTER | "_") { NUMBER | CHARACTER | "_" } ;
NamedType = Identifier ":" Type; NamedType = Identifier ":" Type;
Type = Identifier ["<" Type {"," Type} ">"];
# (* # (*
# vim: ft=ebnf # vim: ft=ebnf

View File

@ -92,7 +92,7 @@ nasp trinitrix {
/// Remove a keymapping /// Remove a keymapping
/// ///
/// Does nothing, if the keymapping doesn't exists /// Does nothing, if the keymapping doesn't exists
fn remove((/* mode: */ String, /* key: */ String)); fn remove(mode: String, key: String);
/// List declared keymappings /// List declared keymappings
fn get(mode: String); fn get(mode: String);

View File

@ -1,2 +1,2 @@
pub mod checked; // pub mod checked;
pub mod unchecked; pub mod unchecked;

View File

@ -55,7 +55,7 @@ pub enum Genus {
pub struct Function { pub struct Function {
pub identifier: Token, // Will later become an Identifier pub identifier: Token, // Will later become an Identifier
pub inputs: Vec<NamedType>, pub inputs: Vec<NamedType>,
pub output: Option<Token>, // Will later become an Type pub output: Option<Type>,
} }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
@ -73,5 +73,11 @@ pub struct Enumeration {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct NamedType { pub struct NamedType {
pub name: Token, // Will later become an Identifier pub name: Token, // Will later become an Identifier
pub r#type: Token, // Will later become an Type pub r#type: Type,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Type {
pub identifier: Token, // Will later become an Identifier
pub generic_args: Vec<Type>,
} }

View File

@ -89,7 +89,7 @@ impl ErrorContext {
pub fn from_index(start: usize, orginal_file: &str) -> Self { pub fn from_index(start: usize, orginal_file: &str) -> Self {
let span = TokenSpan { let span = TokenSpan {
start, start,
end: start, end: start + 1,
}; };
Self::from_span(span, orginal_file) Self::from_span(span, orginal_file)
} }

View File

@ -121,6 +121,8 @@ pub enum TokenKind {
BraceClose, BraceClose,
ParenOpen, ParenOpen,
ParenClose, ParenClose,
SquareOpen,
SquareClose,
/// This is not a real TokenKind, but only used for error handling /// This is not a real TokenKind, but only used for error handling
Dummy, Dummy,
} }
@ -156,6 +158,8 @@ impl Display for TokenKind {
TokenKind::ParenOpen => f.write_str("PARENOPEN"), TokenKind::ParenOpen => f.write_str("PARENOPEN"),
TokenKind::ParenClose => f.write_str("PARENCLOSE"), TokenKind::ParenClose => f.write_str("PARENCLOSE"),
TokenKind::Dummy => f.write_str("DUMMY"), TokenKind::Dummy => f.write_str("DUMMY"),
TokenKind::SquareOpen => f.write_str("SQUAREOPEN"),
TokenKind::SquareClose => f.write_str("SQUARECLOSE"),
} }
} }
} }
@ -211,6 +215,10 @@ macro_rules! token {
[,] => { $crate::lexing::TokenKind::Comma }; [,] => { $crate::lexing::TokenKind::Comma };
[Arrow] => { $crate::lexing::TokenKind::Arrow }; [Arrow] => { $crate::lexing::TokenKind::Arrow };
[->] => { $crate::lexing::TokenKind::Arrow }; [->] => { $crate::lexing::TokenKind::Arrow };
[SquareOpen] => { $crate::lexing::TokenKind::SquareOpen };
[<] => { $crate::lexing::TokenKind::SquareOpen };
[SquareClose] => { $crate::lexing::TokenKind::SquareClose };
[>] => { $crate::lexing::TokenKind::SquareClose};
[BraceOpen] => { $crate::lexing::TokenKind::BraceOpen }; [BraceOpen] => { $crate::lexing::TokenKind::BraceOpen };
// [{] => { $crate::lexing::TokenKind::BraceOpen }; // [{] => { $crate::lexing::TokenKind::BraceOpen };
[BraceClose] => { $crate::lexing::TokenKind::BraceClose }; [BraceClose] => { $crate::lexing::TokenKind::BraceClose };

View File

@ -60,8 +60,14 @@ impl<'a> Tokenizer<'a> {
':' => (TokenKind::Colon, 1), ':' => (TokenKind::Colon, 1),
';' => (TokenKind::Semicolon, 1), ';' => (TokenKind::Semicolon, 1),
',' => (TokenKind::Comma, 1), ',' => (TokenKind::Comma, 1),
'<' => (TokenKind::SquareOpen, 1),
'>' => (TokenKind::SquareClose, 1),
'-' => tokenize_arrow(self.remaining_text)?, '-' => tokenize_arrow(self.remaining_text)?,
c @ '_' | c if c.is_alphanumeric() => tokenize_ident(self.remaining_text)?,
// can't use a OR (`|`) here, as the guard takes precedence
c if c.is_alphabetic() => tokenize_ident(self.remaining_text)?,
'_' => tokenize_ident(self.remaining_text)?,
other => return Err(LexingError::UnknownCharacter(other)), other => return Err(LexingError::UnknownCharacter(other)),
}; };

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
command_spec::unchecked::{ command_spec::unchecked::{
CommandSpec, Declaration, Enumeration, Function, NamedType, Structure, CommandSpec, Declaration, Enumeration, Function, NamedType, Structure, Type,
}, },
error::ErrorContext, error::ErrorContext,
lexing::{Token, TokenKind, TokenStream}, lexing::{Token, TokenKind, TokenStream},
@ -73,6 +73,26 @@ impl Parser {
} }
} }
fn parse_type(&mut self) -> Result<Type, ParsingError> {
let identifier = self.expect(token![Ident])?;
let mut generic_args = vec![];
if self.expect_peek(token![<]) {
self.expect(token![<])?;
if self.expect_peek(token![Ident]) {
generic_args.push(self.parse_type()?);
}
while self.expect_peek(token![Comma]) {
generic_args.push(self.parse_type()?);
}
self.expect(token![>])?;
}
Ok(Type {
identifier,
generic_args,
})
}
fn parse_namespace(&mut self) -> Result<Vec<Declaration>, ParsingError> { fn parse_namespace(&mut self) -> Result<Vec<Declaration>, ParsingError> {
self.expect(token![nasp])?; self.expect(token![nasp])?;
let namespace_name = self.expect(token![Ident])?; let namespace_name = self.expect(token![Ident])?;
@ -140,7 +160,7 @@ impl Parser {
fn parse_named_type(&mut self) -> Result<NamedType, ParsingError> { fn parse_named_type(&mut self) -> Result<NamedType, ParsingError> {
let name = self.expect(token![Ident])?; let name = self.expect(token![Ident])?;
self.expect(token![Colon])?; self.expect(token![Colon])?;
let r#type = self.expect(token![Ident])?; let r#type = self.parse_type()?;
Ok(NamedType { name, r#type }) Ok(NamedType { name, r#type })
} }
@ -162,7 +182,7 @@ impl Parser {
let mut output_type = None; let mut output_type = None;
if self.expect_peek(token![->]) { if self.expect_peek(token![->]) {
self.expect(token![->])?; self.expect(token![->])?;
output_type = Some(self.expect(token![Ident])?); output_type = Some(self.parse_type()?);
} }
self.expect(token![;])?; self.expect(token![;])?;
Ok(Function { Ok(Function {