rprlib/
parser.rs

1use pest::iterators::{Pair, Pairs};
2use pest::{error::Error, Parser};
3use pest_derive::*;
4
5use crate::node::*;
6
7#[derive(Parser)]
8#[grammar = "./grammar.pest"]
9struct RiscVAsm {}
10
11pub trait ParseFrom<T>
12where
13    Self: std::marker::Sized,
14{
15    fn parse_from(pair: Pair<T>) -> Self;
16}
17
18impl ParseFrom<Rule> for Register {
19    fn parse_from(pair: Pair<Rule>) -> Self {
20        debug_assert_eq!(pair.as_rule(), Rule::registers);
21        Register::from(pair.as_str())
22    }
23}
24
25impl ParseFrom<Rule> for RfKeyword {
26    fn parse_from(pair: Pair<Rule>) -> Self {
27        debug_assert_eq!(pair.as_rule(), Rule::rf_keyword);
28        RfKeyword::from(pair.as_str())
29    }
30}
31
32impl ParseFrom<Rule> for Rf {
33    fn parse_from(pair: Pair<Rule>) -> Self {
34        debug_assert_eq!(pair.as_rule(), Rule::rf);
35        let mut pairs = pair.into_inner();
36        let keyword = pairs.next().unwrap();
37        let symbol = pairs.next().unwrap();
38        Self(RfKeyword::parse_from(keyword), Symbol::parse_from(symbol))
39    }
40}
41
42impl ParseFrom<Rule> for Symbol {
43    fn parse_from(pair: Pair<Rule>) -> Self {
44        debug_assert_eq!(pair.as_rule(), Rule::symbol);
45        let pair = pair.into_inner().next().unwrap();
46        match pair.as_rule() {
47            Rule::num => Self(pair.as_str().to_string(), 0),
48            Rule::sym => {
49                let mut pairs = pair.into_inner();
50                let sym = pairs.next().unwrap();
51                let offset = pairs.next();
52                if offset.is_none() {
53                    return Self(sym.as_str().to_string(), 0);
54                }
55                let offset = offset.unwrap().as_str().parse().unwrap();
56                Self(sym.as_str().to_string(), offset)
57            }
58            _ => unreachable!(),
59        }
60    }
61}
62
63impl ParseFrom<Rule> for Offset {
64    fn parse_from(pair: Pair<Rule>) -> Self {
65        debug_assert_eq!(pair.as_rule(), Rule::offset);
66        let mut pairs = pair.into_inner();
67        let pair = pairs.next().unwrap();
68        let right = pairs.next().map(Register::parse_from);
69        match pair.as_rule() {
70            Rule::symbol => Offset::Imm(Symbol::parse_from(pair), right),
71            Rule::rf => Offset::Rf(Rf::parse_from(pair), right),
72            _ => unreachable!(),
73        }
74    }
75}
76
77impl ParseFrom<Rule> for InstExpr {
78    fn parse_from(pair: Pair<Rule>) -> Self {
79        debug_assert_eq!(pair.as_rule(), Rule::inst_expr);
80        let pair = pair.into_inner().next().unwrap();
81        match pair.as_rule() {
82            Rule::registers => InstExpr::Reg(Register::parse_from(pair)),
83            Rule::offset => InstExpr::RealTimeOffset(Offset::parse_from(pair)),
84            _ => unreachable!(),
85        }
86    }
87}
88
89impl ParseFrom<Rule> for Instruction {
90    fn parse_from(pair: Pair<Rule>) -> Self {
91        debug_assert_eq!(pair.as_rule(), Rule::inst);
92        let mut pairs = pair.into_inner();
93        let inst = pairs.next().unwrap().as_str();
94        let exprs = pairs.map(InstExpr::parse_from);
95        Self(inst.to_string(), exprs.collect())
96    }
97}
98
99impl ParseFrom<Rule> for PseudoInst {
100    fn parse_from(pair: Pair<Rule>) -> Self {
101        debug_assert_eq!(pair.as_rule(), Rule::pseudo_inst);
102        let pair = pair.into_inner().next().unwrap();
103        if let Rule::generic_pseudo_inst = pair.as_rule() {
104            let mut pairs = pair.into_inner();
105            let inst = pairs.next().unwrap().as_str();
106            let exprs = pairs.map(InstExpr::parse_from);
107            PseudoInst(Instruction(inst.to_string(), exprs.collect()))
108        } else if let Rule::io_pinst = pair.as_rule() {
109            let mut pairs = pair.into_inner();
110            let inst = pairs.next().unwrap().as_str();
111            let reg = pairs.next().unwrap();
112            let sym = pairs.next().unwrap();
113            let reg = InstExpr::Reg(Register::parse_from(reg));
114            let sym = InstExpr::RealTimeOffset(Offset::Imm(Symbol::parse_from(sym), None));
115            PseudoInst(Instruction(inst.to_string(), vec![reg, sym]))
116        } else {
117            unreachable!()
118        }
119    }
120}
121
122impl ParseFrom<Rule> for Expr {
123    fn parse_from(pair: Pair<Rule>) -> Self {
124        debug_assert_eq!(pair.as_rule(), Rule::expr);
125        let pair = pair.into_inner().next().unwrap();
126        match pair.as_rule() {
127            Rule::sym => Expr::Sym(pair.as_str().to_string()),
128            Rule::str => Expr::Str(pair.as_str().to_string()),
129            Rule::num => Expr::Num(pair.as_str().to_string()),
130            _ => unreachable!(),
131        }
132    }
133}
134
135impl ParseFrom<Rule> for Pseudo {
136    fn parse_from(pair: Pair<Rule>) -> Self {
137        debug_assert_eq!(pair.as_rule(), Rule::pseudo);
138        let pair = pair.into_inner().next().unwrap();
139        let mut pairs = pair.into_inner();
140        let pseudo_op = pairs.next().unwrap().as_str();
141        let exprs = pairs.map(Expr::parse_from);
142        Self(pseudo_op.to_string(), exprs.collect())
143    }
144}
145
146impl ParseFrom<Rule> for Label {
147    fn parse_from(pair: Pair<Rule>) -> Self {
148        debug_assert_eq!(pair.as_rule(), Rule::label);
149        let pair = pair.into_inner().next().unwrap();
150        Self(Symbol::parse_from(pair))
151    }
152}
153
154impl ParseFrom<Rule> for Node {
155    fn parse_from(pair: Pair<Rule>) -> Self {
156        debug_assert_eq!(pair.as_rule(), Rule::line);
157        let pair = pair.into_inner().next().unwrap();
158        match pair.as_rule() {
159            Rule::inst => Node::Inst(Instruction::parse_from(pair)),
160            Rule::pseudo_inst => Node::PseudoInst(PseudoInst::parse_from(pair)),
161            Rule::pseudo => Node::PseudoOps(Pseudo::parse_from(pair)),
162            Rule::label => Node::Label(Label::parse_from(pair)),
163            _ => unreachable!(),
164        }
165    }
166}
167
168pub fn parse(i: &str) -> Result<Vec<Node>, Error<Rule>> {
169    let r: Result<Vec<Pairs<Rule>>, Error<Rule>> = i
170        .split('\n')
171        .map(str::trim)
172        .map(|x| RiscVAsm::parse(Rule::line, x))
173        .collect();
174    let r = r?;
175    let r = r
176        .into_iter()
177        .flatten()
178        .filter(|pair| pair.clone().into_inner().next().is_some())
179        .map(Node::parse_from)
180        .collect();
181    Ok(r)
182}