007446a167
This commit refactors several modules to use the defined types from `ast::types` and `ast::nodes` directly, rather than using fully qualified paths. This improves code readability and reduces redundancy. Specifically, the following changes were made: - In `analyzer.rs`, `crate::ast::types::Identity` and `crate::ast::types::Purity` are now used directly. - In `binder.rs`, `crate::ast::types::NodeIdentity`, `crate::ast::types::SourceLocation`, `crate::ast::types::RecordLayout`, and `crate::ast::types::Value` are now used directly. - In `macros.rs`, types like `Address`, `VirtualId`, `NodeIdentity`, `SourceLocation`, `StaticType`, and `Purity` are now used directly. - In `optimizer/engine.rs`, `Address<VirtualId>` is now used directly. - In `type_checker.rs`, `BoundPhase`, `Signature`, `Keyword`, and `RecordLayout` are now used directly. - In `environment.rs`, `CompilerScope`, `LocalInfo`, `CapturePass`, `AnalyzedPhase`, `NativeFunction`, and `Closure` are now used directly. - In `nodes.rs`, `RecordLayout`, `Keyword`, `Purity`, and `StaticType` are now used directly. - In `parser.rs`, `SourceLocation` and `NodeIdentity` are now used directly. - In `rtl/math.rs`, `NativeFunction`, `Purity`, `Signature`, `StaticType`, `Value`, `RefCell`, and `Rc` are now used directly. - In `rtl/streams.rs`, `ScalarValue`, `SeriesMember`, `Object`, `PipeFn`, `Value`, `VM`, `RingBuffer`, `RecordSeries`, `SeriesView`, `build_map_stream`, and `build_pipeline_node` are now used directly. - In `rtl/type_registry.rs`, `RecordLayout`, `Keyword`, `Purity`, `Signature`, `StaticType`, and `Value` are now used directly. - In `vm.rs`, `RecordSeries`, `SeriesView`, `build_map_stream`, `build_pipeline_node`, `StreamNode`, `Object`, and `PipeFn` are now used directly. - In `utils/tester.rs`, `TypedNode` is now used directly.
545 lines
17 KiB
Rust
545 lines
17 KiB
Rust
use crate::ast::diagnostics::Diagnostics;
|
|
use crate::ast::lexer::{Lexer, Token, TokenKind};
|
|
use crate::ast::nodes::{Symbol, SyntaxKind, SyntaxNode};
|
|
use crate::ast::types::{Identity, Keyword, NodeIdentity, SourceLocation, Value};
|
|
use std::rc::Rc;
|
|
|
|
pub struct Parser<'a> {
|
|
lexer: Lexer<'a>,
|
|
current_token: Token,
|
|
pub diagnostics: Diagnostics,
|
|
}
|
|
|
|
impl<'a> Parser<'a> {
|
|
pub fn new(input: &'a str) -> Self {
|
|
let mut lexer = Lexer::new(input);
|
|
let mut diagnostics = Diagnostics::new();
|
|
let current_token = match lexer.next_token() {
|
|
Ok(t) => t,
|
|
Err(e) => {
|
|
diagnostics.push_error(e, None);
|
|
Token {
|
|
kind: TokenKind::EOF,
|
|
location: SourceLocation { line: 1, col: 1 },
|
|
}
|
|
}
|
|
};
|
|
Self {
|
|
lexer,
|
|
current_token,
|
|
diagnostics,
|
|
}
|
|
}
|
|
|
|
fn advance(&mut self) -> Token {
|
|
let next = match self.lexer.next_token() {
|
|
Ok(t) => t,
|
|
Err(e) => {
|
|
self.diagnostics
|
|
.push_error(e, Some(NodeIdentity::new(self.current_token.location)));
|
|
Token {
|
|
kind: TokenKind::EOF,
|
|
location: self.current_token.location,
|
|
}
|
|
}
|
|
};
|
|
std::mem::replace(&mut self.current_token, next)
|
|
}
|
|
|
|
fn peek(&self) -> &TokenKind {
|
|
&self.current_token.kind
|
|
}
|
|
|
|
pub fn parse_expression(&mut self) -> SyntaxNode {
|
|
let token_loc = self.current_token.location;
|
|
let identity = NodeIdentity::new(token_loc);
|
|
|
|
match self.peek() {
|
|
TokenKind::LeftParen => self.parse_list(),
|
|
TokenKind::LeftBracket => self.parse_vector_literal(),
|
|
TokenKind::LeftBrace => self.parse_record_literal(),
|
|
TokenKind::Quote => {
|
|
self.advance(); // consume '
|
|
let expr = self.parse_expression();
|
|
SyntaxNode {
|
|
identity: identity.clone(),
|
|
kind: SyntaxKind::Call {
|
|
callee: Rc::new(self.make_id_node("quote", identity.clone())),
|
|
args: Rc::new(SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Tuple {
|
|
elements: vec![Rc::new(expr)],
|
|
},
|
|
ty: (),
|
|
}),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
TokenKind::Backtick => {
|
|
self.advance(); // consume `
|
|
let expr = self.parse_expression();
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Template(Rc::new(expr)),
|
|
ty: (),
|
|
}
|
|
}
|
|
TokenKind::Tilde => {
|
|
self.advance(); // consume ~
|
|
if *self.peek() == TokenKind::At {
|
|
self.advance(); // consume @
|
|
let expr = self.parse_expression();
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Splice(Rc::new(expr)),
|
|
ty: (),
|
|
}
|
|
} else {
|
|
let expr = self.parse_expression();
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Placeholder(Rc::new(expr)),
|
|
ty: (),
|
|
}
|
|
}
|
|
}
|
|
_ => self.parse_atom(),
|
|
}
|
|
}
|
|
|
|
pub fn at_eof(&self) -> bool {
|
|
matches!(self.current_token.kind, TokenKind::EOF)
|
|
}
|
|
|
|
fn synchronize(&mut self) {
|
|
while !self.at_eof() {
|
|
match self.peek() {
|
|
TokenKind::RightParen | TokenKind::RightBracket | TokenKind::RightBrace => {
|
|
self.advance();
|
|
return;
|
|
}
|
|
_ => {
|
|
self.advance();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn parse_atom(&mut self) -> SyntaxNode {
|
|
let token = self.advance();
|
|
let identity = NodeIdentity::new(token.location);
|
|
|
|
let kind = match token.kind {
|
|
TokenKind::Integer(n) => SyntaxKind::Constant(Value::Int(n)),
|
|
TokenKind::Float(n) => SyntaxKind::Constant(Value::Float(n)),
|
|
TokenKind::String(s) => SyntaxKind::Constant(Value::Text(s)),
|
|
TokenKind::Keyword(k) => SyntaxKind::Constant(Value::Keyword(Keyword::intern(&k))),
|
|
TokenKind::Identifier(id) => match id.as_ref() {
|
|
"..." => SyntaxKind::Nop,
|
|
s if s.starts_with('.') && s.len() > 1 => {
|
|
SyntaxKind::FieldAccessor(Keyword::intern(&s[1..]))
|
|
}
|
|
_ => SyntaxKind::Identifier {
|
|
symbol: id.into(),
|
|
binding: (),
|
|
},
|
|
},
|
|
TokenKind::EOF => SyntaxKind::Error, // Error already logged by advance
|
|
_ => {
|
|
self.diagnostics.push_error(
|
|
format!("Unexpected token in atom: {:?}", token.kind),
|
|
Some(identity.clone()),
|
|
);
|
|
SyntaxKind::Error
|
|
}
|
|
};
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind,
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_list(&mut self) -> SyntaxNode {
|
|
let start_loc = self.advance().location; // consume '('
|
|
let identity = NodeIdentity::new(start_loc);
|
|
|
|
if *self.peek() == TokenKind::RightParen {
|
|
self.diagnostics.push_error(
|
|
"Empty list () is not a valid expression",
|
|
Some(identity.clone()),
|
|
);
|
|
self.advance(); // consume )
|
|
return SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Error,
|
|
ty: (),
|
|
};
|
|
}
|
|
|
|
let head = self.parse_expression();
|
|
|
|
let node = if let SyntaxKind::Identifier { ref symbol, .. } = head.kind {
|
|
match symbol.name.as_ref() {
|
|
"if" => self.parse_if(identity),
|
|
"fn" => self.parse_fn(identity),
|
|
"pipe" => self.parse_pipe(identity),
|
|
"again" => self.parse_again(identity),
|
|
"def" => self.parse_def(identity),
|
|
"assign" => self.parse_assign(identity),
|
|
"do" => self.parse_do(identity),
|
|
"macro" => self.parse_macro_decl(identity),
|
|
_ => self.parse_call(head, identity),
|
|
}
|
|
} else {
|
|
self.parse_call(head, identity)
|
|
};
|
|
|
|
self.expect(TokenKind::RightParen);
|
|
node
|
|
}
|
|
|
|
fn parse_again(&mut self, identity: Identity) -> SyntaxNode {
|
|
let mut elements = Vec::new();
|
|
|
|
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
|
elements.push(Rc::new(self.parse_expression()));
|
|
}
|
|
|
|
let args_node = SyntaxNode {
|
|
identity: identity.clone(),
|
|
kind: SyntaxKind::Tuple { elements },
|
|
ty: (),
|
|
};
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Again {
|
|
args: Rc::new(args_node),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_if(&mut self, identity: Identity) -> SyntaxNode {
|
|
let cond = Rc::new(self.parse_expression());
|
|
let then_br = Rc::new(self.parse_expression());
|
|
let mut else_br = None;
|
|
|
|
if *self.peek() != TokenKind::RightParen {
|
|
else_br = Some(Rc::new(self.parse_expression()));
|
|
}
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::If {
|
|
cond,
|
|
then_br,
|
|
else_br,
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_def(&mut self, identity: Identity) -> SyntaxNode {
|
|
let pattern = Rc::new(self.parse_pattern());
|
|
let value = Rc::new(self.parse_expression());
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Def {
|
|
pattern,
|
|
value,
|
|
info: (),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_assign(&mut self, identity: Identity) -> SyntaxNode {
|
|
// (assign target value)
|
|
let target = Rc::new(self.parse_expression());
|
|
let value = Rc::new(self.parse_expression());
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Assign {
|
|
target,
|
|
value,
|
|
info: (),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_do(&mut self, identity: Identity) -> SyntaxNode {
|
|
let mut exprs = Vec::new();
|
|
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
|
exprs.push(Rc::new(self.parse_expression()));
|
|
}
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Block { exprs },
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_pipe(&mut self, identity: Identity) -> SyntaxNode {
|
|
let inputs_node = self.parse_expression();
|
|
let inputs = match inputs_node.kind {
|
|
SyntaxKind::Tuple { elements } => elements,
|
|
_ => vec![Rc::new(inputs_node)],
|
|
};
|
|
let lambda = Rc::new(self.parse_expression());
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Pipe { inputs, lambda },
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_fn(&mut self, identity: Identity) -> SyntaxNode {
|
|
let params = Rc::new(self.parse_param_vector());
|
|
let body = self.parse_expression();
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Lambda {
|
|
params,
|
|
body: Rc::new(body),
|
|
info: (),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_macro_decl(&mut self, identity: Identity) -> SyntaxNode {
|
|
let name_node = self.parse_expression();
|
|
let name = match name_node.kind {
|
|
SyntaxKind::Identifier { symbol, .. } => symbol,
|
|
_ => {
|
|
self.diagnostics.push_error(
|
|
"Expected identifier for macro name",
|
|
Some(name_node.identity.clone()),
|
|
);
|
|
Symbol::from("error")
|
|
}
|
|
};
|
|
let params = Rc::new(self.parse_param_vector());
|
|
let body = self.parse_expression();
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::MacroDecl {
|
|
name,
|
|
params,
|
|
body: Rc::new(body),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_param_vector(&mut self) -> SyntaxNode {
|
|
if *self.peek() != TokenKind::LeftBracket {
|
|
self.diagnostics.push_error(
|
|
format!(
|
|
"Expected parameter vector [...] for fn, found {:?}",
|
|
self.peek()
|
|
),
|
|
Some(NodeIdentity::new(self.current_token.location)),
|
|
);
|
|
return SyntaxNode {
|
|
identity: NodeIdentity::new(self.current_token.location),
|
|
kind: SyntaxKind::Error,
|
|
ty: (),
|
|
};
|
|
}
|
|
self.parse_pattern()
|
|
}
|
|
|
|
fn parse_pattern(&mut self) -> SyntaxNode {
|
|
let next = self.peek();
|
|
match next {
|
|
TokenKind::Identifier(_) => {
|
|
let token = self.advance();
|
|
let sym: Symbol = match token.kind {
|
|
TokenKind::Identifier(s) => s.into(),
|
|
_ => unreachable!(),
|
|
};
|
|
SyntaxNode {
|
|
identity: NodeIdentity::new(token.location),
|
|
kind: SyntaxKind::Identifier {
|
|
symbol: sym,
|
|
binding: (),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
TokenKind::LeftBracket => {
|
|
let token = self.advance();
|
|
let identity = NodeIdentity::new(token.location);
|
|
|
|
let mut elements = Vec::new();
|
|
while *self.peek() != TokenKind::RightBracket && *self.peek() != TokenKind::EOF {
|
|
elements.push(Rc::new(self.parse_pattern()));
|
|
}
|
|
self.expect(TokenKind::RightBracket);
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Tuple { elements },
|
|
ty: (),
|
|
}
|
|
}
|
|
TokenKind::Tilde => {
|
|
let token = self.advance(); // consume ~
|
|
if *self.peek() == TokenKind::At {
|
|
self.advance(); // consume @
|
|
let expr = self.parse_expression();
|
|
SyntaxNode {
|
|
identity: NodeIdentity::new(token.location),
|
|
kind: SyntaxKind::Splice(Rc::new(expr)),
|
|
ty: (),
|
|
}
|
|
} else {
|
|
let expr = self.parse_expression();
|
|
SyntaxNode {
|
|
identity: NodeIdentity::new(token.location),
|
|
kind: SyntaxKind::Placeholder(Rc::new(expr)),
|
|
ty: (),
|
|
}
|
|
}
|
|
}
|
|
_ => {
|
|
self.diagnostics.push_error(
|
|
format!(
|
|
"Expected identifier or pattern vector [...] for definition, found {:?}",
|
|
next
|
|
),
|
|
Some(NodeIdentity::new(self.current_token.location)),
|
|
);
|
|
self.advance();
|
|
SyntaxNode {
|
|
identity: NodeIdentity::new(self.current_token.location),
|
|
kind: SyntaxKind::Error,
|
|
ty: (),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn parse_call(&mut self, callee: SyntaxNode, identity: Identity) -> SyntaxNode {
|
|
let mut elements = Vec::new();
|
|
|
|
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
|
elements.push(Rc::new(self.parse_expression()));
|
|
}
|
|
|
|
// The arguments are wrapped in a Tuple node, reusing the call's identity/location.
|
|
let args_node = SyntaxNode {
|
|
identity: identity.clone(),
|
|
kind: SyntaxKind::Tuple { elements },
|
|
ty: (),
|
|
};
|
|
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Call {
|
|
callee: Rc::new(callee),
|
|
args: Rc::new(args_node),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_vector_literal(&mut self) -> SyntaxNode {
|
|
let token = self.advance();
|
|
let mut elements = Vec::new();
|
|
|
|
while *self.peek() != TokenKind::RightBracket && *self.peek() != TokenKind::EOF {
|
|
let expr = self.parse_expression();
|
|
elements.push(Rc::new(expr));
|
|
}
|
|
|
|
self.expect(TokenKind::RightBracket);
|
|
|
|
SyntaxNode {
|
|
identity: NodeIdentity::new(token.location),
|
|
kind: SyntaxKind::Tuple { elements },
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn parse_record_literal(&mut self) -> SyntaxNode {
|
|
let token = self.advance();
|
|
let mut fields = Vec::new();
|
|
|
|
while *self.peek() != TokenKind::RightBrace && *self.peek() != TokenKind::EOF {
|
|
let key_node = self.parse_expression();
|
|
// We check for keyword kind here (syntactically) to avoid ambiguity, but
|
|
// strictly we could allow any expression and check at runtime.
|
|
// Delphi enforces keywords. We can do minimal check here.
|
|
match &key_node.kind {
|
|
SyntaxKind::Constant(Value::Keyword(_)) => {}
|
|
_ => {
|
|
self.diagnostics.push_error(
|
|
"Record keys must be keywords (syntactically)",
|
|
Some(key_node.identity.clone()),
|
|
);
|
|
}
|
|
}
|
|
|
|
if *self.peek() == TokenKind::RightBrace || *self.peek() == TokenKind::EOF {
|
|
self.diagnostics.push_error(
|
|
"Record literal must have even number of forms",
|
|
Some(NodeIdentity::new(self.current_token.location)),
|
|
);
|
|
break;
|
|
}
|
|
let val_node = self.parse_expression();
|
|
|
|
fields.push((Rc::new(key_node), Rc::new(val_node)));
|
|
}
|
|
self.expect(TokenKind::RightBrace);
|
|
|
|
SyntaxNode {
|
|
identity: NodeIdentity::new(token.location),
|
|
kind: SyntaxKind::Record {
|
|
fields,
|
|
layout: (),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
|
|
fn expect(&mut self, kind: TokenKind) -> Token {
|
|
if self.peek() == &kind {
|
|
self.advance()
|
|
} else {
|
|
self.diagnostics.push_error(
|
|
format!("Expected {:?}, but found {:?}", kind, self.peek()),
|
|
Some(NodeIdentity::new(self.current_token.location)),
|
|
);
|
|
// Recovery: skip until we find what we expected or a synchronization point
|
|
self.synchronize();
|
|
Token {
|
|
kind,
|
|
location: self.current_token.location,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn make_id_node(&self, name: &str, identity: Identity) -> SyntaxNode {
|
|
SyntaxNode {
|
|
identity,
|
|
kind: SyntaxKind::Identifier {
|
|
symbol: Symbol::from(name),
|
|
binding: (),
|
|
},
|
|
ty: (),
|
|
}
|
|
}
|
|
}
|