use std::sync::{Arc, OnceLock};
use crate::{
err::ParseError,
instance::InstanceBuilder,
self_builder,
span::{ParsedId, Span},
};
use netlist_macros::Builder;
#[derive(Debug, Clone, Copy, Builder)]
pub enum ValueBuilder {
Num(f64),
Expr(Span),
}
#[derive(Debug, Clone, Default, Copy, Builder)]
pub struct KeyValueBuilder {
pub k: Span,
pub v: ValueBuilder,
}
#[derive(Debug, Clone, Copy, Builder)]
pub enum TokenBuilder {
KV(KeyValueBuilder),
Value(ValueBuilder),
V(Span),
I(Span),
}
#[derive(Debug, Clone, Copy)]
pub enum GeneralCmd {
Ic,
Meas,
}
self_builder!(GeneralCmd);
#[derive(Debug, Clone, Builder)]
pub struct GeneralBuilder {
pub cmd: GeneralCmd,
pub tokens: Vec<TokenBuilder>,
}
#[derive(Debug, Clone, Builder)]
pub struct UnknwonBuilder {
pub cmd: Span,
pub tokens: Vec<TokenBuilder>,
}
#[derive(Debug, Clone, Builder)]
pub struct ModelBuilder {
pub name: Span,
pub model_type: ModelTypeBuilder,
pub params: Vec<KeyValueBuilder>,
}
#[derive(Debug, Clone, Copy, Builder)]
pub enum ModelTypeBuilder {
AMP,
C,
CORE,
D,
L,
NJF,
NMOS,
NPN,
OPT,
PJF,
PMOS,
PNP,
R,
U,
W,
S,
Unknown(Span),
}
#[derive(Debug, Clone, Builder)]
pub struct DataBuilder {
pub name: Span,
pub values: DataValuesBuilder,
}
#[derive(Debug, Clone, Builder)]
pub enum DataValuesBuilder {
InlineExpr {
params: Vec<Span>,
values: Vec<ValueBuilder>,
},
InlineNum {
params: Vec<Span>,
values: Vec<f64>,
},
MER(DataFilesBuilder),
LAM(DataFilesBuilder),
}
#[derive(Debug, Clone, Builder)]
pub struct DataFilesBuilder {
pub files: Vec<DataFileBuilder>,
pub out: Option<Span>,
}
#[derive(Debug, Clone, Builder)]
pub struct DataFileBuilder {
pub file: Span,
pub pname_col_num: Vec<PnameColNumBuilder>,
}
#[derive(Debug, Clone, Builder)]
pub struct PnameColNumBuilder {
pub pname: Span,
pub col_num: usize,
}
#[derive(Debug)]
pub struct SubcktBuilder {
pub name: Span,
pub ports: Vec<Span>,
pub params: Vec<KeyValueBuilder>,
pub ast: ASTBuilder,
}
#[derive(Debug, Default)]
pub struct LocalAST {
pub subckt: Vec<SubcktBuilder>,
pub instance: Vec<InstanceBuilder>,
pub model: Vec<ModelBuilder>,
pub param: Vec<KeyValueBuilder>,
pub option: Vec<(Span, Option<ValueBuilder>)>,
pub data: Vec<DataBuilder>,
pub general: Vec<GeneralBuilder>,
pub init_condition: Vec<(Span, ValueBuilder, Option<Span>)>,
pub nodeset: Vec<(Span, ValueBuilder, Option<Span>)>,
pub unknwon: Vec<UnknwonBuilder>,
pub errors: Vec<ParseError>,
}
impl LocalAST {
pub fn is_empty(&self) -> bool {
self.subckt.is_empty()
&& self.instance.is_empty()
&& self.model.is_empty()
&& self.param.is_empty()
&& self.option.is_empty()
&& self.data.is_empty()
&& self.general.is_empty()
&& self.unknwon.is_empty()
&& self.errors.is_empty()
}
}
#[derive(Debug)]
pub enum Segment {
Local(Box<LocalAST>),
Include(Arc<OnceLock<Result<ParsedId, ParseError>>>),
}
#[derive(Debug, Default)]
pub struct ASTBuilder {
pub segments: Vec<Segment>,
}
impl ASTBuilder {
pub fn new() -> Self {
Self {
segments: Vec::new(),
}
}
}
impl Default for ValueBuilder {
#[inline]
fn default() -> Self {
Self::Num(0.0)
}
}
impl From<(&str, Span)> for ModelTypeBuilder {
#[inline]
fn from(value: (&str, Span)) -> Self {
let (_str, _type) = value;
match _str.to_uppercase().as_str() {
"AMP" => Self::AMP,
"C" => Self::C,
"CORE" => Self::CORE,
"D" => Self::D,
"L" => Self::L,
"NJF" => Self::NJF,
"NMOS" => Self::NMOS,
"NPN" => Self::NPN,
"OPT" => Self::OPT,
"PJF" => Self::PJF,
"PMOS" => Self::PMOS,
"PNP" => Self::PNP,
"R" => Self::R,
"U" => Self::U,
"W" => Self::W,
"S" => Self::S,
_ => Self::Unknown(_type),
}
}
}