Skip to content

Commit

Permalink
Parsing User Error for InvalidToken (#21)
Browse files Browse the repository at this point in the history
* Lexer captures InvalidToken and parser returns it as a 
* Positions can now be implemented by @l and @r tokens at Lalrpop #5 .
* The F/lex FFI part of lexer is now more documented.
* The token position is now checked and implemented from the Lexer grammar.
  • Loading branch information
adjivas authored and Ulysse Beaugnon committed May 23, 2018
1 parent eb020ef commit a40d816
Show file tree
Hide file tree
Showing 20 changed files with 1,291 additions and 718 deletions.
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn main() {

add_dependency(exh_file);
let exh_out = Path::new(&out_dir).join("choices.rs");
telamon_gen::process_file(&Path::new(exh_file), &exh_out, cfg!(feature="format_exh"));
telamon_gen::process_file(&Path::new(exh_file), &exh_out, cfg!(feature="format_exh")).unwrap();
if cfg!(feature="cuda") { compile_link_cuda(); }

if cfg!(feature = "mppa") {
Expand Down
35 changes: 0 additions & 35 deletions examples/common.rs

This file was deleted.

31 changes: 30 additions & 1 deletion examples/sgemm_low.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,36 @@ extern crate itertools;
extern crate log;
extern crate rayon;

mod common;
mod common {
/// Generates the code for the best candidate in the search space.
pub fn gen_best<'a>(search_space: Vec<SearchSpace>,
context: &'a Context,
out: &str) {
let conf = explorer::Config::read();
let begin_time = std::time::Instant::now();
let best_opt = explorer::find_best(&conf, context, search_space);
let duration = std::time::Instant::now() - begin_time;
warn!("Search completed in {}s", duration.as_secs());
match best_opt {
Some(best) => {
let mut file = std::fs::File::create(out).unwrap();
context.device().gen_code(&best, &mut file)
}
None => println!("Did not find any well suited candidate before timeout"),
}
}

/// Generate a name for the output file.
pub fn file_name(name: &str,
_: ir::Type,
sizes: &[i32],
instantiated: bool) -> String {
const PATH: &str = "examples/out/";
std::fs::create_dir_all(PATH).unwrap();
let sizes = sizes.iter().format_with("", |i, f| f(&format_args!("_{}", i)));
format!("{}{}_{}{}.c", PATH, name, instantiated, sizes)
}
}

#[allow(unused_imports)]
use telamon::{explorer, helper, ir};
Expand Down
7 changes: 7 additions & 0 deletions telamon-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ lex = []
doc = false
name = "cli_gen"

[[bench]]
name = "lexer"
harness = false

[dev-dependencies]
criterion = "0.2"

[build-dependencies]
lalrpop = "0.14"
cc = "1.0.12"
Expand Down
29 changes: 29 additions & 0 deletions telamon-gen/benches/lexer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#[macro_use]
extern crate criterion;
extern crate telamon_gen;

use criterion::Criterion;

use telamon_gen::lexer;

use std::fs;
use std::ffi::OsStr;

fn criterion_benchmark(c: &mut Criterion) {
let entries = fs::read_dir("cc_tests/src/").unwrap();
for entry in entries {
if let Ok(entry) = entry {
if entry.path().extension().eq(&Some(OsStr::new("exh"))) {
let path = entry.path();
let mut input = fs::File::open(&path).unwrap();
let mut name = String::from("lexer ");
name.push_str(path.file_stem().unwrap().to_str().unwrap());

c.bench_function(&name, move |b| b.iter(|| lexer::Lexer::new(&mut input)));
}
}
}
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
10 changes: 7 additions & 3 deletions telamon-gen/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@ extern crate lalrpop;
fn add_dependency(dep: &str) { println!("cargo:rerun-if-changed={}", dep); }

fn main() {
// Compile the lexer.(`LEX="flex" cargo build --features "lex"`)
// Regenerate the lexer.(`LEX="flex" cargo build --features "lex"`)
#[cfg(feature = "lex")]
{
use std::{env,process::Command};

// Generate the lexer .
add_dependency("src/poc.l");
let bin = env::var("LEX").unwrap_or(String::from("flex"));

Command::new(bin)
.arg("-oexh.c")
.arg("-osrc/exh.c")
.arg("src/exh.l")
.status()
.expect("failed to execute Flex's process");
}

// Compile the lexer .
cc::Build::new()
.file("exh.c")
.file("src/exh.c")
.include("src")
.flag("-Wno-unused-parameter")
.flag("-Wno-unused-variable")
.flag_if_supported("-Wno-unused-function")
Expand Down
2 changes: 1 addition & 1 deletion telamon-gen/cc_tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ fn main() {
let file_name = src_path.file_name().unwrap();
println!("cargo:rerun-if-changed={}", file_name.to_str().unwrap());
let dst_path = Path::new(&out_dir).join(&file_name).with_extension("rs");
telamon_gen::process_file(&src_path, &dst_path, !cfg!(feature="noformat_exh"));
telamon_gen::process_file(&src_path, &dst_path, !cfg!(feature="noformat_exh")).unwrap();
}
}
13 changes: 12 additions & 1 deletion telamon-gen/src/bin/cli_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@
extern crate telamon_gen;
extern crate env_logger;

use std::process;
use std::path::Path;

fn main() {
env_logger::init();
telamon_gen::process(&mut std::io::stdin(), &mut std::io::stdout(), true);
if let Err(process_error) = telamon_gen::process(
&mut std::io::stdin(),
&mut std::io::stdout(),
true,
&Path::new("exh")
) {
eprintln!("error: {}", process_error);
process::exit(-1);
}
}
103 changes: 103 additions & 0 deletions telamon-gen/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use super::lexer;
use super::lalrpop_util::*;

use std::{path, fmt};
use std::error::Error;

#[derive(Debug)]
pub enum Cause {
/// Lalrpop
Parse(ParseError<lexer::Position,
lexer::Token,
lexer::LexicalError>),
/// Will be remplaced by field for Ast [...]
Other,
}

#[derive(Debug)]
pub struct ProcessError<'a> {
/// Display of filename.
pub path: path::Display<'a>,
/// Position of lexeme.
pub span: Option<lexer::Span>,
cause: Cause,
}

impl <'a>From<(path::Display<'a>,
ParseError<lexer::Position,
lexer::Token,
lexer::LexicalError>
)> for ProcessError<'a> {
fn from((path, parse): (path::Display<'a>,
ParseError<lexer::Position,
lexer::Token,
lexer::LexicalError>
)) -> Self {
match parse {
ParseError::InvalidToken { location }
=> ProcessError {
path: path,
span: Some(lexer::Span { leg: location, ..Default::default() }),
cause: Cause::Parse(parse),
},
ParseError::UnrecognizedToken { token: None, .. }
=> ProcessError {
path: path,
span: None,
cause: Cause::Parse(parse),
},
ParseError::UnrecognizedToken { token: Some((l, .., e)), .. } |
ParseError::ExtraToken { token: (l, .., e) } |
ParseError::User { error: lexer::LexicalError::UnexpectedToken(l, .., e) } |
ParseError::User { error: lexer::LexicalError::InvalidToken(l, .., e) }
=> ProcessError {
path: path,
span: Some(lexer::Span { leg: l, end: Some(e) }),
cause: Cause::Parse(parse),
},
}
}
}

impl <'a> fmt::Display for ProcessError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ProcessError { path, span, cause: Cause::Parse(
ParseError::UnrecognizedToken {
token: Some((_, ref token, _)), ..
}), ..} |
ProcessError { path, span, cause: Cause::Parse(ParseError::ExtraToken {
token: (_, ref token, _)
}), ..} |
ProcessError { path, span, cause: Cause::Parse(
ParseError::User {
error: lexer::LexicalError::UnexpectedToken(_, ref token, _)
}), ..} |
ProcessError { path, span, cause: Cause::Parse(
ParseError::User {
error: lexer::LexicalError::InvalidToken(_, ref token, _)
}), ..} => {
if let Some(span) = span {
write!(f, "{}, {} -> {}", token, span, path)
} else {
write!(f, "{} -> {}", token, path)
}
},
_ => Ok(()),
}
}
}

impl <'a>Error for ProcessError<'a> {
fn description(&self) -> &str {
"Process error"
}

fn cause(&self) -> Option<&Error> {
if let Cause::Parse(ref parse) = self.cause {
parse.cause()
} else {
None
}
}
}
Loading

0 comments on commit a40d816

Please sign in to comment.