1extern crate lalrpop_util;
2extern crate regex;
3
4pub mod ast;
5pub mod verilog_parser;
6
7pub use lalrpop_util::ParseError as ParseError;
8use regex::Regex;
9use std::fmt::Debug;
10
11
12pub fn codelist(code: &str) {
13 for (i, line) in code.lines().enumerate() {
14 println!("{:>3} | {}", i+1, line);
15 }
16}
17
18pub fn code_error(code: &str, tok_pos: usize) {
19 let code = format!("\n\n{}", code);
20 let code = code.lines().collect::<Vec<_>>();
21 let mut pos: isize = 0;
22 for (i, lines) in (&code[..]).windows(3).enumerate() {
23 if pos + lines[2].len() as isize >= tok_pos as isize {
24 if i > 1 {
25 println!("{:>3} | {}", i - 1, lines[0]);
26 }
27 if i > 0 {
28 println!("{:>3} | {}", i, lines[1]);
29 }
30 println!("{:>3} | {}", i + 1, lines[2]);
31
32 println!("{}^", (0..(tok_pos as isize) - (pos - 6)).map(|_| "~").collect::<String>());
33 return;
34 }
35 pos += (lines[2].len() as isize) + 1;
36 }
37}
38
39pub fn parse_results<C,T,E>(code: &str, res: Result<C, ParseError<usize,T,E>>) -> C
40where C: Debug, T: Debug, E: Debug {
41 match res {
42 Ok(value) => {
43 return value;
44 }
45 Err(ParseError::InvalidToken {
46 location: loc
47 }) => {
48 println!("Error: Invalid token:");
49 code_error(code, loc);
50 panic!("{:?}", res);
51 }
52 Err(ParseError::UnrecognizedToken {
53 token: Some((loc, _, _)),
54 ..
55 }) => {
56 println!("Error: Unrecognized token:");
57 code_error(code, loc);
58 panic!("{:?}", res);
59 }
60 err => {
61 panic!("{:?}", err);
62 }
63 }
64}
65
66pub fn parse(code: &str) -> ast::Code {
68 let re = Regex::new(r"(?m)//.*").unwrap();
70 let code = re.replace_all(&code, "");
71
72 parse_results(&code, verilog_parser::parse_Code(&code))
73}
74
75trait ToVerilog {
76 fn to_verilog(&self) -> String;
77}
78
79impl ToVerilog for ast::Code {
80 fn to_verilog(&self) -> String {
81 self.0.iter()
82 .map(|x| x.to_verilog())
83 .collect::<Vec<_>>()
84 .join("\n")
85 }
86}
87
88impl ToVerilog for ast::Toplevel {
89 fn to_verilog(&self) -> String {
90 match self {
91 &ast::Toplevel::Module(ast::Ident(ref name), ref args, ref decls) => {
92 format!("module {name} ({args}\n);{decls}\nendmodule\n",
93 name=name,
94 args=args.iter()
95 .map(|a| format!("\n{}", (a.0).0))
96 .collect::<Vec<_>>()
97 .join(","),
98 decls=decls.iter()
99 .map(|a| a.to_verilog())
100 .collect::<Vec<_>>()
101 .join(""))
102 }
103 }
104 }
105}
106
107impl ToVerilog for ast::Decl {
108 fn to_verilog(&self) -> String {
109 match self {
110 &ast::Decl::InnerArg(ref args) => {
111 format!("\n{args};",
112 args=args.iter()
113 .map(|a| format!("{}", (a.0).0))
114 .collect::<Vec<_>>()
115 .join(", "))
116 }
117 &ast::Decl::Reg(ast::Ident(ref name), ref dims) => {
118 format!("\nreg [{dims}] {name};",
119 name=name,
120 dims=dims.iter()
121 .map(|a| format!("{}", a.to_verilog()))
122 .collect::<Vec<_>>()
123 .join(":"))
124 }
125 &ast::Decl::Always(ref edge, ref body) => {
126 format!("\nalways @({edge}) {body}",
127 edge=edge.to_verilog(),
128 body=body.to_verilog())
129 }
130 _ => { "\nTODO;".to_string() },
131 }
132 }
133}
134
135impl ToVerilog for ast::Seq {
136 fn to_verilog(&self) -> String {
137 match self {
138 &ast::Seq::If(ref cond, ref then, ref alt) => {
139 format!("\nif ({cond}) {then}{alt}",
140 cond=cond.to_verilog(),
141 then=then.to_verilog(),
142 alt=if let &Some(ref alt) = alt {
143 format!("\nelse {then}",
144 then=alt.to_verilog())
145 } else {
146 "".to_string()
147 })
148 }
149 &ast::Seq::Set(ref kind, ast::Ident(ref name), ref value) => {
150 format!("\n{name} {kind} {value};",
151 name=name,
152 kind="<=",
153 value=value.to_verilog())
154 }
155 _ => { "\nTODO;".to_string() },
156 }
157 }
158}
159
160impl ToVerilog for ast::SeqBlock {
161 fn to_verilog(&self) -> String {
162 if (self.0).len() == 0 {
163 panic!("should be > 0")
164 } else if (self.0).len() == 1 {
165 (self.0)[0].to_verilog()
166 } else {
167 format!("\nbegin{}\nend", self.0.iter().map(|x| x.to_verilog()).collect::<Vec<_>>().join(""))
168 }
169 }
170}
171
172impl ToVerilog for ast::Expr {
173 fn to_verilog(&self) -> String {
174 match self {
175 &ast::Expr::Ref(ast::Ident(ref name)) => {
176 name.to_string()
177 }
178 &ast::Expr::Num(value) => {
179 format!("{}", value)
180 }
181 &ast::Expr::Arith(ref op, ref left, ref right) => {
182 format!("{left} {op} {right}",
183 left=left.to_verilog(),
184 op=match *op {
185 ast::Op::Add => "+",
186 _ => "??",
187 },
188 right=right.to_verilog())
189 }
190 _ => { "TODO EXPR".to_string() },
191 }
192 }
193}
194
195impl ToVerilog for ast::EdgeRef {
196 fn to_verilog(&self) -> String {
197 format!("{} {}", self.1.to_verilog(), (self.0).0)
198 }
199}
200
201impl ToVerilog for ast::Edge {
202 fn to_verilog(&self) -> String {
203 match self {
204 &ast::Edge::Pos => "posedge".to_string(),
205 &ast::Edge::Neg => "negedge".to_string(),
206 }
207 }
208}
209
210#[test]
211fn test_parser() {
212 let input = r#"
213//-----------------------------------------------------
214// Design Name : up_counter
215// File Name : up_counter.v
216// Function : Up counter
217// Coder : Deepak
218//-----------------------------------------------------
219module up_counter (
220out , // Output of the counter
221enable , // enable for counter
222clk , // clock Input
223reset // reset Input
224);
225//----------Output Ports--------------
226 output [7:0] out;
227//------------Input Ports--------------
228 input enable, clk, reset;
229//------------Internal Variables--------
230 reg [7:0] out;
231//-------------Code Starts Here-------
232 always @(posedge clk)
233 if (reset) begin
234 out <= 8'b0 ;
235 end else if (enable) begin
236 out <= out + 1;
237 end
238endmodule
239"#;
240
241 let res = parse(input);
242 println!("Out: {:?}", res);
243 println!("Out: \n{}\n", res.to_verilog());
244}