From 2a9bfb342b234bdc4d3e092c2eb0ce92946139dd Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Mon, 3 Jul 2023 23:11:44 -0500 Subject: [PATCH] More refactoring --- forge_core/src/ast.rs | 56 +++++++- forge_core/src/forge_parser.rs | 242 +++++++++++++-------------------- 2 files changed, 149 insertions(+), 149 deletions(-) diff --git a/forge_core/src/ast.rs b/forge_core/src/ast.rs index bef3b5c..af270ef 100644 --- a/forge_core/src/ast.rs +++ b/forge_core/src/ast.rs @@ -1 +1,55 @@ -use crate::forge_parser::Pair; +#[derive(Eq, PartialEq, Clone, Debug)] +pub enum Declaration { + Function(Function), + Global(Global), + Struct(Struct), + Const(Const), +} + +#[derive(Eq, PartialEq, Clone, Debug, Default)] +pub struct Varinfo { + pub typename: Option, + pub size: Option, +} + +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct Global { + pub name: String, + pub typename: Option, + pub size: Option, +} + +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct Struct { + pub name: String, + pub members: Vec, +} + +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct Member { + pub name: String, + pub typename: Option, + pub size: Option, +} + +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct Const { + pub name: String, + pub value: Option, + pub string: Option, +} + +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct Function { + pub name: String, + pub org: Option, + pub typename: Option, + pub inline: bool, + pub args: Vec, +} + +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct Argname { + pub name: String, + pub typename: Option, +} diff --git a/forge_core/src/forge_parser.rs b/forge_core/src/forge_parser.rs index db958da..8d38cfb 100644 --- a/forge_core/src/forge_parser.rs +++ b/forge_core/src/forge_parser.rs @@ -6,6 +6,7 @@ mod inner { pub struct ForgeParser; } +use crate::ast::*; use inner::*; use pest::error::{Error, LineColLocation}; use std::iter::Peekable; @@ -14,13 +15,20 @@ use std::str::FromStr; pub(crate) type Pair<'a> = pest::iterators::Pair<'a, Rule>; pub(crate) type Pairs<'i, R = Rule> = pest::iterators::Pairs<'i, R>; -trait Children { +trait PairExt { fn first(self) -> Self; fn first_as_string(self) -> String; fn only(self) -> Self; + fn into_number(self) -> i32; + + /// Create a String containing the string represented by a given pair. Since the pair will + /// reference bytes containing escape sequences, this isn't the same as an &str to the + /// original code; this is a new string translating those escape sequences to their actual + /// bytes. + fn into_quoted_string(self) -> String; } -impl<'a> Children for Pair<'a> { +impl<'a> PairExt for Pair<'a> { fn first(self) -> Self { self.into_inner().next().unwrap() } @@ -35,6 +43,36 @@ impl<'a> Children for Pair<'a> { debug_assert_eq!(iter.next(), None); child } + + fn into_number(self) -> i32 { + let first = self.into_inner().next().unwrap(); + match first.as_rule() { + Rule::dec_number | Rule::dec_zero | Rule::neg_number => { + i32::from_str(first.as_str()).unwrap() + } + Rule::hex_number => i32::from_str_radix(first.as_str().get(2..).unwrap(), 16).unwrap(), + Rule::bin_number => i32::from_str_radix(first.as_str().get(2..).unwrap(), 2).unwrap(), + Rule::oct_number => i32::from_str_radix(first.as_str().get(2..).unwrap(), 8).unwrap(), + _ => panic!("Expected a number, got {}", first.as_str()), + } + } + + fn into_quoted_string(self) -> String { + let mut string = String::with_capacity(self.as_str().len()); + for inner in self.into_inner() { + let string_inner = inner.as_str(); + match string_inner { + "\\t" => string.push('\t'), + "\\r" => string.push('\r'), + "\\n" => string.push('\n'), + "\\0" => string.push('\0'), + "\\\\" => string.push('\\'), + "\\\"" => string.push('\"'), + _ => string.push_str(string_inner), + } + } + string + } } trait PairsExt { @@ -52,44 +90,6 @@ impl PairsExt for Peekable> { } } -fn parse_number(pair: Pair) -> i32 { - let first = pair.into_inner().next().unwrap(); - match first.as_rule() { - Rule::dec_number | Rule::dec_zero | Rule::neg_number => { - i32::from_str(first.as_str()).unwrap() - } - Rule::hex_number => i32::from_str_radix(first.as_str().get(2..).unwrap(), 16).unwrap(), - Rule::bin_number => i32::from_str_radix(first.as_str().get(2..).unwrap(), 2).unwrap(), - Rule::oct_number => i32::from_str_radix(first.as_str().get(2..).unwrap(), 8).unwrap(), - _ => panic!("Expected a number, got {}", first.as_str()), - } -} - -/// Create a String containing the string represented by a given pair. Since the pair will -/// reference bytes containing escape sequences, this isn't the same as an &str to the -/// original code; this is a new string translating those escape sequences to their actual -/// bytes. -fn parse_string(pair: Pair) -> String { - let mut string = String::with_capacity(pair.as_str().len()); - for inner in pair.into_inner() { - let string_inner = inner.as_str(); - match string_inner { - "\\t" => string.push('\t'), - "\\r" => string.push('\r'), - "\\n" => string.push('\n'), - "\\0" => string.push('\0'), - "\\\\" => string.push('\\'), - "\\\"" => string.push('\"'), - _ => string.push_str(string_inner), - } - } - string -} - -fn parse_name(pair: Pair) -> &str { - pair.as_str() -} - #[derive(Eq, PartialEq, Clone, Debug)] pub struct ParseError(usize, usize, String); @@ -104,78 +104,70 @@ impl From> for ParseError { } } -trait Parseable<'a>: From> { +trait AstNode: Sized { const RULE: Rule; - fn parse(src: &'a str) -> Result { + fn from_pair(pair: Pair) -> Self; +} + +trait Parseable: Sized { + fn parse(src: &str) -> Result; +} + +impl Parseable for T { + fn parse(src: &str) -> Result { let pair = ForgeParser::parse(Self::RULE, src) .map_err(ParseError::from)? .next() .unwrap(); - Ok(pair.into()) + Ok(Self::from_pair(pair)) } } -#[derive(Eq, PartialEq, Clone, Debug)] -pub enum Declaration { - Function(Function), - Global(Global), - Struct(Struct), - Const(Const), -} +/////////////////////////////////////////////////////////////////////////////////////////// -impl<'a> From> for Declaration { - fn from(pair: Pair) -> Self { +impl AstNode for Declaration { + const RULE: Rule = Rule::declaration; + fn from_pair(pair: Pair) -> Self { match pair.as_rule() { - Rule::function => todo!(), - Rule::global => Self::Global(pair.into()), - Rule::struct_decl => Self::Struct(pair.into()), - Rule::const_decl => Self::Const(pair.into()), + Rule::function => Self::Function(Function::from_pair(pair)), + Rule::global => Self::Global(Global::from_pair(pair)), + Rule::struct_decl => Self::Struct(Struct::from_pair(pair)), + Rule::const_decl => Self::Const(Const::from_pair(pair)), _ => todo!(), } } } -impl Parseable<'_> for Declaration { - const RULE: Rule = Rule::declaration; -} - -#[derive(Eq, PartialEq, Clone, Debug, Default)] -pub struct Varinfo { - typename: Option, - size: Option, -} +/////////////////////////////////////////////////////////////////////////////////////////// impl Varinfo { fn read_or_default(mut pairs: Peekable) -> Self { pairs .next_if_rule(Rule::varinfo) - .map_or(Self::default(), |v| v.into()) + .map_or(Self::default(), Self::from_pair) } } -impl From> for Varinfo { - fn from(pair: Pair<'_>) -> Self { +impl AstNode for Varinfo { + const RULE: Rule = Rule::varinfo; + fn from_pair(pair: Pair) -> Self { let mut children = pair.into_inner().peekable(); let typename = children .next_if_rule(Rule::typename) .map(|t| String::from(t.first().as_str())); let size = children .next_if_rule(Rule::size) - .map(|s| parse_number(s.first())); + .map(|s| s.first().into_number()); Self { typename, size } } } -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct Global { - name: String, - typename: Option, - size: Option, -} +/////////////////////////////////////////////////////////////////////////////////////////// -impl From> for Global { - fn from(global: Pair) -> Self { - let mut inner = global.into_inner().peekable(); +impl AstNode for Global { + const RULE: Rule = Rule::global; + fn from_pair(pair: Pair) -> Self { + let mut inner = pair.into_inner().peekable(); let name = String::from(inner.next().unwrap().as_str()); let varinfo = Varinfo::read_or_default(inner); @@ -187,39 +179,22 @@ impl From> for Global { } } -impl Parseable<'_> for Global { - const RULE: Rule = Rule::global; -} +/////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct Struct { - name: String, - members: Vec, -} - -impl From> for Struct { - fn from(pair: Pair<'_>) -> Self { +impl AstNode for Struct { + const RULE: Rule = Rule::struct_decl; + fn from_pair(pair: Pair<'_>) -> Self { let mut inner = pair.into_inner(); let name = String::from(inner.next().unwrap().as_str()); let member_pairs = inner.next().unwrap().into_inner(); - let members: Vec<_> = member_pairs.map(|member| member.into()).collect(); + let members: Vec<_> = member_pairs.map(Member::from_pair).collect(); Struct { name, members } } } -impl Parseable<'_> for Struct { - const RULE: Rule = Rule::struct_decl; -} - -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct Member { - name: String, - typename: Option, - size: Option, -} - -impl From> for Member { - fn from(pair: Pair<'_>) -> Self { +impl AstNode for Member { + const RULE: Rule = Rule::member; + fn from_pair(pair: Pair<'_>) -> Self { let mut inner = pair.into_inner().peekable(); let name = String::from(inner.next().unwrap().as_str()); let varinfo = Varinfo::read_or_default(inner); @@ -232,53 +207,35 @@ impl From> for Member { } } -impl Parseable<'_> for Member { - const RULE: Rule = Rule::member; -} +/////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct Const { - name: String, - value: Option, - string: Option, -} - -impl From> for Const { - fn from(pair: Pair) -> Self { +impl AstNode for Const { + const RULE: Rule = Rule::const_decl; + fn from_pair(pair: Pair) -> Self { let mut inner = pair.into_inner(); let name = String::from(inner.next().unwrap().as_str()); let value = inner.next().unwrap(); match value.as_rule() { Rule::string => Const { name, - string: Some(String::from(parse_string(value))), + string: Some(String::from(value.into_quoted_string())), value: None, }, Rule::number => Const { name, string: None, - value: Some(parse_number(value)), + value: Some(value.into_number()), }, _ => unreachable!(), } } } -impl Parseable<'_> for Const { - const RULE: Rule = Rule::const_decl; -} +/////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct Function { - name: String, - org: Option, - typename: Option, - inline: bool, - args: Vec, -} - -impl From> for Function { - fn from(pair: Pair<'_>) -> Self { +impl AstNode for Function { + const RULE: Rule = Rule::function; + fn from_pair(pair: Pair<'_>) -> Self { let mut inner = pair.into_inner().peekable(); let name = String::from(inner.next().unwrap().as_str()); let mut inline = false; @@ -289,7 +246,7 @@ impl From> for Function { let annotation = annotation.first(); match annotation.as_rule() { Rule::inline_annotation => inline = true, - Rule::org_annotation => org = Some(parse_number(annotation.first())), + Rule::org_annotation => org = Some(annotation.first().into_number()), Rule::type_annotation => typename = Some(annotation.first_as_string()), _ => unreachable!(), } @@ -299,7 +256,7 @@ impl From> for Function { .next() .unwrap() .into_inner() - .map(|a| Argname::from(a)) + .map(Argname::from_pair) .collect(); Self { @@ -312,18 +269,9 @@ impl From> for Function { } } -impl Parseable<'_> for Function { - const RULE: Rule = Rule::function; -} - -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct Argname { - name: String, - typename: Option, -} - -impl From> for Argname { - fn from(pair: Pair<'_>) -> Self { +impl AstNode for Argname { + const RULE: Rule = Rule::argname; + fn from_pair(pair: Pair<'_>) -> Self { let mut inner = pair.into_inner().peekable(); let name = String::from(inner.next().unwrap().as_str()); let typename = inner.next().map(|t| String::from(t.first().as_str())); @@ -331,9 +279,7 @@ impl From> for Argname { } } -impl Parseable<'_> for Argname { - const RULE: Rule = Rule::argname; -} +/////////////////////////////////////////////////////////////////////////////////////////// #[cfg(test)] mod test {