Parser
This commit is contained in:
Generated
+177
@@ -5,3 +5,180 @@ version = 4
|
||||
[[package]]
|
||||
name = "archforge"
|
||||
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"
|
||||
|
||||
[dependencies]
|
||||
pest = "2.8.6"
|
||||
pest_derive = "2.8.6"
|
||||
|
||||
+27
-4
@@ -1,21 +1,44 @@
|
||||
#[derive(Debug)]
|
||||
pub struct Program {
|
||||
pub functions: Vec<Function>,
|
||||
pub statements: Vec<Statement>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Function {
|
||||
pub name: 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 opcode: String,
|
||||
pub operands: Vec<Operand>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionCall {
|
||||
pub name: String,
|
||||
pub args: Vec<Operand>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Operand {
|
||||
Global(String),
|
||||
Local(String),
|
||||
Reg(Reg),
|
||||
Number(i64),
|
||||
Pointer(Box<Operand>),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Reg {
|
||||
Global(String),
|
||||
Local(String),
|
||||
}
|
||||
|
||||
@@ -1 +1,138 @@
|
||||
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