split up parser into folder

This commit is contained in:
NotAFile 2022-01-16 22:06:52 +01:00
parent 7238d6991c
commit c2628102cc
6 changed files with 160 additions and 144 deletions

View File

@ -140,7 +140,7 @@ pub fn lower_module(pa_module: parser::Module) -> Result<String, CompileError> {
parser::ModuleItem::Assign(assignment) => { parser::ModuleItem::Assign(assignment) => {
lower_assignment(&context, &mut ir_module, assignment)? lower_assignment(&context, &mut ir_module, assignment)?
} }
parser::ModuleItem::Proc(proc) => todo!("lowering process") parser::ModuleItem::Proc(proc) => todo!("lowering process"),
} }
} }
ir_module.write_rtlil(&mut writer); ir_module.write_rtlil(&mut writer);

View File

@ -4,11 +4,11 @@ mod literals;
mod parser; mod parser;
mod rtlil; mod rtlil;
use nom::error::convert_error;
use std::fs::File; use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
use structopt::StructOpt; use structopt::StructOpt;
use nom::error::convert_error;
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
#[structopt(name = "example", about = "An example of StructOpt usage.")] #[structopt(name = "example", about = "An example of StructOpt usage.")]

View File

@ -1,3 +1,6 @@
mod module;
mod proc;
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::tag, bytes::complete::tag,
@ -17,6 +20,7 @@ pub type Span<'a> = LocatedSpan<&'a str>;
pub type IResult<I, O, E = VerboseError<I>> = nom::IResult<I, O, E>; pub type IResult<I, O, E = VerboseError<I>> = nom::IResult<I, O, E>;
use crate::literals::hexadecimal; use crate::literals::hexadecimal;
pub use crate::parser::module::{module, Module, ModuleItem, PortDirection};
fn ws0<'a, F: 'a, O, E: ParseError<Span<'a>>>( fn ws0<'a, F: 'a, O, E: ParseError<Span<'a>>>(
inner: F, inner: F,
@ -49,56 +53,6 @@ pub struct NetDecl<'a> {
pub value: Option<(u64, u64)>, pub value: Option<(u64, u64)>,
} }
#[derive(Debug)]
pub enum PortDirection {
Input,
Output,
}
#[derive(Debug)]
pub struct PortDecl<'a> {
pub pos: Span<'a>,
pub direction: PortDirection,
pub net: NetDecl<'a>,
}
#[derive(Debug)]
pub struct Module<'a> {
pub name: &'a str,
pub ports: Vec<PortDecl<'a>>,
pub items: Vec<ModuleItem<'a>>,
}
#[derive(Debug)]
pub enum ModuleItem<'a> {
Assign(Assign<'a>),
Proc(ProcBlock<'a>),
}
#[derive(Debug)]
pub struct ProcBlock<'a> {
pub net: Span<'a>,
pub items: Vec<ProcStatement<'a>>,
}
#[derive(Debug)]
pub enum ProcStatement<'a> {
IfElse(IfElseBlock),
Assign,
Match(MatchBlock<'a>),
}
// TODO: postponed because annoying to implement
#[derive(Debug)]
pub struct IfElseBlock {
}
#[derive(Debug)]
pub struct MatchBlock<'a> {
expr: Expression<'a>,
arms: Vec<(&'a str, ProcStatement<'a>)>
}
#[derive(Debug)] #[derive(Debug)]
pub struct Assign<'a> { pub struct Assign<'a> {
pub lhs: &'a str, pub lhs: &'a str,
@ -140,27 +94,6 @@ fn declaration(i: Span) -> IResult<Span, NetDecl> {
)(i) )(i)
} }
fn port_decl(i: Span) -> IResult<Span, PortDecl> {
map(
consumed(tuple((
alt((
map(tag("input"), |_| PortDirection::Input),
map(tag("output"), |_| PortDirection::Output),
)),
declaration,
))),
|(pos, (direction, net))| PortDecl {
pos,
direction,
net,
},
)(i)
}
fn ports_list(input: Span) -> IResult<Span, Vec<PortDecl>> {
separated_list0(ws0(char(',')), ws0(port_decl))(input)
}
fn operation(input: Span) -> IResult<Span, Operation> { fn operation(input: Span) -> IResult<Span, Operation> {
// temporarily given up on before I learn the shunting yard algorithm // temporarily given up on before I learn the shunting yard algorithm
alt(( alt((
@ -212,11 +145,9 @@ fn assign_statement(input: Span) -> IResult<Span, Assign> {
ws0(terminated(tag("assign"), multispace1)), ws0(terminated(tag("assign"), multispace1)),
map( map(
separated_pair(ws0(identifier), char('='), ws0(expression)), separated_pair(ws0(identifier), char('='), ws0(expression)),
|(lhs, expr)| { |(lhs, expr)| Assign {
Assign {
lhs: (*lhs.fragment()), lhs: (*lhs.fragment()),
expr, expr,
}
}, },
), ),
ws0(char(';')), ws0(char(';')),
@ -224,70 +155,6 @@ fn assign_statement(input: Span) -> IResult<Span, Assign> {
)(input) )(input)
} }
/// parse a statement that is valid inside a proc block
fn proc_statement(input: Span) -> IResult<Span, ProcStatement> {
map(
nom::character::complete::anychar,
|_| {
ProcStatement::Match(MatchBlock {
expr: Expression::Ident("asdf"),
arms: Vec::new(),
})
}
)(input)
}
fn proc_block(input: Span) -> IResult<Span, ProcBlock> {
context(
"proc block",
map(
tuple((
ws0(tag("proc")),
ws0(delimited(char('('), ws0(identifier), char(')'))),
ws0(delimited(char('{'), many0(ws0(proc_statement)), char('}')))
)),
|(_, net, items)| {
ProcBlock {
net,
items,
}
}
)
)(input)
}
fn module_item(input: Span) -> IResult<Span, ModuleItem> {
alt((
map(assign_statement, |assig| ModuleItem::Assign(assig)),
map(proc_block, |proc| ModuleItem::Proc(proc)),
))(input)
}
/// parse a top-level module declaration
pub fn module(input: Span) -> IResult<Span, Module> {
context(
"module",
map(
tuple((
tag("module"),
ws0(identifier),
ws0(delimited(char('('), ws0(ports_list), char(')'))),
ws0(delimited(
char('{'),
many1(ws0(module_item)),
char('}'),
)),
)),
|(_, name, ports, items)| Module {
name: (*name.fragment()),
ports,
items,
},
),
)(input)
}
pub fn parse(input: Span) -> IResult<Span, Module> { pub fn parse(input: Span) -> IResult<Span, Module> {
module(input) module(input)
} }

89
src/parser/module.rs Normal file
View File

@ -0,0 +1,89 @@
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, u64 as decimal},
combinator::{consumed, map, opt, recognize},
error::{context, ParseError, VerboseError},
multi::{many0, many1, separated_list0},
sequence::{delimited, pair, preceded, separated_pair, terminated, tuple},
};
use crate::parser::proc::{proc_block, ProcBlock};
use crate::parser::{
assign_statement, declaration, identifier, intliteral, widthspec, ws0, Assign, IResult,
NetDecl, Span,
};
#[derive(Debug)]
pub enum PortDirection {
Input,
Output,
}
#[derive(Debug)]
pub struct PortDecl<'a> {
pub pos: Span<'a>,
pub direction: PortDirection,
pub net: NetDecl<'a>,
}
#[derive(Debug)]
pub struct Module<'a> {
pub name: &'a str,
pub ports: Vec<PortDecl<'a>>,
pub items: Vec<ModuleItem<'a>>,
}
#[derive(Debug)]
pub enum ModuleItem<'a> {
Assign(Assign<'a>),
Proc(ProcBlock<'a>),
}
fn port_decl(i: Span) -> IResult<Span, PortDecl> {
map(
consumed(tuple((
alt((
map(tag("input"), |_| PortDirection::Input),
map(tag("output"), |_| PortDirection::Output),
)),
declaration,
))),
|(pos, (direction, net))| PortDecl {
pos,
direction,
net,
},
)(i)
}
fn ports_list(input: Span) -> IResult<Span, Vec<PortDecl>> {
separated_list0(ws0(char(',')), ws0(port_decl))(input)
}
fn module_item(input: Span) -> IResult<Span, ModuleItem> {
alt((
map(assign_statement, |assig| ModuleItem::Assign(assig)),
map(proc_block, |proc| ModuleItem::Proc(proc)),
))(input)
}
/// parse a top-level module declaration
pub fn module(input: Span) -> IResult<Span, Module> {
context(
"module",
map(
tuple((
tag("module"),
ws0(identifier),
ws0(delimited(char('('), ws0(ports_list), char(')'))),
ws0(delimited(char('{'), many1(ws0(module_item)), char('}'))),
)),
|(_, name, ports, items)| Module {
name: (*name.fragment()),
ports,
items,
},
),
)(input)
}

58
src/parser/proc.rs Normal file
View File

@ -0,0 +1,58 @@
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, u64 as decimal},
combinator::{consumed, map, opt, recognize},
error::{context, ParseError, VerboseError},
multi::{many0, many1, separated_list0},
sequence::{delimited, pair, preceded, separated_pair, terminated, tuple},
};
use crate::parser::{identifier, ws0, Expression, IResult, Span};
#[derive(Debug)]
pub struct ProcBlock<'a> {
pub net: Span<'a>,
pub items: Vec<ProcStatement<'a>>,
}
#[derive(Debug)]
pub enum ProcStatement<'a> {
IfElse(IfElseBlock),
Assign,
Match(MatchBlock<'a>),
}
// TODO: postponed because annoying to implement
#[derive(Debug)]
pub struct IfElseBlock {}
#[derive(Debug)]
pub struct MatchBlock<'a> {
expr: Expression<'a>,
arms: Vec<(&'a str, ProcStatement<'a>)>,
}
/// parse a statement that is valid inside a proc block
fn proc_statement(input: Span) -> IResult<Span, ProcStatement> {
map(nom::character::complete::anychar, |_| {
ProcStatement::Match(MatchBlock {
expr: Expression::Ident("asdf"),
arms: Vec::new(),
})
})(input)
}
pub fn proc_block(input: Span) -> IResult<Span, ProcBlock> {
context(
"proc block",
map(
tuple((
ws0(tag("proc")),
ws0(delimited(char('('), ws0(identifier), char(')'))),
ws0(delimited(char('{'), many0(ws0(proc_statement)), char('}'))),
)),
|(_, net, items)| ProcBlock { net, items },
),
)(input)
}

View File

@ -144,7 +144,8 @@ impl Module {
} }
pub fn add_connection(&mut self, target: &str, source: &str) { pub fn add_connection(&mut self, target: &str, source: &str) {
self.connections.push((SigSpec::wire(target), SigSpec::wire(source))) self.connections
.push((SigSpec::wire(target), SigSpec::wire(source)))
} }
pub fn add_cell(&mut self, cell: Cell) { pub fn add_cell(&mut self, cell: Cell) {
@ -200,7 +201,8 @@ impl Cell {
} }
pub fn add_connection(&mut self, from: &str, to: &str) { pub fn add_connection(&mut self, from: &str, to: &str) {
self.connections.push((SigSpec::wire(from), SigSpec::wire(to))) self.connections
.push((SigSpec::wire(from), SigSpec::wire(to)))
} }
} }