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}