Simple parser
This commit is contained in:
+10
-5
@@ -1,8 +1,7 @@
|
|||||||
WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
|
WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
|
||||||
COMMENT = _{ "//" ~ (!"\n" ~ ANY)* }
|
COMMENT = _{ "//" ~ (!"\n" ~ ANY)* }
|
||||||
|
|
||||||
program = { SOI ~ item* ~ EOI }
|
program = { SOI ~ top_level* ~ EOI }
|
||||||
item = _{ import_decl | function_decl }
|
|
||||||
|
|
||||||
// primitives
|
// primitives
|
||||||
identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
|
identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
|
||||||
@@ -14,9 +13,11 @@ inner_str = @{ (!"\"" ~ ANY)* }
|
|||||||
|
|
||||||
// ================= TOP LEVEL =================
|
// ================= TOP LEVEL =================
|
||||||
|
|
||||||
|
top_level = _{ import | function_decl }
|
||||||
|
|
||||||
export = { "export"? }
|
export = { "export"? }
|
||||||
|
|
||||||
import_decl = { "import" ~ string_lit ~ ";" }
|
import = { "import" ~ string_lit ~ ";" }
|
||||||
|
|
||||||
param_list = { param ~ ("," ~ param)* ~ ","? }
|
param_list = { param ~ ("," ~ param)* ~ ","? }
|
||||||
param = { identifier ~ ":" ~ type_expr }
|
param = { identifier ~ ":" ~ type_expr }
|
||||||
@@ -26,9 +27,13 @@ function_decl = {
|
|||||||
|
|
||||||
// ================= STATEMENTS =================
|
// ================= STATEMENTS =================
|
||||||
|
|
||||||
block = { "{" ~ "}" }
|
block = { "{" ~ statement_list ~ "}" }
|
||||||
|
|
||||||
statement = _{ "idk" }
|
statement_list = { statement* }
|
||||||
|
|
||||||
|
statement = _{ expr_stmt }
|
||||||
|
|
||||||
|
expr_stmt = { expr ~ ";" }
|
||||||
|
|
||||||
// ================= EXPRESSIONS =================
|
// ================= EXPRESSIONS =================
|
||||||
type_expr = _{ identifier }
|
type_expr = _{ identifier }
|
||||||
|
|||||||
+74
-18
@@ -16,30 +16,86 @@ pub fn parse(source: &str) -> Result<Vec<TopLevel>, ParseError> {
|
|||||||
|
|
||||||
let mut statements = vec![];
|
let mut statements = vec![];
|
||||||
|
|
||||||
// pairs is an iterator over the top-level program pair
|
|
||||||
// we need to get its inner children
|
|
||||||
for pair in pairs {
|
for pair in pairs {
|
||||||
match pair.as_rule() {
|
statements.push(TopLevel::from_pair(pair));
|
||||||
Rule::program => {
|
|
||||||
for inner in pair.into_inner() {
|
|
||||||
match inner.as_rule() {
|
|
||||||
Rule::import_decl => {
|
|
||||||
let path = inner.into_inner().next().unwrap().as_str().to_string();
|
|
||||||
statements.push(TopLevel::Import(path));
|
|
||||||
}
|
|
||||||
Rule::EOI => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Rule::EOI => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(statements)
|
Ok(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypeExpr {
|
||||||
|
pub fn from_pair(pair: pest::iterators::Pair<Rule>) -> Self {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::type_expr => {
|
||||||
|
let inner = pair.into_inner().next().unwrap();
|
||||||
|
TypeExpr::from_pair(inner)
|
||||||
|
}
|
||||||
|
Rule::identifier => TypeExpr::Identifier(pair.as_str().to_string()),
|
||||||
|
_ => unimplemented!("TypeExpr parsing not implemented yet"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TopLevel {
|
||||||
|
pub fn from_pair(pair: pest::iterators::Pair<Rule>) -> Self {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::program => {
|
||||||
|
let inner = pair.into_inner().next().unwrap();
|
||||||
|
TopLevel::from_pair(inner)
|
||||||
|
}
|
||||||
|
Rule::import => {
|
||||||
|
let path = pair.into_inner().next().unwrap().as_str().to_string();
|
||||||
|
TopLevel::Import(path)
|
||||||
|
}
|
||||||
|
Rule::function_decl => {
|
||||||
|
let mut inner = pair.into_inner();
|
||||||
|
let export = if let Some(first) = inner.peek() {
|
||||||
|
if first.as_rule() == Rule::export {
|
||||||
|
inner.next();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
let name = inner.next().unwrap().as_str().to_string();
|
||||||
|
let params_pair = inner.next().unwrap();
|
||||||
|
let params = if params_pair.as_rule() == Rule::param_list {
|
||||||
|
params_pair
|
||||||
|
.into_inner()
|
||||||
|
.map(|p| {
|
||||||
|
let mut param_inner = p.into_inner();
|
||||||
|
let param_name = param_inner.next().unwrap().as_str().to_string();
|
||||||
|
let param_type = TypeExpr::from_pair(param_inner.next().unwrap());
|
||||||
|
(param_name, param_type)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
let return_type = if let Some(next) = inner.peek() {
|
||||||
|
if next.as_rule() == Rule::type_expr {
|
||||||
|
Some(TypeExpr::from_pair(inner.next().unwrap()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
// For now, we'll just ignore the function body and return an empty vector
|
||||||
|
TopLevel::FunctionDecl {
|
||||||
|
name,
|
||||||
|
params,
|
||||||
|
return_type,
|
||||||
|
body: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unimplemented!("TopLevel parsing not implemented yet {:?}", pair.as_rule()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn from_pair(pair: pest::iterators::Pair<Rule>) -> Self {
|
pub fn from_pair(pair: pest::iterators::Pair<Rule>) -> Self {
|
||||||
match pair.as_rule() {
|
match pair.as_rule() {
|
||||||
|
|||||||
+3
-1
@@ -1,3 +1,5 @@
|
|||||||
import "fmt";
|
import "fmt";
|
||||||
|
|
||||||
function add(a: int, b: int): int {}
|
function add(a: int, b: int): int {
|
||||||
|
hello;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user