Add huiac binary that just prints out the AST.

This commit is contained in:
James Harton 2018-09-03 18:53:11 +12:00
parent 2072134c80
commit e1a0472ed8
9 changed files with 157 additions and 16 deletions

View file

@ -1,5 +1,6 @@
[workspace] [workspace]
members = [ members = [
"compiler", "compiler",
"huiac",
"parser" "parser"
] ]

8
huiac/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "huiac"
version = "0.1.0"
authors = ["James Harton <james@automat.nz>"]
[dependencies]
huia-parser = { path = "../parser" }
clap = "2.32.0"

27
huiac/src/main.rs Normal file
View file

@ -0,0 +1,27 @@
extern crate clap;
extern crate huia_parser;
use clap::{App, Arg};
use std::fs;
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
fn main() {
let matches = App::new("huiac")
.version(VERSION)
.author("James Harton <james@automat.nz>")
.about("The compiler for the Huia programming language.")
.arg(
Arg::with_name("INPUT")
.help("The source file to compile")
.required(true)
.index(1),
)
.get_matches();
let source_path = matches.value_of("INPUT").unwrap();
let source_file = fs::read_to_string(source_path).expect("Unable to read input file");
let result = huia_parser::parse_file(&source_file);
println!("{:?}", result);
}

24
parser/src/ast/file.rs Normal file
View file

@ -0,0 +1,24 @@
use ast::{consume, node::Node};
use grammar::Rule;
use pest::iterators::Pair;
use pest::Span;
#[derive(Debug)]
pub struct File<'a> {
span: Span<'a>,
children: Vec<Node<'a>>,
}
impl<'a> From<Pair<'a, Rule>> for File<'a> {
fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::file);
let span = pair.clone().into_span();
let children = pair.into_inner().map(|p| consume(p)).collect();
File {
span: span,
children: children,
}
}
}

View file

@ -5,6 +5,7 @@ mod boolean;
mod braced; mod braced;
mod call; mod call;
mod constructor; mod constructor;
mod file;
mod float; mod float;
mod infix; mod infix;
mod integer; mod integer;
@ -25,6 +26,7 @@ pub use self::{
braced::Braced, braced::Braced,
call::{Call, Message, Receiver}, call::{Call, Message, Receiver},
constructor::Constructor, constructor::Constructor,
file::File,
float::Float, float::Float,
infix::Infix, infix::Infix,
integer::Integer, integer::Integer,
@ -34,25 +36,34 @@ pub use self::{
unary::Unary, unary::Unary,
variable::Variable, variable::Variable,
}; };
use error::ParseError;
use grammar::Rule; use grammar::Rule;
use pest::iterators::Pair; use pest::iterators::Pair;
pub fn consume<'a>(pair: Pair<'a, Rule>) -> Node<'a> { pub fn consume<'a>(pair: Pair<'a, Rule>) -> Node<'a> {
match pair.as_rule() { match build(pair) {
Rule::array => Node::from(Array::from(pair)), Ok(node) => node,
Rule::atom => Node::from(Atom::from(pair)), Err(e) => panic!("{}", e),
Rule::boolean_true => Node::from(True::from(pair)), }
Rule::boolean_false => Node::from(False::from(pair)), }
Rule::braced => Node::from(Braced::from(pair)),
Rule::call => Node::from(Call::from(pair)), pub fn build<'a>(pair: Pair<'a, Rule>) -> Result<Node<'a>, ParseError<'a>> {
Rule::constructor => Node::from(Constructor::from(pair)), match pair.as_rule() {
Rule::expression_infix => precedence::climb(pair), Rule::array => Ok(Node::from(Array::from(pair))),
Rule::float => Node::from(Float::from(pair)), Rule::atom => Ok(Node::from(Atom::from(pair))),
Rule::integer => Node::from(Integer::from(pair)), Rule::boolean_true => Ok(Node::from(True::from(pair))),
Rule::property => Node::from(Property::from(pair)), Rule::boolean_false => Ok(Node::from(False::from(pair))),
Rule::string => Node::from(StringLiteral::from(pair)), Rule::braced => Ok(Node::from(Braced::from(pair))),
Rule::unary => Node::from(Unary::from(pair)), Rule::call => Ok(Node::from(Call::from(pair))),
Rule::variable => Node::from(Variable::from(pair)), Rule::constructor => Ok(Node::from(Constructor::from(pair))),
_ => panic!("Node {:?} is not a consumable", pair), Rule::expression_infix => Ok(precedence::climb(pair)),
Rule::file => Ok(Node::from(File::from(pair))),
Rule::float => Ok(Node::from(Float::from(pair))),
Rule::integer => Ok(Node::from(Integer::from(pair))),
Rule::property => Ok(Node::from(Property::from(pair))),
Rule::string => Ok(Node::from(StringLiteral::from(pair))),
Rule::unary => Ok(Node::from(Unary::from(pair))),
Rule::variable => Ok(Node::from(Variable::from(pair))),
_ => Err(ParseError::from(pair)),
} }
} }

