lab5
This commit is contained in:
50
src/cli.rs
50
src/cli.rs
@@ -27,6 +27,20 @@ pub enum Command {
|
|||||||
input: PathBuf,
|
input: PathBuf,
|
||||||
output_tree: PathBuf,
|
output_tree: PathBuf,
|
||||||
},
|
},
|
||||||
|
Gen {
|
||||||
|
mode: GenMode,
|
||||||
|
input: PathBuf,
|
||||||
|
output: PathBuf,
|
||||||
|
output_symbols: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, clap::ValueEnum)]
|
||||||
|
pub enum GenMode {
|
||||||
|
#[clap(name = "intermediate", alias = "i")]
|
||||||
|
Intermediate,
|
||||||
|
#[clap(name = "postfix", alias = "p")]
|
||||||
|
Postfix,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
@@ -60,6 +74,12 @@ fn validate_inner(args: ArgsInner) -> Result<ArgsInner, clap::Error> {
|
|||||||
} => validate_lex(input, output_tokens, output_symbols)?,
|
} => validate_lex(input, output_tokens, output_symbols)?,
|
||||||
Command::Syn { input, output_tree } => validate_syn(input, output_tree)?,
|
Command::Syn { input, output_tree } => validate_syn(input, output_tree)?,
|
||||||
Command::Sem { input, output_tree } => validate_sem(input, output_tree)?,
|
Command::Sem { input, output_tree } => validate_sem(input, output_tree)?,
|
||||||
|
Command::Gen {
|
||||||
|
mode,
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
output_symbols,
|
||||||
|
} => validate_gen(mode, input, output, output_symbols)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(args)
|
Ok(args)
|
||||||
@@ -129,3 +149,33 @@ fn validate_sem(input: &PathBuf, output_tree: &PathBuf) -> Result<(), clap::Erro
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_gen(
|
||||||
|
_mode: &GenMode,
|
||||||
|
input: &PathBuf,
|
||||||
|
output: &PathBuf,
|
||||||
|
output_symbols: &PathBuf,
|
||||||
|
) -> Result<(), clap::Error> {
|
||||||
|
if !input.is_file() {
|
||||||
|
return Err(clap::Error::raw(
|
||||||
|
clap::error::ErrorKind::InvalidValue,
|
||||||
|
format!("Input file '{}' does not exist", input.display()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if input == output {
|
||||||
|
return Err(clap::Error::raw(
|
||||||
|
clap::error::ErrorKind::InvalidValue,
|
||||||
|
"Input and output files cannot be the same",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
if input == output_symbols {
|
||||||
|
return Err(clap::Error::raw(
|
||||||
|
clap::error::ErrorKind::InvalidValue,
|
||||||
|
"Input and output files cannot be the same",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
253
src/main.rs
253
src/main.rs
@@ -2,107 +2,19 @@ mod ast;
|
|||||||
mod cli;
|
mod cli;
|
||||||
mod error;
|
mod error;
|
||||||
mod parse;
|
mod parse;
|
||||||
|
mod representation;
|
||||||
mod symbols;
|
mod symbols;
|
||||||
|
mod util;
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::{
|
||||||
|
io::{self, Write},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
use ast::{typed::TypedExpr, UntypedExpr};
|
use cli::GenMode;
|
||||||
use parse::parser::Parser;
|
use parse::parser::Parser;
|
||||||
use symbols::SymbolsTable;
|
use symbols::SymbolsTable;
|
||||||
|
|
||||||
fn write_typed_expr(
|
|
||||||
expr: &TypedExpr,
|
|
||||||
symbols: &SymbolsTable,
|
|
||||||
writer: &mut impl Write,
|
|
||||||
prefix: &str,
|
|
||||||
is_last: bool,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
let branch = if is_last { "└──" } else { "├──" };
|
|
||||||
|
|
||||||
write!(writer, "{}{}", prefix, branch)?;
|
|
||||||
|
|
||||||
match expr {
|
|
||||||
TypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
|
||||||
TypedExpr::Float { value, .. } => writeln!(writer, "<{}>", value),
|
|
||||||
TypedExpr::Var { name, .. } => {
|
|
||||||
let ty = symbols.resolve(*name).unwrap().ty.unwrap();
|
|
||||||
writeln!(writer, "<id,{},{}>", name, ty)
|
|
||||||
}
|
|
||||||
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
|
||||||
writeln!(writer, "<{}>", op)?;
|
|
||||||
|
|
||||||
let new_prefix = if is_last {
|
|
||||||
format!("{} ", prefix)
|
|
||||||
} else {
|
|
||||||
format!("{}│ ", prefix)
|
|
||||||
};
|
|
||||||
|
|
||||||
write_typed_expr(lhs, symbols, writer, &new_prefix, false)?;
|
|
||||||
write_typed_expr(rhs, symbols, writer, &new_prefix, true)
|
|
||||||
}
|
|
||||||
TypedExpr::IntToFloat { value, .. } => {
|
|
||||||
writeln!(writer, "i2f")?;
|
|
||||||
|
|
||||||
let new_prefix = if is_last {
|
|
||||||
format!("{} ", prefix)
|
|
||||||
} else {
|
|
||||||
format!("{}│ ", prefix)
|
|
||||||
};
|
|
||||||
|
|
||||||
write_typed_expr(value, symbols, writer, &new_prefix, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_typed_expr(
|
|
||||||
expr: &TypedExpr,
|
|
||||||
symbols: &SymbolsTable,
|
|
||||||
writer: &mut impl Write,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
write_typed_expr(expr, symbols, writer, "", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_untyped_expr(
|
|
||||||
expr: &UntypedExpr,
|
|
||||||
writer: &mut impl Write,
|
|
||||||
prefix: &str,
|
|
||||||
is_last: bool,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
let branch = if is_last { "└──" } else { "├──" };
|
|
||||||
|
|
||||||
write!(writer, "{}{}", prefix, branch)?;
|
|
||||||
|
|
||||||
match expr {
|
|
||||||
UntypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
|
||||||
UntypedExpr::Float { value, .. } => writeln!(writer, "<{}>", value),
|
|
||||||
UntypedExpr::Var {
|
|
||||||
name: id, typename, ..
|
|
||||||
} => {
|
|
||||||
write!(writer, "<id,{}", id)?;
|
|
||||||
if let Some(typename) = typename {
|
|
||||||
write!(writer, ",{}", typename)?;
|
|
||||||
}
|
|
||||||
writeln!(writer, ">")
|
|
||||||
}
|
|
||||||
UntypedExpr::BinOp { lhs, op, rhs, .. } => {
|
|
||||||
writeln!(writer, "<{}>", op)?;
|
|
||||||
|
|
||||||
let new_prefix = if is_last {
|
|
||||||
format!("{} ", prefix)
|
|
||||||
} else {
|
|
||||||
format!("{}│ ", prefix)
|
|
||||||
};
|
|
||||||
|
|
||||||
write_untyped_expr(lhs, writer, &new_prefix, false)?;
|
|
||||||
write_untyped_expr(rhs, writer, &new_prefix, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_untyped_expr(expr: &UntypedExpr, writer: &mut impl Write) -> io::Result<()> {
|
|
||||||
write_untyped_expr(expr, writer, "", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let args = cli::Args::parse();
|
let args = cli::Args::parse();
|
||||||
|
|
||||||
@@ -112,50 +24,74 @@ fn main() -> anyhow::Result<()> {
|
|||||||
output_tokens,
|
output_tokens,
|
||||||
output_symbols,
|
output_symbols,
|
||||||
} => {
|
} => {
|
||||||
let input = std::fs::read_to_string(input)?;
|
lex_command(input, output_tokens, output_symbols)?;
|
||||||
let mut symbols = SymbolsTable::default();
|
}
|
||||||
let tokens =
|
cli::Command::Syn { input, output_tree } => {
|
||||||
parse::lexer::make_tokenizer(&input, &mut symbols).collect::<Result<Vec<_>, _>>();
|
syn_command(input, output_tree)?;
|
||||||
|
}
|
||||||
match tokens {
|
cli::Command::Sem { input, output_tree } => {
|
||||||
Ok(tokens) => {
|
sem_command(input, output_tree)?;
|
||||||
let mut writer_tokens =
|
}
|
||||||
io::BufWriter::new(std::fs::File::create(output_tokens)?);
|
cli::Command::Gen {
|
||||||
|
mode,
|
||||||
for (_, token, _) in tokens {
|
input,
|
||||||
writeln!(writer_tokens, "{token:>6} - {}", token.as_str())?;
|
output,
|
||||||
|
output_symbols,
|
||||||
|
} => {
|
||||||
|
gen_command(mode, input, output, output_symbols)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut writer_symbols =
|
Ok(())
|
||||||
io::BufWriter::new(std::fs::File::create(output_symbols)?);
|
}
|
||||||
|
|
||||||
|
fn gen_command(
|
||||||
|
mode: &GenMode,
|
||||||
|
input: &Path,
|
||||||
|
output: &Path,
|
||||||
|
output_symbols: &Path,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
let input = std::fs::read_to_string(input)?;
|
||||||
|
let mut symbols = SymbolsTable::default();
|
||||||
|
let typed_expr = match {
|
||||||
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
||||||
|
let mut parser = Parser::new(tokens);
|
||||||
|
parser.parse()
|
||||||
|
}
|
||||||
|
.and_then(|expr| ast::to_typed_expr(expr, &mut symbols))
|
||||||
|
{
|
||||||
|
Ok(expr) => expr,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("error: {}", e);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut writer = io::BufWriter::new(std::fs::File::create(output)?);
|
||||||
|
|
||||||
|
match mode {
|
||||||
|
GenMode::Intermediate => {
|
||||||
|
let intermediate_exprs =
|
||||||
|
representation::intermediate::to_intermediate_expr(typed_expr, &mut symbols);
|
||||||
|
util::print_intermediate_exprs(&intermediate_exprs, &mut writer)?;
|
||||||
|
}
|
||||||
|
GenMode::Postfix => {
|
||||||
|
util::print_postfix_exprs(&typed_expr, &mut writer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut writer_symbols = io::BufWriter::new(std::fs::File::create(output_symbols)?);
|
||||||
for (name, data) in &symbols {
|
for (name, data) in &symbols {
|
||||||
writeln!(writer_symbols, "{name} -> {}", data)?;
|
writeln!(writer_symbols, "{name} -> {}", data)?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Err(e) => {
|
Ok(())
|
||||||
eprintln!("error: {}", e);
|
}
|
||||||
}
|
|
||||||
}
|
fn sem_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
||||||
}
|
|
||||||
cli::Command::Syn { input, output_tree } => {
|
|
||||||
let input = std::fs::read_to_string(input)?;
|
let input = std::fs::read_to_string(input)?;
|
||||||
let mut symbols = SymbolsTable::default();
|
let mut symbols = SymbolsTable::default();
|
||||||
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
|
||||||
|
|
||||||
let mut parser = Parser::new(tokens);
|
|
||||||
let res = parser.parse();
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(expr) => {
|
|
||||||
let mut writer_tree = io::BufWriter::new(std::fs::File::create(output_tree)?);
|
|
||||||
print_untyped_expr(&expr, &mut writer_tree)?;
|
|
||||||
}
|
|
||||||
Err(e) => eprintln!("error: {}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cli::Command::Sem { input, output_tree } => {
|
|
||||||
let input = std::fs::read_to_string(input)?;
|
|
||||||
let mut symbols = SymbolsTable::default();
|
|
||||||
let res = {
|
let res = {
|
||||||
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
||||||
let mut parser = Parser::new(tokens);
|
let mut parser = Parser::new(tokens);
|
||||||
@@ -166,12 +102,59 @@ fn main() -> anyhow::Result<()> {
|
|||||||
match res {
|
match res {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
let mut writer_tree = io::BufWriter::new(std::fs::File::create(output_tree)?);
|
let mut writer_tree = io::BufWriter::new(std::fs::File::create(output_tree)?);
|
||||||
print_typed_expr(&expr, &symbols, &mut writer_tree)?;
|
util::print_typed_expr(&expr, &symbols, &mut writer_tree)?;
|
||||||
}
|
}
|
||||||
Err(e) => eprintln!("error: {}", e),
|
Err(e) => eprintln!("error: {}", e),
|
||||||
}
|
};
|
||||||
}
|
|
||||||
}
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn syn_command(input: &Path, output_tree: &Path) -> Result<(), anyhow::Error> {
|
||||||
|
let input = std::fs::read_to_string(input)?;
|
||||||
|
let mut symbols = SymbolsTable::default();
|
||||||
|
|
||||||
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols);
|
||||||
|
let mut parser = Parser::new(tokens);
|
||||||
|
let res = parser.parse();
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(expr) => {
|
||||||
|
let mut writer_tree = io::BufWriter::new(std::fs::File::create(output_tree)?);
|
||||||
|
util::print_untyped_expr(&expr, &mut writer_tree)?;
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!("error: {}", e),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lex_command(
|
||||||
|
input: &Path,
|
||||||
|
output_tokens: &Path,
|
||||||
|
output_symbols: &Path,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
let input = std::fs::read_to_string(input)?;
|
||||||
|
let mut symbols = SymbolsTable::default();
|
||||||
|
let tokens = parse::lexer::make_tokenizer(&input, &mut symbols).collect::<Result<Vec<_>, _>>();
|
||||||
|
|
||||||
|
match tokens {
|
||||||
|
Ok(tokens) => {
|
||||||
|
let mut writer_tokens = io::BufWriter::new(std::fs::File::create(output_tokens)?);
|
||||||
|
|
||||||
|
for (_, token, _) in tokens {
|
||||||
|
writeln!(writer_tokens, "{token:>6} - {}", token.as_str())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut writer_symbols = io::BufWriter::new(std::fs::File::create(output_symbols)?);
|
||||||
|
for (name, data) in &symbols {
|
||||||
|
writeln!(writer_symbols, "{name} -> {}", data)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("error: {}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ impl<'s, T: Iterator<Item = (usize, char)>> Lexer<'s, T> {
|
|||||||
if let Some(id) = self.symbols.get(&name) {
|
if let Some(id) = self.symbols.get(&name) {
|
||||||
Ok((start, Token::Name(id), end))
|
Ok((start, Token::Name(id), end))
|
||||||
} else {
|
} else {
|
||||||
self.symbols.add(name.clone());
|
let id = self.symbols.add(name.clone());
|
||||||
let id = self.symbols.get(&name).unwrap();
|
// let id = self.symbols.get(&name).unwrap();
|
||||||
Ok((start, Token::Name(id), end))
|
Ok((start, Token::Name(id), end))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
90
src/representation/intermediate.rs
Normal file
90
src/representation/intermediate.rs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::{typed::TypedExpr, BinOp},
|
||||||
|
symbols::{Symbol, SymbolsTable},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum IntermediateValue {
|
||||||
|
Int { value: i64 },
|
||||||
|
Float { value: f64 },
|
||||||
|
Var { name: Symbol },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for IntermediateValue {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IntermediateValue::Int { value } => write!(f, "{}", value),
|
||||||
|
IntermediateValue::Float { value } => write!(f, "{}", value),
|
||||||
|
IntermediateValue::Var { name } => write!(f, "<id,{}>", name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum IntermediateExpr {
|
||||||
|
IntToFloat {
|
||||||
|
result: Symbol,
|
||||||
|
value: IntermediateValue,
|
||||||
|
},
|
||||||
|
BinOp {
|
||||||
|
result: Symbol,
|
||||||
|
lhs: IntermediateValue,
|
||||||
|
op: BinOp,
|
||||||
|
rhs: IntermediateValue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_intermediate_expr_inner(
|
||||||
|
expr: TypedExpr,
|
||||||
|
symbols: &mut SymbolsTable,
|
||||||
|
intermediate_var_counter: &mut usize,
|
||||||
|
exprs: &mut Vec<IntermediateExpr>,
|
||||||
|
) -> IntermediateValue {
|
||||||
|
let ty = expr.ty(symbols);
|
||||||
|
|
||||||
|
match expr {
|
||||||
|
TypedExpr::Int { value, .. } => IntermediateValue::Int { value },
|
||||||
|
TypedExpr::Float { value, .. } => IntermediateValue::Float { value },
|
||||||
|
TypedExpr::Var { name, .. } => IntermediateValue::Var { name },
|
||||||
|
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
||||||
|
let lhs = to_intermediate_expr_inner(*lhs, symbols, intermediate_var_counter, exprs);
|
||||||
|
let rhs = to_intermediate_expr_inner(*rhs, symbols, intermediate_var_counter, exprs);
|
||||||
|
|
||||||
|
let result = symbols.add(format!("#T{}", intermediate_var_counter));
|
||||||
|
symbols.resolve_mut(result).unwrap().ty = Some(ty);
|
||||||
|
*intermediate_var_counter += 1;
|
||||||
|
|
||||||
|
exprs.push(IntermediateExpr::BinOp {
|
||||||
|
result,
|
||||||
|
lhs,
|
||||||
|
op,
|
||||||
|
rhs,
|
||||||
|
});
|
||||||
|
|
||||||
|
IntermediateValue::Var { name: result }
|
||||||
|
}
|
||||||
|
TypedExpr::IntToFloat { value, .. } => {
|
||||||
|
let value =
|
||||||
|
to_intermediate_expr_inner(*value, symbols, intermediate_var_counter, exprs);
|
||||||
|
|
||||||
|
let result = symbols.add(format!("#T{}", intermediate_var_counter));
|
||||||
|
symbols.resolve_mut(result).unwrap().ty = Some(ty);
|
||||||
|
*intermediate_var_counter += 1;
|
||||||
|
|
||||||
|
exprs.push(IntermediateExpr::IntToFloat { result, value });
|
||||||
|
|
||||||
|
IntermediateValue::Var { name: result }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_intermediate_expr(expr: TypedExpr, symbols: &mut SymbolsTable) -> Vec<IntermediateExpr> {
|
||||||
|
let mut exprs = Vec::new();
|
||||||
|
let mut intermediate_var_counter = 0;
|
||||||
|
|
||||||
|
to_intermediate_expr_inner(expr, symbols, &mut intermediate_var_counter, &mut exprs);
|
||||||
|
|
||||||
|
exprs
|
||||||
|
}
|
||||||
1
src/representation/mod.rs
Normal file
1
src/representation/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod intermediate;
|
||||||
@@ -19,12 +19,14 @@ pub struct SymbolData {
|
|||||||
|
|
||||||
impl Display for SymbolData {
|
impl Display for SymbolData {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.id)?;
|
let mut builder = f.debug_struct("symbol");
|
||||||
|
builder.field("id", &self.id.0);
|
||||||
|
|
||||||
if let Some(ty) = self.ty {
|
if let Some(ty) = self.ty {
|
||||||
write!(f, ":{}", ty)?;
|
builder.field("type", &ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
builder.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ impl SymbolsTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&mut self, symbol: impl Into<String>) {
|
pub fn add(&mut self, symbol: impl Into<String>) -> Symbol {
|
||||||
let symbol = symbol.into();
|
let symbol = symbol.into();
|
||||||
if let hash_map::Entry::Vacant(e) = self.symbols.entry(symbol.clone()) {
|
if let hash_map::Entry::Vacant(e) = self.symbols.entry(symbol.clone()) {
|
||||||
e.insert(SymbolData {
|
e.insert(SymbolData {
|
||||||
@@ -57,7 +59,11 @@ impl SymbolsTable {
|
|||||||
ty: None,
|
ty: None,
|
||||||
});
|
});
|
||||||
self.next_id += 1;
|
self.next_id += 1;
|
||||||
|
|
||||||
|
return Symbol(self.next_id - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.get(&symbol).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, symbol: &str) -> Option<Symbol> {
|
pub fn get(&self, symbol: &str) -> Option<Symbol> {
|
||||||
|
|||||||
154
src/util.rs
Normal file
154
src/util.rs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
use std::io;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::{typed::TypedExpr, BinOp, UntypedExpr},
|
||||||
|
representation::intermediate::IntermediateExpr,
|
||||||
|
symbols::SymbolsTable,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn print_intermediate_exprs(
|
||||||
|
exprs: &[IntermediateExpr],
|
||||||
|
writer: &mut impl io::Write,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
for expr in exprs {
|
||||||
|
match expr {
|
||||||
|
IntermediateExpr::IntToFloat { result, value } => {
|
||||||
|
writeln!(writer, "i2f <id,{}>, {}", result, value)?;
|
||||||
|
}
|
||||||
|
IntermediateExpr::BinOp {
|
||||||
|
result,
|
||||||
|
lhs,
|
||||||
|
op,
|
||||||
|
rhs,
|
||||||
|
} => {
|
||||||
|
writeln!(
|
||||||
|
writer,
|
||||||
|
"{} <id,{}>, {}, {}",
|
||||||
|
match op {
|
||||||
|
BinOp::Add => "add",
|
||||||
|
BinOp::Sub => "sub",
|
||||||
|
BinOp::Mul => "mul",
|
||||||
|
BinOp::Div => "div",
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
lhs,
|
||||||
|
rhs
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_postfix_exprs(expr: &TypedExpr, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
match expr {
|
||||||
|
TypedExpr::Int { value, .. } => write!(writer, "{} ", value)?,
|
||||||
|
TypedExpr::Float { value, .. } => write!(writer, "{} ", value)?,
|
||||||
|
TypedExpr::Var { name, .. } => write!(writer, "<id,{}> ", name)?,
|
||||||
|
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
||||||
|
print_postfix_exprs(lhs, writer)?;
|
||||||
|
print_postfix_exprs(rhs, writer)?;
|
||||||
|
write!(writer, "{} ", op)?;
|
||||||
|
}
|
||||||
|
TypedExpr::IntToFloat { value, .. } => {
|
||||||
|
print_postfix_exprs(value, writer)?;
|
||||||
|
write!(writer, "i2f ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_typed_expr(
|
||||||
|
expr: &TypedExpr,
|
||||||
|
symbols: &SymbolsTable,
|
||||||
|
writer: &mut impl io::Write,
|
||||||
|
prefix: &str,
|
||||||
|
is_last: bool,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let branch = if is_last { "└──" } else { "├──" };
|
||||||
|
|
||||||
|
write!(writer, "{}{}", prefix, branch)?;
|
||||||
|
|
||||||
|
match expr {
|
||||||
|
TypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
||||||
|
TypedExpr::Float { value, .. } => writeln!(writer, "<{}>", value),
|
||||||
|
TypedExpr::Var { name, .. } => {
|
||||||
|
let ty = symbols.resolve(*name).unwrap().ty.unwrap();
|
||||||
|
writeln!(writer, "<id,{},{}>", name, ty)
|
||||||
|
}
|
||||||
|
TypedExpr::BinOp { lhs, op, rhs, .. } => {
|
||||||
|
writeln!(writer, "<{}>", op)?;
|
||||||
|
|
||||||
|
let new_prefix = if is_last {
|
||||||
|
format!("{} ", prefix)
|
||||||
|
} else {
|
||||||
|
format!("{}│ ", prefix)
|
||||||
|
};
|
||||||
|
|
||||||
|
write_typed_expr(lhs, symbols, writer, &new_prefix, false)?;
|
||||||
|
write_typed_expr(rhs, symbols, writer, &new_prefix, true)
|
||||||
|
}
|
||||||
|
TypedExpr::IntToFloat { value, .. } => {
|
||||||
|
writeln!(writer, "i2f")?;
|
||||||
|
|
||||||
|
let new_prefix = if is_last {
|
||||||
|
format!("{} ", prefix)
|
||||||
|
} else {
|
||||||
|
format!("{}│ ", prefix)
|
||||||
|
};
|
||||||
|
|
||||||
|
write_typed_expr(value, symbols, writer, &new_prefix, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_typed_expr(
|
||||||
|
expr: &TypedExpr,
|
||||||
|
symbols: &SymbolsTable,
|
||||||
|
writer: &mut impl io::Write,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
write_typed_expr(expr, symbols, writer, "", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_untyped_expr(
|
||||||
|
expr: &UntypedExpr,
|
||||||
|
writer: &mut impl io::Write,
|
||||||
|
prefix: &str,
|
||||||
|
is_last: bool,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let branch = if is_last { "└──" } else { "├──" };
|
||||||
|
|
||||||
|
write!(writer, "{}{}", prefix, branch)?;
|
||||||
|
|
||||||
|
match expr {
|
||||||
|
UntypedExpr::Int { value, .. } => writeln!(writer, "<{}>", value),
|
||||||
|
UntypedExpr::Float { value, .. } => writeln!(writer, "<{}>", value),
|
||||||
|
UntypedExpr::Var {
|
||||||
|
name: id, typename, ..
|
||||||
|
} => {
|
||||||
|
write!(writer, "<id,{}", id)?;
|
||||||
|
if let Some(typename) = typename {
|
||||||
|
write!(writer, ",{}", typename)?;
|
||||||
|
}
|
||||||
|
writeln!(writer, ">")
|
||||||
|
}
|
||||||
|
UntypedExpr::BinOp { lhs, op, rhs, .. } => {
|
||||||
|
writeln!(writer, "<{}>", op)?;
|
||||||
|
|
||||||
|
let new_prefix = if is_last {
|
||||||
|
format!("{} ", prefix)
|
||||||
|
} else {
|
||||||
|
format!("{}│ ", prefix)
|
||||||
|
};
|
||||||
|
|
||||||
|
write_untyped_expr(lhs, writer, &new_prefix, false)?;
|
||||||
|
write_untyped_expr(rhs, writer, &new_prefix, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_untyped_expr(expr: &UntypedExpr, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
write_untyped_expr(expr, writer, "", true)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user