Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions src/bind/binder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::collections::HashMap;
use std::io::Error;
use std::rc::Rc;
use std::vec::Vec;

Expand All @@ -11,24 +10,30 @@ use crate::bind::gate::GateDec;
use crate::bind::par::ParDec;
use crate::bind::reg::RegDec;

use crate::utils::error::{CompoundError, ErrorTy, LocatedError};

pub struct Binder {
gates: HashMap<String, Rc<GateDec>>,
regs: HashMap<String, Rc<RegDec>>,
error: Option<Error>,
error: CompoundError,
}

impl MutVisitor for Binder {
fn visit_dec(&mut self, e: &mut node::Dec) {
match e {
node::Dec::RegDec {
loc: _,
loc,
name,
ty,
size,
dec,
} => {
if self.regs.contains_key(name) {
self.error = Some(Error::other(format!("Redefined register '{}'", name)));
self.error.add(LocatedError::new(
ErrorTy::Bind,
format!("redefined register '{}'", name),
loc.clone(),
));
return;
}
let it = Rc::new(RegDec::new(name.clone(), ty.clone(), *size));
Expand All @@ -40,18 +45,26 @@ impl MutVisitor for Binder {

fn visit_reg(&mut self, e: &mut node::Reg) {
match e {
node::Reg::SimpleReg { loc: _, name, dec } => match self.regs.get(name) {
node::Reg::SimpleReg { loc, name, dec } => match self.regs.get(name) {
Some(it) => drop(dec.replace(Rc::clone(it))),
_ => self.error = Some(Error::other(format!("Undeclared register '{}'", name))),
_ => self.error.add(LocatedError::new(
ErrorTy::Bind,
format!("undeclared register '{}'", name),
loc.clone(),
)),
},
node::Reg::SubscriptReg {
loc: _,
loc,
name,
index: _,
dec,
} => match self.regs.get(name) {
Some(it) => drop(dec.replace(Rc::clone(it))),
_ => self.error = Some(Error::other(format!("Undeclared register '{}'", name))),
_ => self.error.add(LocatedError::new(
ErrorTy::Bind,
format!("undeclared register '{}'", name),
loc.clone(),
)),
},
}
}
Expand All @@ -60,15 +73,19 @@ impl MutVisitor for Binder {
match e {
node::Stmt::DecStmt(dec) => self.visit_dec(dec),
node::Stmt::GateStmt {
loc: _,
loc,
gate,
pars: _,
args,
dec,
} => {
match self.gates.get(gate) {
Some(it) => drop(dec.replace(Rc::clone(it))),
_ => self.error = Some(Error::other(format!("Undeclared gate '{}'", gate))),
_ => self.error.add(LocatedError::new(
ErrorTy::Bind,
format!("undeclared gate '{}'", gate),
loc.clone(),
)),
};
args.iter_mut().for_each(|arg| self.visit_reg(arg));
}
Expand Down Expand Up @@ -110,15 +127,19 @@ impl Binder {
Binder {
gates: gates,
regs: HashMap::new(),
error: None,
error: CompoundError::new(),
}
}

pub fn bind(&mut self, program: &mut Vec<node::Stmt>) {
program.iter_mut().for_each(|x| self.visit_stmt(x));
}

pub fn get_error(&self) -> &Option<Error> {
pub fn get_error(&self) -> &CompoundError {
&self.error
}

pub fn get_error_mut(&mut self) -> &mut CompoundError {
&mut self.error
}
}
21 changes: 13 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ pub mod bind;
pub mod parse;
pub mod utils;

use std::process;

use crate::ast::pretty_printer::PrettyPrinter;

use crate::bind::binder::Binder;

use crate::parse::lexer::Lexer;
use crate::parse::parser::Parser;

use crate::utils::error::{CompoundError, Error};

fn main() {
let lexer = Lexer::new(String::from("<stdin>"), std::io::stdin());
let mut parser = Parser::new(lexer);
Expand All @@ -21,12 +25,13 @@ fn main() {
PrettyPrinter.pretty_print(program);
}

parser
.get_error()
.iter()
.for_each(|it| println!("{}", it.to_string()));
binder
.get_error()
.iter()
.for_each(|it| println!("{}", it.to_string()));
let mut error = CompoundError::new();
error.consume(parser.get_error_mut());
error.consume(binder.get_error_mut());

if !error.empty() {
eprintln!("{}", error.get_desc());
}

process::exit(error.get_exit_code());
}
69 changes: 48 additions & 21 deletions src/parse/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use regex::Regex;

use std::io::Error;
use std::io::Read;

use crate::utils::chars;
use crate::utils::error::{CompoundError, ErrorTy, LocatedError, SimpleError};
use crate::utils::location::Location;

use crate::parse::token::{Token, TokenTy};
Expand All @@ -13,7 +13,7 @@ pub struct Lexer<Input: Read> {
current: Option<char>,
location: Location,
token: Option<Token>,
error: Option<Error>,
error: CompoundError,
}

impl<Input: Read> Lexer<Input> {
Expand All @@ -23,7 +23,7 @@ impl<Input: Read> Lexer<Input> {
current: None,
location: Location::new(file, 0, 0, 0, 0),
token: None,
error: None,
error: CompoundError::new(),
}
}

Expand Down Expand Up @@ -51,11 +51,14 @@ impl<Input: Read> Lexer<Input> {
self.current
}
Ok(2..) => {
self.error = Some(Error::other("Read an unexpected number of characters"));
self.error.add(SimpleError::new(
ErrorTy::Internal,
"read an unexpected number of characters",
));
None
}
Err(err) => {
self.error = Some(err);
self.error.add(SimpleError::new(ErrorTy::Internal, err));
None
}
}
Expand All @@ -82,7 +85,8 @@ impl<Input: Read> Lexer<Input> {
}
}
None => {
self.error = Some(Error::other("Unterminated comment"));
self.error
.add(SimpleError::new(ErrorTy::Lex, "unterminated comment"));
return;
}
_ => self.reset_char(),
Expand All @@ -100,7 +104,7 @@ impl<Input: Read> Lexer<Input> {
id += &c.to_string();
self.reset_char();
}
if self.error.is_some() {
if !self.error.empty() {
return;
}
let ty = match id.as_str() {
Expand Down Expand Up @@ -130,15 +134,18 @@ impl<Input: Read> Lexer<Input> {
id += &c.to_string();
self.reset_char();
}
if self.error.is_some() {
if !self.error.empty() {
return;
}
if let Some(ty) = match id.as_str() {
"OPENQASM" => Some(TokenTy::OpenQASM),
"U" => Some(TokenTy::UGate),
"CX" => Some(TokenTy::CXGate),
_ => {
self.error = Some(Error::other(format!("Invalid identifier '{}'", id)));
self.error.add(SimpleError::new(
ErrorTy::Lex,
format!("invalid identifier '{}'", id),
));
None
}
} {
Expand All @@ -156,7 +163,7 @@ impl<Input: Read> Lexer<Input> {
number += &c.to_string();
self.reset_char();
}
if self.error.is_some() {
if !self.error.empty() {
return;
}
if let Some(c) = self.next_char()
Expand All @@ -170,7 +177,7 @@ impl<Input: Read> Lexer<Input> {
number += &c.to_string();
self.reset_char();
}
if self.error.is_some() {
if !self.error.empty() {
return;
}
while let Some(c) = self.next_char()
Expand All @@ -179,7 +186,7 @@ impl<Input: Read> Lexer<Input> {
number += &c.to_string();
self.reset_char();
}
if self.error.is_some() {
if !self.error.empty() {
return;
}
}
Expand All @@ -189,20 +196,23 @@ impl<Input: Read> Lexer<Input> {
match number.parse::<u32>() {
Ok(n) => Some(TokenTy::Integer(n)),
Err(err) => {
self.error = Some(Error::other(err.to_string()));
self.error.add(SimpleError::new(ErrorTy::Lex, err));
None
}
}
} else if real_re.is_match(number.as_str()) {
match number.parse::<f32>() {
Ok(n) => Some(TokenTy::Real(n)),
Err(err) => {
self.error = Some(Error::other(err.to_string()));
self.error.add(SimpleError::new(ErrorTy::Lex, err));
None
}
}
} else {
self.error = Some(Error::other(format!("Invalid number '{}'", number)));
self.error.add(SimpleError::new(
ErrorTy::Lex,
format!("invalid number '{}'", number),
));
None
} {
self.next_char();
Expand Down Expand Up @@ -242,7 +252,10 @@ impl<Input: Read> Lexer<Input> {
},
'^' => Some(TokenTy::Pow),
_ => {
self.error = Some(Error::other(format!("Invalid operator '{}'", c)));
self.error.add(SimpleError::new(
ErrorTy::Internal,
format!("invalid operator '{}'", c),
));
None
}
} {
Expand All @@ -261,7 +274,10 @@ impl<Input: Read> Lexer<Input> {
',' => Some(TokenTy::Comma),
';' => Some(TokenTy::Semi),
_ => {
self.error = Some(Error::other(format!("Invalid punctuation '{}'", c)));
self.error.add(SimpleError::new(
ErrorTy::Internal,
format!("invalid punctuation '{}'", c),
));
None
}
} {
Expand All @@ -282,7 +298,10 @@ impl<Input: Read> Lexer<Input> {
'(' => Some(TokenTy::LPar),
')' => Some(TokenTy::RPar),
_ => {
self.error = Some(Error::other(format!("Invalid bracket '{}'", c)));
self.error.add(SimpleError::new(
ErrorTy::Internal,
format!("invalid bracket '{}'", c),
));
None
}
} {
Expand All @@ -299,7 +318,7 @@ impl<Input: Read> Lexer<Input> {
{
self.reset_char();
}
if self.error.is_some() {
if !self.error.empty() {
return;
}
if let Some(c) = self.next_char() {
Expand All @@ -316,7 +335,11 @@ impl<Input: Read> Lexer<Input> {
} else if chars::is_bracket(c) {
self.process_bracket();
} else {
self.error = Some(Error::other(format!("Invalid character '{}'", c)));
self.error.add(LocatedError::new(
ErrorTy::Lex,
format!("invalid character '{}'", c),
self.location.clone(),
));
}
} else {
self.token = Some(Token::new(TokenTy::Eof, self.location.clone()));
Expand All @@ -343,7 +366,11 @@ impl<Input: Read> Lexer<Input> {
println!("eof@{}", self.location.to_string());
}

pub fn get_error(&self) -> &Option<Error> {
pub fn get_error(&self) -> &CompoundError {
&self.error
}

pub fn get_error_mut(&mut self) -> &mut CompoundError {
&mut self.error
}
}
Loading