View file

@ -5,6 +5,7 @@ use ast::{
braced::Braced, braced::Braced,
call::Call, call::Call,
constructor::Constructor, constructor::Constructor,
file::File,
float::Float, float::Float,
infix::Infix, infix::Infix,
integer::Integer, integer::Integer,
@ -22,6 +23,7 @@ pub enum Node<'a> {
Call(Call<'a>), Call(Call<'a>),
Constructor(Constructor<'a>), Constructor(Constructor<'a>),
False(False<'a>), False(False<'a>),
File(File<'a>),
Float(Float<'a>), Float(Float<'a>),
Infix(Infix<'a>), Infix(Infix<'a>),
Integer(Integer<'a>), Integer(Integer<'a>),
@ -68,6 +70,12 @@ impl<'a> From<False<'a>> for Node<'a> {
} }
} }
impl<'a> From<File<'a>> for Node<'a> {
fn from(inner: File<'a>) -> Self {
Node::File(inner)
}
}
impl<'a> From<Float<'a>> for Node<'a> { impl<'a> From<Float<'a>> for Node<'a> {
fn from(inner: Float<'a>) -> Self { fn from(inner: Float<'a>) -> Self {
Node::Float(inner) Node::Float(inner)

40
parser/src/error.rs Normal file
View file

@ -0,0 +1,40 @@
use grammar::Rule;
use pest;
use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum ParseError<'a> {
PestError(pest::Error<'a, Rule>),
AstGeneration(pest::iterators::Pair<'a, Rule>),
}
impl<'a> From<pest::Error<'a, Rule>> for ParseError<'a> {
fn from(pest: pest::Error<'a, Rule>) -> Self {
ParseError::PestError(pest)
}
}
impl<'a> From<pest::iterators::Pair<'a, Rule>> for ParseError<'a> {
fn from(pest: pest::iterators::Pair<'a, Rule>) -> Self {
ParseError::AstGeneration(pest)
}
}
impl<'a> fmt::Display for ParseError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ParseError::PestError(ref e) => write!(f, "{}", e),
ParseError::AstGeneration(_) => write!(f, "Internal error during AST generation"),
}
}
}
impl<'a> Error for ParseError<'a> {
fn cause(&self) -> Option<&Error> {
match self {
ParseError::PestError(ref e) => Some(e),
_ => None,
}
}
}

View file

@ -10,4 +10,10 @@ extern crate lazy_static;
extern crate regex; extern crate regex;
mod ast; mod ast;
mod error;
mod grammar; mod grammar;
mod parse;
pub use ast::*;
pub use error::ParseError;
pub use parse::parse_file;

16
parser/src/parse.rs Normal file
View file

@ -0,0 +1,16 @@
use ast::{build, Node};
use error::ParseError;
use grammar::{Grammar, Rule};
use pest::{iterators::Pair, Parser};
pub fn parse_file<'a>(source: &'a str) -> Result<Node<'a>, ParseError<'a>> {
run_parser(source, Rule::file).and_then(build)
}
fn run_parser<'a>(source: &'a str, rule: Rule) -> Result<Pair<'a, Rule>, ParseError<'a>> {
let result = Grammar::parse(rule, source);
match result {
Ok(mut pairs) => Ok(pairs.next().unwrap()),
Err(pest_error) => Err(ParseError::from(pest_error)),
}
}