More refactoring
This commit is contained in:
+55
-1
@@ -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<String>,
|
||||||
|
pub size: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
|
pub struct Global {
|
||||||
|
pub name: String,
|
||||||
|
pub typename: Option<String>,
|
||||||
|
pub size: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
|
pub struct Struct {
|
||||||
|
pub name: String,
|
||||||
|
pub members: Vec<Member>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
|
pub struct Member {
|
||||||
|
pub name: String,
|
||||||
|
pub typename: Option<String>,
|
||||||
|
pub size: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
|
pub struct Const {
|
||||||
|
pub name: String,
|
||||||
|
pub value: Option<i32>,
|
||||||
|
pub string: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
|
pub struct Function {
|
||||||
|
pub name: String,
|
||||||
|
pub org: Option<i32>,
|
||||||
|
pub typename: Option<String>,
|
||||||
|
pub inline: bool,
|
||||||
|
pub args: Vec<Argname>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
|
pub struct Argname {
|
||||||
|
pub name: String,
|
||||||
|
pub typename: Option<String>,
|
||||||
|
}
|
||||||
|
|||||||
+94
-148
@@ -6,6 +6,7 @@ mod inner {
|
|||||||
pub struct ForgeParser;
|
pub struct ForgeParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::ast::*;
|
||||||
use inner::*;
|
use inner::*;
|
||||||
use pest::error::{Error, LineColLocation};
|
use pest::error::{Error, LineColLocation};
|
||||||
use std::iter::Peekable;
|
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 Pair<'a> = pest::iterators::Pair<'a, Rule>;
|
||||||
pub(crate) type Pairs<'i, R = Rule> = pest::iterators::Pairs<'i, R>;
|
pub(crate) type Pairs<'i, R = Rule> = pest::iterators::Pairs<'i, R>;
|
||||||
|
|
||||||
trait Children {
|
trait PairExt {
|
||||||
fn first(self) -> Self;
|
fn first(self) -> Self;
|
||||||
fn first_as_string(self) -> String;
|
fn first_as_string(self) -> String;
|
||||||
fn only(self) -> Self;
|
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 {
|
fn first(self) -> Self {
|
||||||
self.into_inner().next().unwrap()
|
self.into_inner().next().unwrap()
|
||||||
}
|
}
|
||||||
@@ -35,6 +43,36 @@ impl<'a> Children for Pair<'a> {
|
|||||||
debug_assert_eq!(iter.next(), None);
|
debug_assert_eq!(iter.next(), None);
|
||||||
child
|
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 {
|
trait PairsExt {
|
||||||
@@ -52,44 +90,6 @@ impl PairsExt for Peekable<Pairs<'_>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)]
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct ParseError(usize, usize, String);
|
pub struct ParseError(usize, usize, String);
|
||||||
|
|
||||||
@@ -104,78 +104,70 @@ impl From<pest::error::Error<Rule>> for ParseError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Parseable<'a>: From<Pair<'a>> {
|
trait AstNode: Sized {
|
||||||
const RULE: Rule;
|
const RULE: Rule;
|
||||||
fn parse(src: &'a str) -> Result<Self, ParseError> {
|
fn from_pair(pair: Pair) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Parseable: Sized {
|
||||||
|
fn parse(src: &str) -> Result<Self, ParseError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AstNode> Parseable for T {
|
||||||
|
fn parse(src: &str) -> Result<Self, ParseError> {
|
||||||
let pair = ForgeParser::parse(Self::RULE, src)
|
let pair = ForgeParser::parse(Self::RULE, src)
|
||||||
.map_err(ParseError::from)?
|
.map_err(ParseError::from)?
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.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<Pair<'a>> for Declaration {
|
impl AstNode for Declaration {
|
||||||
fn from(pair: Pair) -> Self {
|
const RULE: Rule = Rule::declaration;
|
||||||
|
fn from_pair(pair: Pair) -> Self {
|
||||||
match pair.as_rule() {
|
match pair.as_rule() {
|
||||||
Rule::function => todo!(),
|
Rule::function => Self::Function(Function::from_pair(pair)),
|
||||||
Rule::global => Self::Global(pair.into()),
|
Rule::global => Self::Global(Global::from_pair(pair)),
|
||||||
Rule::struct_decl => Self::Struct(pair.into()),
|
Rule::struct_decl => Self::Struct(Struct::from_pair(pair)),
|
||||||
Rule::const_decl => Self::Const(pair.into()),
|
Rule::const_decl => Self::Const(Const::from_pair(pair)),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable<'_> for Declaration {
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const RULE: Rule = Rule::declaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug, Default)]
|
|
||||||
pub struct Varinfo {
|
|
||||||
typename: Option<String>,
|
|
||||||
size: Option<i32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Varinfo {
|
impl Varinfo {
|
||||||
fn read_or_default(mut pairs: Peekable<Pairs>) -> Self {
|
fn read_or_default(mut pairs: Peekable<Pairs>) -> Self {
|
||||||
pairs
|
pairs
|
||||||
.next_if_rule(Rule::varinfo)
|
.next_if_rule(Rule::varinfo)
|
||||||
.map_or(Self::default(), |v| v.into())
|
.map_or(Self::default(), Self::from_pair)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Pair<'_>> for Varinfo {
|
impl AstNode for Varinfo {
|
||||||
fn from(pair: Pair<'_>) -> Self {
|
const RULE: Rule = Rule::varinfo;
|
||||||
|
fn from_pair(pair: Pair) -> Self {
|
||||||
let mut children = pair.into_inner().peekable();
|
let mut children = pair.into_inner().peekable();
|
||||||
let typename = children
|
let typename = children
|
||||||
.next_if_rule(Rule::typename)
|
.next_if_rule(Rule::typename)
|
||||||
.map(|t| String::from(t.first().as_str()));
|
.map(|t| String::from(t.first().as_str()));
|
||||||
let size = children
|
let size = children
|
||||||
.next_if_rule(Rule::size)
|
.next_if_rule(Rule::size)
|
||||||
.map(|s| parse_number(s.first()));
|
.map(|s| s.first().into_number());
|
||||||
Self { typename, size }
|
Self { typename, size }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
pub struct Global {
|
|
||||||
name: String,
|
|
||||||
typename: Option<String>,
|
|
||||||
size: Option<i32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Pair<'_>> for Global {
|
impl AstNode for Global {
|
||||||
fn from(global: Pair) -> Self {
|
const RULE: Rule = Rule::global;
|
||||||
let mut inner = global.into_inner().peekable();
|
fn from_pair(pair: Pair) -> Self {
|
||||||
|
let mut inner = pair.into_inner().peekable();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
let name = String::from(inner.next().unwrap().as_str());
|
||||||
let varinfo = Varinfo::read_or_default(inner);
|
let varinfo = Varinfo::read_or_default(inner);
|
||||||
|
|
||||||
@@ -187,39 +179,22 @@ impl From<Pair<'_>> for Global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable<'_> for Global {
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const RULE: Rule = Rule::global;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
impl AstNode for Struct {
|
||||||
pub struct Struct {
|
const RULE: Rule = Rule::struct_decl;
|
||||||
name: String,
|
fn from_pair(pair: Pair<'_>) -> Self {
|
||||||
members: Vec<Member>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Pair<'_>> for Struct {
|
|
||||||
fn from(pair: Pair<'_>) -> Self {
|
|
||||||
let mut inner = pair.into_inner();
|
let mut inner = pair.into_inner();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
let name = String::from(inner.next().unwrap().as_str());
|
||||||
let member_pairs = inner.next().unwrap().into_inner();
|
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 }
|
Struct { name, members }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable<'_> for Struct {
|
impl AstNode for Member {
|
||||||
const RULE: Rule = Rule::struct_decl;
|
const RULE: Rule = Rule::member;
|
||||||
}
|
fn from_pair(pair: Pair<'_>) -> Self {
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
|
||||||
pub struct Member {
|
|
||||||
name: String,
|
|
||||||
typename: Option<String>,
|
|
||||||
size: Option<i32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Pair<'_>> for Member {
|
|
||||||
fn from(pair: Pair<'_>) -> Self {
|
|
||||||
let mut inner = pair.into_inner().peekable();
|
let mut inner = pair.into_inner().peekable();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
let name = String::from(inner.next().unwrap().as_str());
|
||||||
let varinfo = Varinfo::read_or_default(inner);
|
let varinfo = Varinfo::read_or_default(inner);
|
||||||
@@ -232,53 +207,35 @@ impl From<Pair<'_>> for Member {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable<'_> for Member {
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const RULE: Rule = Rule::member;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
impl AstNode for Const {
|
||||||
pub struct Const {
|
const RULE: Rule = Rule::const_decl;
|
||||||
name: String,
|
fn from_pair(pair: Pair) -> Self {
|
||||||
value: Option<i32>,
|
|
||||||
string: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Pair<'_>> for Const {
|
|
||||||
fn from(pair: Pair) -> Self {
|
|
||||||
let mut inner = pair.into_inner();
|
let mut inner = pair.into_inner();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
let name = String::from(inner.next().unwrap().as_str());
|
||||||
let value = inner.next().unwrap();
|
let value = inner.next().unwrap();
|
||||||
match value.as_rule() {
|
match value.as_rule() {
|
||||||
Rule::string => Const {
|
Rule::string => Const {
|
||||||
name,
|
name,
|
||||||
string: Some(String::from(parse_string(value))),
|
string: Some(String::from(value.into_quoted_string())),
|
||||||
value: None,
|
value: None,
|
||||||
},
|
},
|
||||||
Rule::number => Const {
|
Rule::number => Const {
|
||||||
name,
|
name,
|
||||||
string: None,
|
string: None,
|
||||||
value: Some(parse_number(value)),
|
value: Some(value.into_number()),
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable<'_> for Const {
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const RULE: Rule = Rule::const_decl;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
impl AstNode for Function {
|
||||||
pub struct Function {
|
const RULE: Rule = Rule::function;
|
||||||
name: String,
|
fn from_pair(pair: Pair<'_>) -> Self {
|
||||||
org: Option<i32>,
|
|
||||||
typename: Option<String>,
|
|
||||||
inline: bool,
|
|
||||||
args: Vec<Argname>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Pair<'_>> for Function {
|
|
||||||
fn from(pair: Pair<'_>) -> Self {
|
|
||||||
let mut inner = pair.into_inner().peekable();
|
let mut inner = pair.into_inner().peekable();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
let name = String::from(inner.next().unwrap().as_str());
|
||||||
let mut inline = false;
|
let mut inline = false;
|
||||||
@@ -289,7 +246,7 @@ impl From<Pair<'_>> for Function {
|
|||||||
let annotation = annotation.first();
|
let annotation = annotation.first();
|
||||||
match annotation.as_rule() {
|
match annotation.as_rule() {
|
||||||
Rule::inline_annotation => inline = true,
|
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()),
|
Rule::type_annotation => typename = Some(annotation.first_as_string()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@@ -299,7 +256,7 @@ impl From<Pair<'_>> for Function {
|
|||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_inner()
|
.into_inner()
|
||||||
.map(|a| Argname::from(a))
|
.map(Argname::from_pair)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@@ -312,18 +269,9 @@ impl From<Pair<'_>> for Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable<'_> for Function {
|
impl AstNode for Argname {
|
||||||
const RULE: Rule = Rule::function;
|
const RULE: Rule = Rule::argname;
|
||||||
}
|
fn from_pair(pair: Pair<'_>) -> Self {
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
|
||||||
pub struct Argname {
|
|
||||||
name: String,
|
|
||||||
typename: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Pair<'_>> for Argname {
|
|
||||||
fn from(pair: Pair<'_>) -> Self {
|
|
||||||
let mut inner = pair.into_inner().peekable();
|
let mut inner = pair.into_inner().peekable();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
let name = String::from(inner.next().unwrap().as_str());
|
||||||
let typename = inner.next().map(|t| String::from(t.first().as_str()));
|
let typename = inner.next().map(|t| String::from(t.first().as_str()));
|
||||||
@@ -331,9 +279,7 @@ impl From<Pair<'_>> for Argname {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable<'_> for Argname {
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const RULE: Rule = Rule::argname;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|||||||
Reference in New Issue
Block a user