-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e858f84
commit 5672c6e
Showing
10 changed files
with
253 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,49 @@ | ||
use crate::parser::Rule; | ||
use pest::iterators::Pair; | ||
use prost::{DecodeError, EncodeError}; | ||
use std::error::Error; | ||
use std::fmt; | ||
|
||
#[derive(Debug)] | ||
pub struct ParseError { | ||
pub message: String, | ||
pub line: usize, | ||
pub column: usize, | ||
} | ||
|
||
impl ParseError { | ||
pub fn new(message: String) -> ParseError { | ||
ParseError { | ||
message, | ||
line: 0, | ||
column: 0, | ||
} | ||
ParseError { message } | ||
} | ||
|
||
pub fn from_pair(message: String, pair: Pair<Rule>) -> ParseError { | ||
let (line, column) = pair.as_span().start_pos().line_col(); | ||
ParseError { | ||
message, | ||
line, | ||
column, | ||
message: format!("{} (line: {}, column: {})", message, line, column), | ||
} | ||
} | ||
} | ||
|
||
impl fmt::Display for ParseError { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!( | ||
f, | ||
"{} (line: {}, column: {})", | ||
self.message, self.line, self.column | ||
) | ||
write!(f, "{}", self.message) | ||
} | ||
} | ||
|
||
impl Error for ParseError {} | ||
|
||
impl From<std::io::Error> for ParseError { | ||
fn from(error: std::io::Error) -> Self { | ||
ParseError::new(format!("{}", error)) | ||
} | ||
} | ||
|
||
impl From<EncodeError> for ParseError { | ||
fn from(error: EncodeError) -> Self { | ||
ParseError::new(format!("{}", error)) | ||
} | ||
} | ||
|
||
impl From<DecodeError> for ParseError { | ||
fn from(error: DecodeError) -> Self { | ||
ParseError::new(format!("{}", error)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,102 @@ | ||
use super::ast::Program as AstProgram; | ||
use super::ir::Program as IrProgram; | ||
use super::ast::{Command as AstCommand, Program as AstProgram}; | ||
use super::errors::ParseError; | ||
use pest_derive::Parser; | ||
use std::fs; | ||
use std::path::Path; | ||
|
||
#[derive(Parser)] | ||
#[grammar = "pest/klang.pest"] | ||
pub struct PestParser; | ||
|
||
pub struct Node { | ||
pub text: String, | ||
pub children: Vec<Node>, | ||
} | ||
|
||
impl Node { | ||
pub fn to_ast(&self) -> AstCommand { | ||
AstCommand { | ||
text: self.text.clone(), | ||
children: self.children.iter().map(|child| child.to_ast()).collect(), | ||
} | ||
} | ||
|
||
pub fn from_ast(ast: &AstCommand) -> Self { | ||
Node { | ||
text: ast.text.clone(), | ||
children: ast | ||
.children | ||
.iter() | ||
.map(|child| Node::from_ast(child)) | ||
.collect(), | ||
} | ||
} | ||
|
||
pub fn to_string(&self, indent: usize) -> String { | ||
let mut result = format!("{:indent$}{}", " ", self.text, indent = indent); | ||
if !self.children.is_empty() { | ||
result.push_str(" {\n"); | ||
for child in &self.children { | ||
result.push_str(&child.to_string(indent + 2)); | ||
} | ||
result.push_str(&format!("{:indent$}}}", " ", indent = indent)); | ||
} | ||
result.push('\n'); | ||
result | ||
} | ||
} | ||
|
||
pub struct KlangProgram { | ||
pub ast_program: AstProgram, | ||
pub ir_program: IrProgram, | ||
pub program: Vec<Node>, | ||
} | ||
|
||
impl KlangProgram { | ||
pub fn to_ast(&self) -> AstProgram { | ||
AstProgram { | ||
commands: self.program.iter().map(|node| node.to_ast()).collect(), | ||
} | ||
} | ||
|
||
pub fn from_ast(ast: &AstProgram) -> Self { | ||
KlangProgram { | ||
program: ast | ||
.commands | ||
.iter() | ||
.map(|command| Node::from_ast(command)) | ||
.collect(), | ||
} | ||
} | ||
|
||
pub fn save_binary(&self, path: &Path) -> Result<(), ParseError> { | ||
let mut buf = Vec::new(); | ||
prost::Message::encode(&self.to_ast(), &mut buf)?; | ||
fs::write(path, &buf)?; | ||
Ok(()) | ||
} | ||
|
||
pub fn load_binary(path: &Path) -> Result<Self, ParseError> { | ||
let buf = fs::read(path)?; | ||
let program = prost::Message::decode(&*buf)?; | ||
Ok(KlangProgram::from_ast(&program)) | ||
} | ||
|
||
pub fn save_text(&self, path: &Path) -> Result<(), ParseError> { | ||
let output = self.to_text(); | ||
fs::write(path, &output)?; | ||
Ok(()) | ||
} | ||
|
||
pub fn to_text(&self) -> String { | ||
self.program | ||
.iter() | ||
.map(|node| node.to_string(0)) | ||
.collect::<Vec<String>>() | ||
.join("\n") | ||
} | ||
} | ||
|
||
impl std::fmt::Display for KlangProgram { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.to_text()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
"""Defines the PyKlang CLI.""" | ||
|
||
import argparse | ||
from pathlib import Path | ||
|
||
from pyklang.bindings import parse_file | ||
|
||
|
||
def main() -> None: | ||
parser = argparse.ArgumentParser(description="Kompile a Klang program.") | ||
parser.add_argument("input", help="The input file to compile.") | ||
parser.add_argument("-o", "--output", help="The output file to compile.") | ||
parser.add_argument("-t", "--text", action="store_true", help="Output the text representation of the program.") | ||
args = parser.parse_args() | ||
|
||
program = parse_file(args.input) | ||
|
||
if args.output is None: | ||
print(program) | ||
else: | ||
Path(args.output).parent.mkdir(parents=True, exist_ok=True) | ||
if args.text: | ||
program.save_text(args.output) | ||
else: | ||
program.save_binary(args.output) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.