1use crate::ast::*;
2use crate::error::*;
3use pest::error::{Error, InputLocation, LineColLocation};
4use pest::iterators::Pair;
5use pest::Parser;
6
7#[derive(Parser)]
8#[grammar = "grammars/kaiju.pest"]
9pub struct KaijuParser;
10
11fn translate_error(err: Error<Rule>) -> Error<Rule> {
12 err.renamed_rules(|rule| match *rule {
13 Rule::shebang => "shebang (`#!{ ... }`)".to_owned(),
14 Rule::identifier => "identifier (`name` or `$extra.name`)".to_owned(),
15 Rule::identifier_simple => "simple identifier (`name`)".to_owned(),
16 Rule::identifier_extended => "extended identifier (`$extra.name`)".to_owned(),
17 Rule::type_ann => "type annotation (`:type`, `:*type`, `:(typeA, typeB)`)".to_owned(),
18 Rule::type_ => "type (`type`, `*type`, `(typeA, typeB)`)".to_owned(),
19 Rule::tuple_type => "tuple type (`(typeA, typeB)`)".to_owned(),
20 Rule::pointer_type => "pointer type (`*type`)".to_owned(),
21 Rule::string => "string (`'hello'`)".to_owned(),
22 Rule::integer => "integer (`42`, `42u8`, `0x2A`, `0x2Au8`)".to_owned(),
23 Rule::integer_inner => "integer (`42`, `0x2A`)".to_owned(),
24 Rule::hex => "hex (`0x2A`)".to_owned(),
25 Rule::float => "float (`4.2`, `4.2f64`, `4.2e7`, `4.2e7f64`)".to_owned(),
26 Rule::float_inner => "float (`4.2`, `4.2e7`)".to_owned(),
27 Rule::number => "number (`42`, `4.2`, `4.2e7`, `0x2A`, `42u8`, `4.2e7f64`)".to_owned(),
28 Rule::tuple_value => "tuple value (`(42, '42', &4.2)`)".to_owned(),
29 Rule::variable => "variable (`a:i32`)".to_owned(),
30 Rule::variable_access => "variable access (`a.foo`)".to_owned(),
31 Rule::tuple_access => "tuple access (`a.0`)".to_owned(),
32 Rule::ref_value => "reference access (`&<a>`, `&<a.v>`)".to_owned(),
33 Rule::deref_value => "dereference value (`*<a>`, `*<a.v>`)".to_owned(),
34 Rule::label => "label (`name:`)".to_owned(),
35 Rule::block => "code block (`{ ... }`)".to_owned(),
36 Rule::operation => "operation (`op param => target`)".to_owned(),
37 Rule::operation_inline => "inline operation (`(op param)`)".to_owned(),
38 Rule::operation_id => "operation identifier (`name`)".to_owned(),
39 Rule::operation_params => "operation params (`param1 param2 ...`)".to_owned(),
40 Rule::operation_targets => "operation targets (`=> target1 target2`)".to_owned(),
41 Rule::function => "function (`fn foo(v:i32):i32 { ... }`)".to_owned(),
42 Rule::function_header => "function header (`fn foo(v:i32):i32`)".to_owned(),
43 Rule::function_params => "function params (`(a:i32, b:f64)`)".to_owned(),
44 Rule::function_locals => "function locals (`<a:i32, b:f64>`)".to_owned(),
45 Rule::function_call => "function call (`foo(42, 4.2)`)".to_owned(),
46 Rule::function_call_args => "function call args (`foo(42, 4.2)`)".to_owned(),
47 Rule::meta_global => "global meta (`#![attrib];`)".to_owned(),
48 Rule::meta_local => "local meta (`#[attrib]`)".to_owned(),
49 Rule::meta_fields => "meta fields (`#[attrib1, attrib2]`)".to_owned(),
50 Rule::meta_field => "meta field (`#[attrib()]`)".to_owned(),
51 Rule::meta_field_args => "meta field args (`#[attrib(arg)]`)".to_owned(),
52 Rule::meta_value => {
53 "meta field value (`#[attrib(42, 4.2, '42', named = 42, attrib2())]`)".to_owned()
54 }
55 Rule::meta_named_value => "meta field named value (`#[attrib(named = 42)]`)".to_owned(),
56 Rule::extern_ => "external function (`extern fn log() from console:log;`)".to_owned(),
57 Rule::extern_item => "external function header (`fn foo(v:i32):i32`)".to_owned(),
58 Rule::extern_location => "external function location (`module:funname`)".to_owned(),
59 Rule::import => "import symbols (`import { foo, bar } from 'std';`)".to_owned(),
60 Rule::import_name => "import symbol identifier (`foo`)".to_owned(),
61 Rule::import_names => "import symbol identifiers (`{ foo, bar }`)".to_owned(),
62 Rule::import_module => "import module path (`'path/to/module`)".to_owned(),
63 Rule::globals => "globals (`<a:i32, b:f64>`)".to_owned(),
64 Rule::struct_ => "struct (`struct A { a:i32, b:f64 }`)".to_owned(),
65 Rule::struct_fields => "struct fields (`{ a:i32, b:f64 }`)".to_owned(),
66 Rule::op_rule => "rule (`add @value:a @value:b => r {}`)".to_owned(),
67 Rule::op_rule_def => "rule definition (`{ field: { name: 'value' } }`)".to_owned(),
68 Rule::op_rule_def_field => "rule definition field (`field: { name: 'value' }`)".to_owned(),
69 Rule::op_rule_def_field_id => "field id (`foo`)".to_owned(),
70 Rule::op_rule_def_field_desc => "field description (`{ name: 'value' }`)".to_owned(),
71 Rule::op_rule_def_field_desc_field => {
72 "field description parameter (`name: 'value'`)".to_owned()
73 }
74 _ => format!("{:?}", rule),
75 })
76}
77
78pub fn parse_module(source: &str) -> CompilationResult<AstModule> {
79 match KaijuParser::parse(Rule::module, source) {
80 Ok(mut ast) => {
81 let pair = ast.next().unwrap();
82 match pair.as_rule() {
83 Rule::module => Ok(parse_module_inner(pair)),
84 _ => unreachable!(),
85 }
86 }
87 Err(err) => {
88 let location = match err.location {
89 InputLocation::Pos(a) => (a, a),
90 InputLocation::Span((a, b)) => (a, b),
91 };
92 let (line, column) = match err.line_col {
93 LineColLocation::Pos((a, b)) => ((a, a), (b, b)),
94 LineColLocation::Span((a, b), (c, d)) => ((a, c), (b, d)),
95 };
96 let err = translate_error(err);
97 Err(CompilationError {
98 message: "".to_owned(),
99 location,
100 line,
101 column,
102 pretty: format!("{}", err),
103 })
104 }
105 }
106}
107
108pub fn parse_ops_descriptor(source: &str) -> CompilationResult<AstOpsDescriptor> {
109 match KaijuParser::parse(Rule::ops_descriptor, source) {
110 Ok(mut ast) => {
111 let pair = ast.next().unwrap();
112 match pair.as_rule() {
113 Rule::ops_descriptor => Ok(parse_ops_descriptor_inner(pair)),
114 _ => unreachable!(),
115 }
116 }
117 Err(err) => {
118 let location = match err.location {
119 InputLocation::Pos(a) => (a, a),
120 InputLocation::Span((a, b)) => (a, b),
121 };
122 let (line, column) = match err.line_col {
123 LineColLocation::Pos((a, b)) => ((a, a), (b, b)),
124 LineColLocation::Span((a, b), (c, d)) => ((a, c), (b, d)),
125 };
126 let err = translate_error(err);
127 Err(CompilationError {
128 message: "".to_owned(),
129 location,
130 line,
131 column,
132 pretty: format!("{}", err),
133 })
134 }
135 }
136}
137
138fn parse_module_inner(pair: Pair<Rule>) -> AstModule {
139 let mut shebang = None;
140 let mut instructions = vec![];
141 for p in pair.into_inner() {
142 match p.as_rule() {
143 Rule::shebang => shebang = Some(p.as_str().trim().to_owned()),
144 Rule::instruction => {
145 instructions.push(parse_instruction(p.into_inner().next().unwrap()))
146 }
147 Rule::EOI => {}
148 _ => unreachable!(),
149 }
150 }
151 AstModule {
152 shebang,
153 instructions,
154 }
155}
156
157fn parse_instruction(pair: Pair<Rule>) -> AstInstruction {
158 match pair.as_rule() {
159 Rule::meta_global => AstInstruction::Meta(parse_meta(pair)),
160 Rule::import => AstInstruction::Import(parse_import(pair)),
161 Rule::globals => AstInstruction::Globals(pair.into_inner().map(parse_variable).collect()),
162 Rule::extern_ => AstInstruction::Extern(parse_extern(pair)),
163 Rule::struct_ => AstInstruction::Struct(parse_struct(pair)),
164 Rule::function => AstInstruction::Function(parse_function(pair)),
165 _ => unreachable!(),
166 }
167}
168
169fn parse_meta(pair: Pair<Rule>) -> AstMeta {
170 AstMeta(
171 pair.into_inner()
172 .next()
173 .unwrap()
174 .into_inner()
175 .map(parse_meta_field)
176 .collect(),
177 )
178}
179
180fn parse_meta_field(pair: Pair<Rule>) -> AstMetaField {
181 let mut inner = pair.into_inner();
182 let id = parse_identifier(inner.next().unwrap());
183 let args = if let Some(p) = inner.next() {
184 p.into_inner()
185 .map(|p| parse_meta_value(p.into_inner().next().unwrap()))
186 .collect()
187 } else {
188 vec![]
189 };
190 AstMetaField { id, args }
191}
192
193fn parse_meta_value(pair: Pair<Rule>) -> AstMetaValue {
194 match pair.as_rule() {
195 Rule::meta_named_value => {
196 let (id, val) = parse_meta_named_value(pair);
197 AstMetaValue::Named(id, val)
198 }
199 Rule::meta_field => AstMetaValue::Field(parse_meta_field(pair)),
200 Rule::string => AstMetaValue::String(parse_string(pair)),
201 Rule::number => AstMetaValue::Number(parse_number(pair)),
202 _ => unreachable!(),
203 }
204}
205
206fn parse_meta_named_value(pair: Pair<Rule>) -> (AstIdentifier, Box<AstMetaValue>) {
207 let mut inner = pair.into_inner();
208 let pid = inner.next().unwrap();
209 let pval = inner.next().unwrap();
210 (
211 parse_identifier(pid),
212 Box::new(parse_meta_value(pval.into_inner().next().unwrap())),
213 )
214}
215
216fn parse_identifier(pair: Pair<Rule>) -> AstIdentifier {
217 let p = pair.into_inner().next().unwrap();
218 match p.as_rule() {
219 Rule::identifier_simple => AstIdentifier(p.as_str().to_owned()),
220 Rule::identifier_extended => {
221 AstIdentifier(p.into_inner().next().unwrap().as_str().to_owned())
222 }
223 _ => unreachable!(),
224 }
225}
226
227fn parse_string(pair: Pair<Rule>) -> AstString {
228 let mut inner = pair.into_inner();
229 let value = inner.next().unwrap().as_str().to_owned();
230 let type_ = if let Some(t) = inner.next() {
231 parse_type(t)
232 } else {
233 AstType::Pointer(Box::new(AstType::Identifier(AstIdentifier(
234 "{string}".to_string(),
235 ))))
236 };
237 AstString(value, type_)
238}
239
240fn parse_number(pair: Pair<Rule>) -> AstNumber {
241 let p = pair.into_inner().next().unwrap();
242 match p.as_rule() {
243 Rule::integer => AstNumber::Integer(parse_integer(p)),
244 Rule::float => AstNumber::Float(parse_float(p)),
245 _ => unreachable!(),
246 }
247}
248
249fn parse_integer(pair: Pair<Rule>) -> AstInteger {
250 let mut inner = pair.into_inner();
251 let value = inner.next().unwrap().as_str();
252 let type_ = if let Some(t) = inner.next() {
253 parse_type(t)
254 } else {
255 AstType::Identifier(AstIdentifier("{integer}".to_string()))
256 };
257 if value.starts_with("0x") {
258 AstInteger(
259 i64::from_str_radix(value.trim_start_matches("0x"), 16).unwrap(),
260 type_,
261 )
262 } else {
263 AstInteger(value.parse().unwrap(), type_)
264 }
265}
266
267fn parse_float(pair: Pair<Rule>) -> AstFloat {
268 let mut inner = pair.into_inner();
269 let value = inner.next().unwrap().as_str();
270 let type_ = if let Some(t) = inner.next() {
271 parse_type(t)
272 } else {
273 AstType::Identifier(AstIdentifier("{float}".to_string()))
274 };
275 AstFloat(value.parse().unwrap(), type_)
276}
277
278fn parse_import(pair: Pair<Rule>) -> AstImport {
279 let mut meta = vec![];
280 let mut names = vec![];
281 let mut module = AstString::default();
282 for p in pair.into_inner() {
283 match p.as_rule() {
284 Rule::meta_local => meta.push(parse_meta(p)),
285 Rule::import_names => names.extend(
286 p.into_inner()
287 .map(|p| parse_identifier(p.into_inner().next().unwrap()))
288 .collect::<Vec<AstIdentifier>>(),
289 ),
290 Rule::import_name => names.push(parse_identifier(p.into_inner().next().unwrap())),
291 Rule::import_module => module = parse_string(p.into_inner().next().unwrap()),
292 _ => unreachable!(),
293 }
294 }
295 AstImport {
296 meta,
297 names,
298 module,
299 }
300}
301
302fn parse_variable(pair: Pair<Rule>) -> AstVariable {
303 let mut inner = pair.into_inner();
304 let id = parse_identifier(inner.next().unwrap());
305 let typeid = parse_type(inner.next().unwrap().into_inner().next().unwrap());
306 AstVariable { id, typeid }
307}
308
309fn parse_type(pair: Pair<Rule>) -> AstType {
310 let p = pair.into_inner().next().unwrap();
311 match p.as_rule() {
312 Rule::tuple_type => AstType::Tuple(p.into_inner().map(parse_type).collect()),
313 Rule::pointer_type => {
314 AstType::Pointer(Box::new(parse_type(p.into_inner().next().unwrap())))
315 }
316 Rule::identifier => AstType::Identifier(parse_identifier(p)),
317 _ => unreachable!(),
318 }
319}
320
321fn parse_extern(pair: Pair<Rule>) -> AstExtern {
322 let mut meta = vec![];
323 let mut item = AstFunctionHeader {
324 id: AstIdentifier::default(),
325 params: vec![],
326 typeid: None,
327 };
328 let mut location_module = AstIdentifier::default();
329 let mut location_function = AstIdentifier::default();
330 for p in pair.into_inner() {
331 match p.as_rule() {
332 Rule::meta_local => meta.push(parse_meta(p)),
333 Rule::extern_item => item = parse_function_header(p),
334 Rule::extern_location => {
335 let mut inner = p.into_inner();
336 location_module = parse_identifier(inner.next().unwrap());
337 location_function = parse_identifier(inner.next().unwrap());
338 }
339 _ => unreachable!(),
340 }
341 }
342 AstExtern {
343 meta,
344 item,
345 location_module,
346 location_function,
347 }
348}
349
350fn parse_struct(pair: Pair<Rule>) -> AstStruct {
351 let mut meta = vec![];
352 let mut export = false;
353 let mut id = AstIdentifier::default();
354 let mut fields = vec![];
355 for p in pair.into_inner() {
356 match p.as_rule() {
357 Rule::meta_local => meta.push(parse_meta(p)),
358 Rule::export => export = true,
359 Rule::identifier => id = parse_identifier(p),
360 Rule::struct_fields => fields = p.into_inner().map(parse_variable).collect(),
361 _ => unreachable!(),
362 }
363 }
364 AstStruct {
365 meta,
366 export,
367 id,
368 fields,
369 }
370}
371
372fn parse_function(pair: Pair<Rule>) -> AstFunction {
373 let mut meta = vec![];
374 let mut export = false;
375 let mut header = None;
376 let mut locals = vec![];
377 let mut ops = vec![];
378 for p in pair.into_inner() {
379 match p.as_rule() {
380 Rule::meta_local => meta.push(parse_meta(p)),
381 Rule::export => export = true,
382 Rule::function_header => header = Some(parse_function_header(p)),
383 Rule::function_locals => locals = p.into_inner().map(parse_variable).collect(),
384 Rule::block => ops = parse_block(p),
385 _ => unreachable!(),
386 }
387 }
388 AstFunction {
389 meta,
390 export,
391 header: header.unwrap(),
392 locals,
393 ops,
394 }
395}
396
397fn parse_function_header(pair: Pair<Rule>) -> AstFunctionHeader {
398 let mut id = AstIdentifier::default();
399 let mut params = vec![];
400 let mut typeid = None;
401 for p in pair.into_inner() {
402 match p.as_rule() {
403 Rule::identifier => id = parse_identifier(p),
404 Rule::function_params => params = p.into_inner().map(parse_variable).collect(),
405 Rule::type_ann => typeid = Some(parse_type(p.into_inner().next().unwrap())),
406 _ => unreachable!(),
407 }
408 }
409 AstFunctionHeader { id, params, typeid }
410}
411
412fn parse_block(pair: Pair<Rule>) -> Vec<AstBlockOp> {
413 pair.into_inner()
414 .map(|p| match p.as_rule() {
415 Rule::label => AstBlockOp::Label(parse_identifier(p.into_inner().next().unwrap())),
416 Rule::operation => AstBlockOp::Operation(parse_operation(p)),
417 _ => unreachable!(),
418 })
419 .collect()
420}
421
422fn parse_operation(pair: Pair<Rule>) -> AstOperation {
423 let mut meta = vec![];
424 let mut id = AstIdentifier::default();
425 let mut params = vec![];
426 let mut targets = vec![];
427 for p in pair.into_inner() {
428 match p.as_rule() {
429 Rule::meta_local => meta.push(parse_meta(p)),
430 Rule::operation_id => id = parse_identifier(p),
431 Rule::operation_params => params = p.into_inner().map(parse_value).collect(),
432 Rule::operation_targets => targets = p.into_inner().map(parse_value).collect(),
433 _ => unreachable!(),
434 }
435 }
436 AstOperation {
437 meta,
438 id,
439 params,
440 targets,
441 }
442}
443
444fn parse_value(pair: Pair<Rule>) -> AstValue {
445 let mut inner = pair.into_inner();
446 let p = inner.next().unwrap().into_inner().next().unwrap();
447 let a = inner.next().map(|p| Box::new(parse_access(p)));
448 match p.as_rule() {
449 Rule::ref_value => parse_ref(p, a),
450 Rule::deref_value => parse_deref(p, a),
451 Rule::function_call => parse_function_call(p, a),
452 Rule::tuple_value => AstValue::Tuple(p.into_inner().map(parse_value).collect(), a),
453 Rule::string => AstValue::String(parse_string(p)),
454 Rule::number => AstValue::Number(parse_number(p)),
455 Rule::operation_inline => parse_operation_inline(p, a),
456 Rule::variable_value => {
457 AstValue::Variable(parse_identifier(p.into_inner().next().unwrap()), a)
458 }
459 _ => unreachable!(),
460 }
461}
462
463fn parse_ref(pair: Pair<Rule>, access: Option<Box<AstAccess>>) -> AstValue {
464 AstValue::Ref(
465 Box::new(parse_value(pair.into_inner().next().unwrap())),
466 access,
467 )
468}
469
470fn parse_deref(pair: Pair<Rule>, access: Option<Box<AstAccess>>) -> AstValue {
471 AstValue::Deref(
472 Box::new(parse_value(pair.into_inner().next().unwrap())),
473 access,
474 )
475}
476
477fn parse_function_call(pair: Pair<Rule>, access: Option<Box<AstAccess>>) -> AstValue {
478 let mut inner = pair.into_inner();
479 let id = parse_identifier(inner.next().unwrap());
480 let params = inner
481 .next()
482 .unwrap()
483 .into_inner()
484 .map(parse_value)
485 .collect();
486 AstValue::FunctionCall(id, params, access)
487}
488
489fn parse_access(pair: Pair<Rule>) -> AstAccess {
490 let p = pair.into_inner().next().unwrap();
491 match p.as_rule() {
492 Rule::variable_access => parse_variable_access(p),
493 Rule::tuple_access => parse_tuple_access(p),
494 _ => unreachable!(),
495 }
496}
497
498fn parse_variable_access(pair: Pair<Rule>) -> AstAccess {
499 let mut inner = pair.into_inner();
500 let id = parse_identifier(inner.next().unwrap());
501 let next = if let Some(p) = inner.next() {
502 Some(Box::new(parse_access(p)))
503 } else {
504 None
505 };
506 AstAccess::Variable(id, next)
507}
508
509fn parse_tuple_access(pair: Pair<Rule>) -> AstAccess {
510 let mut inner = pair.into_inner();
511 let id = parse_integer(inner.next().unwrap());
512 let next = if let Some(p) = inner.next() {
513 Some(Box::new(parse_access(p)))
514 } else {
515 None
516 };
517 AstAccess::Tuple(id, next)
518}
519
520fn parse_operation_inline(pair: Pair<Rule>, access: Option<Box<AstAccess>>) -> AstValue {
521 let mut inner = pair.into_inner();
522 let id = parse_identifier(inner.next().unwrap());
523 let params = inner
524 .next()
525 .unwrap()
526 .into_inner()
527 .map(parse_value)
528 .collect();
529 AstValue::OperationInline(id, params, access)
530}
531
532fn parse_ops_descriptor_inner(pair: Pair<Rule>) -> AstOpsDescriptor {
533 let mut meta = vec![];
534 let mut rules = vec![];
535 for p in pair.into_inner() {
536 match p.as_rule() {
537 Rule::meta_global => meta.push(parse_meta(p)),
538 Rule::op_rule => rules.push(parse_op_rule(p)),
539 Rule::EOI => {}
540 _ => unreachable!(),
541 }
542 }
543 AstOpsDescriptor { meta, rules }
544}
545
546fn parse_op_rule(pair: Pair<Rule>) -> AstOpRule {
547 let mut meta = vec![];
548 let mut id = AstIdentifier::default();
549 let mut params = vec![];
550 let mut targets = vec![];
551 let mut definition = vec![];
552 for p in pair.into_inner() {
553 match p.as_rule() {
554 Rule::meta_local => meta.push(parse_meta(p)),
555 Rule::identifier_simple => id = AstIdentifier(p.as_str().to_owned()),
556 Rule::op_param => params.push(parse_op_param(p)),
557 Rule::op_targets => targets = p.into_inner().map(parse_type).collect(),
558 Rule::op_rule_def => definition = p.into_inner().map(parse_op_rule_def).collect(),
559 _ => unreachable!(),
560 }
561 }
562 AstOpRule {
563 meta,
564 id,
565 params,
566 targets,
567 definition,
568 }
569}
570
571fn parse_op_param(pair: Pair<Rule>) -> AstOpParam {
572 let mut inner = pair.into_inner();
573 AstOpParam {
574 id: AstIdentifier(inner.next().unwrap().as_str().to_owned()),
575 typeid: parse_op_value(inner.next().unwrap()),
576 }
577}
578
579fn parse_op_value(pair: Pair<Rule>) -> AstType {
580 match pair.as_rule() {
581 Rule::op_value => parse_type(pair.into_inner().next().unwrap()),
582 _ => unreachable!(),
583 }
584}
585
586fn parse_op_rule_def(pair: Pair<Rule>) -> AstOpRuleDef {
587 let mut inner = pair.into_inner();
588 AstOpRuleDef {
589 id: AstIdentifier(inner.next().unwrap().as_str().to_owned()),
590 description: inner
591 .next()
592 .unwrap()
593 .into_inner()
594 .map(parse_op_rule_def_desc)
595 .collect(),
596 }
597}
598
599fn parse_op_rule_def_desc(pair: Pair<Rule>) -> AstOpRuleDefDesc {
600 let mut inner = pair.into_inner();
601 AstOpRuleDefDesc {
602 id: AstIdentifier(inner.next().unwrap().as_str().to_owned()),
603 value: parse_string(inner.next().unwrap()),
604 }
605}