1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
use crate::high_level::problem::{CompileProblem, FilePosition}; use pest::error::ErrorVariant; use pest::Parser; #[derive(Parser)] #[grammar = "ast/grammar.pest"] struct NodespeakParser; pub mod structure { pub use super::Rule; use pest::iterators::{Pair, Pairs}; pub type Program<'a> = Pairs<'a, Rule>; pub type Node<'a> = Pair<'a, Rule>; pub fn rule_name(rule: &Rule) -> &'static str { match rule { Rule::WHITESPACE => "whitespace", Rule::COMMENT | Rule::block_comment | Rule::line_comment => "comment", Rule::EOI => "end of file", Rule::dec_int => "integer literal", Rule::hex_int => "hexadecimal literal", Rule::oct_int => "octal literal", Rule::legacy_oct_int => "c-style octal literal", Rule::bin_int => "binary literal", Rule::dec_digit => "digit", Rule::float => "float literal", Rule::int => "int literal", Rule::literal => "literal value", Rule::identifier => "identifier", Rule::vp_var => "variable", Rule::build_array => "array data", Rule::vpe_part_1 | Rule::vpe_part_2 | Rule::vpe_part_3 | Rule::vpe_part | Rule::vpe => { "value-producing expression" } Rule::build_array_type => "array type", Rule::optional_index_indicator => "?", Rule::vp_index => "index expression", Rule::get_property => "property access", Rule::negate => "negate", Rule::not => "not", Rule::operator => "binary operator", Rule::var_dec => "variable declaration", Rule::vc_identifier => "variable", Rule::vc_index => "index expression", Rule::vce => "value-consuming expression", Rule::macro_call_input_list => "input list for macro call", Rule::inline_output => "inline keyword", Rule::macro_call_output => "output for macro call", Rule::macro_call_output_list => "output list for macro call", Rule::macro_call => "single-output macro callession", Rule::macro_inputs => "input list for macro definition", Rule::macro_outputs => "output list for macro definition", Rule::single_macro_output => "single output for macro definition", Rule::macro_signature => "signature for macro definition", Rule::macro_definition => "macro definition", Rule::else_if_clause => "else if clause", Rule::else_clause => "else clause", Rule::if_statement => "if statement", Rule::no_unroll_keyword => "no_unroll (keyword)", Rule::for_loop_statement => "for loop", Rule::raw_string => "string segment", Rule::escape_sequence => "string escape sequence", Rule::string => "string literal", Rule::input_variable_statement => "input declaration", Rule::output_variable_statement => "output declaration", Rule::static_variable_statement => "static variable declaration", Rule::assign_statement => "assignment statement", Rule::macro_call_statement => "macro call as statement", Rule::var_dec_statement => "variable declaration as statement", Rule::return_statement => "return statement", Rule::assert_statement => "assert statement", Rule::include_statement => "include statement", Rule::statement => "statement", Rule::code_block => "code block", Rule::root => "program", } } } pub(self) mod problems { use crate::high_level::problem::{ CompileProblem, FilePosition, ProblemDescriptor, ProblemType, }; pub fn bad_syntax(pos: FilePosition, message: String) -> CompileProblem { CompileProblem::from_descriptors(vec![ProblemDescriptor::new( pos, ProblemType::Error, &format!("Bad Syntax\n{}", message), )]) } } pub fn ingest(text: &str, file_id: usize) -> Result<structure::Program, CompileProblem> { NodespeakParser::parse(Rule::root, text).map_err(|parse_err| { problems::bad_syntax( FilePosition::from_input_location(parse_err.location, file_id), match parse_err.variant { ErrorVariant::ParsingError { positives, negatives, } => format!( "Expected {}... but found {}.", { positives .iter() .map(|rule| structure::rule_name(rule)) .collect::<Vec<&str>>() .join(", ") }, { if negatives.len() == 0 { "unknown syntax".to_owned() } else { negatives .iter() .map(|rule| structure::rule_name(rule)) .collect::<Vec<&str>>() .join(", ") } } ), ErrorVariant::CustomError { message: _message } => { unreachable!("Only parsing errors are encountered in the parser.") } }, ) }) }