Parser
This commit is contained in:
+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