Parser
This commit is contained in:
Generated
+177
@@ -5,3 +5,180 @@ version = 4
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "archforge"
|
name = "archforge"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.183"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"ucd-trie",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_derive"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_generator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_generator"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_meta",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_meta"
|
||||||
|
version = "2.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.117"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
pest = "2.8.6"
|
||||||
|
pest_derive = "2.8.6"
|
||||||
|
|||||||
+26
-3
@@ -1,21 +1,44 @@
|
|||||||
|
#[derive(Debug)]
|
||||||
pub struct Program {
|
pub struct Program {
|
||||||
pub functions: Vec<Function>,
|
pub functions: Vec<Function>,
|
||||||
|
pub statements: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub params: Vec<String>,
|
pub params: Vec<String>,
|
||||||
pub body: Vec<Instruction>,
|
pub body: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Statement {
|
||||||
|
Instruction(Instruction),
|
||||||
|
PointerAssign { left: Reg, right: Reg },
|
||||||
|
FunctionCall(FunctionCall),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Instruction {
|
pub struct Instruction {
|
||||||
pub opcode: String,
|
pub opcode: String,
|
||||||
pub operands: Vec<Operand>,
|
pub operands: Vec<Operand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FunctionCall {
|
||||||
|
pub name: String,
|
||||||
|
pub args: Vec<Operand>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Operand {
|
pub enum Operand {
|
||||||
Global(String),
|
Reg(Reg),
|
||||||
Local(String),
|
|
||||||
Number(i64),
|
Number(i64),
|
||||||
Pointer(Box<Operand>),
|
Pointer(Box<Operand>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Reg {
|
||||||
|
Global(String),
|
||||||
|
Local(String),
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1,138 @@
|
|||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
|
||||||
|
use pest::iterators::Pair;
|
||||||
|
use pest_derive::Parser;
|
||||||
|
|
||||||
|
use ast::*;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[grammar = "parser/grammar.pest"] // relative to src
|
||||||
|
pub struct ForgeParser;
|
||||||
|
|
||||||
|
use pest::Parser;
|
||||||
|
|
||||||
|
pub fn parse_program(src: &str) -> Result<Program, pest::error::Error<Rule>> {
|
||||||
|
let mut pairs = ForgeParser::parse(Rule::program, src)?;
|
||||||
|
let program = pairs.next().unwrap();
|
||||||
|
|
||||||
|
let mut functions = Vec::new();
|
||||||
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
|
for pair in program.into_inner() {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::function_def => functions.push(parse_function(pair)),
|
||||||
|
Rule::instruction | Rule::pointer_assign | Rule::function_call => {
|
||||||
|
statements.push(parse_statement(pair))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Program {
|
||||||
|
functions,
|
||||||
|
statements,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_function(pair: Pair<Rule>) -> Function {
|
||||||
|
let mut inner = pair.into_inner();
|
||||||
|
|
||||||
|
let name = inner.next().unwrap().as_str().to_string();
|
||||||
|
|
||||||
|
let mut params = Vec::new();
|
||||||
|
let mut body = Vec::new();
|
||||||
|
|
||||||
|
for p in inner {
|
||||||
|
match p.as_rule() {
|
||||||
|
Rule::param_list => {
|
||||||
|
for param in p.into_inner() {
|
||||||
|
params.push(param.as_str().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rule::block => {
|
||||||
|
for stmt in p.into_inner() {
|
||||||
|
body.push(parse_statement(stmt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function { name, params, body }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_statement(pair: Pair<Rule>) -> Statement {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::instruction => Statement::Instruction(parse_instruction(pair)),
|
||||||
|
|
||||||
|
Rule::pointer_assign => {
|
||||||
|
let mut inner = pair.into_inner();
|
||||||
|
|
||||||
|
let left = parse_reg(inner.next().unwrap());
|
||||||
|
let right = parse_reg(inner.next().unwrap());
|
||||||
|
|
||||||
|
Statement::PointerAssign { left, right }
|
||||||
|
}
|
||||||
|
|
||||||
|
Rule::function_call => Statement::FunctionCall(parse_function_call(pair)),
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_instruction(pair: Pair<Rule>) -> Instruction {
|
||||||
|
let mut inner = pair.into_inner();
|
||||||
|
|
||||||
|
let opcode = inner.next().unwrap().as_str().to_string();
|
||||||
|
|
||||||
|
let mut operands = Vec::new();
|
||||||
|
|
||||||
|
if let Some(list) = inner.next() {
|
||||||
|
for op in list.into_inner() {
|
||||||
|
operands.push(parse_operand(op));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction { opcode, operands }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_function_call(pair: Pair<Rule>) -> FunctionCall {
|
||||||
|
let mut inner = pair.into_inner();
|
||||||
|
|
||||||
|
let name = inner.next().unwrap().as_str().to_string();
|
||||||
|
|
||||||
|
let mut args = Vec::new();
|
||||||
|
|
||||||
|
if let Some(list) = inner.next() {
|
||||||
|
for arg in list.into_inner() {
|
||||||
|
args.push(parse_operand(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionCall { name, args }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_operand(pair: Pair<Rule>) -> Operand {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::number => Operand::Number(pair.as_str().parse().unwrap()),
|
||||||
|
|
||||||
|
Rule::global_reg | Rule::local_reg => Operand::Reg(parse_reg(pair)),
|
||||||
|
|
||||||
|
Rule::pointer_expr => {
|
||||||
|
let inner = pair.into_inner().next().unwrap();
|
||||||
|
Operand::Pointer(Box::new(parse_operand(inner)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_reg(pair: Pair<Rule>) -> Reg {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::global_reg => Reg::Global(pair.as_str()[1..].to_string()),
|
||||||
|
|
||||||
|
Rule::local_reg => Reg::Local(pair.as_str()[1..].to_string()),
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user