feat: Add comments to AST nodes
This commit introduces support for comments within the AST nodes. Comments are now parsed by the lexer and stored within the `Token` struct. These comments are then propagated through various compiler phases, including the `Node` struct, ensuring they are preserved in the Abstract Syntax Tree. This change enhances the AST's ability to retain source code information, which can be valuable for debugging and analysis.
This commit is contained in:
@@ -298,6 +298,7 @@ impl<'a> Analyzer<'a> {
|
||||
Node {
|
||||
identity: node.identity.clone(),
|
||||
kind: new_kind,
|
||||
comments: node.comments.clone(),
|
||||
ty: NodeMetrics {
|
||||
original: node_rc,
|
||||
purity,
|
||||
|
||||
@@ -539,6 +539,7 @@ impl Binder {
|
||||
self.make_node(node.identity.clone(), NodeKind::Error)
|
||||
}
|
||||
SyntaxKind::Error => Node {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity.clone(),
|
||||
kind: NodeKind::Error,
|
||||
ty: (),
|
||||
@@ -701,6 +702,7 @@ impl Binder {
|
||||
|
||||
fn make_node(&self, identity: Identity, kind: NodeKind<BoundPhase>) -> Node<BoundPhase> {
|
||||
Node {
|
||||
comments: std::rc::Rc::from([]),
|
||||
identity,
|
||||
kind,
|
||||
ty: (),
|
||||
|
||||
@@ -79,9 +79,10 @@ impl Lowering {
|
||||
ty: RuntimeMetadata {
|
||||
ty: node.ty.original.ty.clone(),
|
||||
is_tail: is_tail_position,
|
||||
original: node_rc,
|
||||
original: node_rc.clone(),
|
||||
stack_size: 0,
|
||||
},
|
||||
comments: node.comments.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -261,9 +262,10 @@ impl Lowering {
|
||||
ty: RuntimeMetadata {
|
||||
ty: node.ty.original.ty.clone(),
|
||||
is_tail: is_tail_position,
|
||||
original: node_rc,
|
||||
original: node_rc.clone(),
|
||||
stack_size,
|
||||
},
|
||||
comments: node.comments.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let p_names = self.extract_param_names(¶ms)?;
|
||||
self.registry.define(name.name, p_names, (*body).clone());
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Nop,
|
||||
ty: (),
|
||||
@@ -128,6 +129,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let expanded_args = self.expand_recursive((*args).clone())?;
|
||||
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Call {
|
||||
callee: Rc::new(expanded_callee),
|
||||
@@ -146,6 +148,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
self.registry.pop();
|
||||
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Block {
|
||||
exprs: expanded_exprs,
|
||||
@@ -161,6 +164,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
self.registry.pop();
|
||||
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Lambda {
|
||||
params: Rc::new(expanded_params),
|
||||
@@ -184,6 +188,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
None
|
||||
};
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::If {
|
||||
cond: Rc::new(cond),
|
||||
@@ -198,6 +203,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let pattern = self.expand_recursive((*pattern).clone())?;
|
||||
let value = self.expand_recursive((*value).clone())?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Def {
|
||||
pattern: Rc::new(pattern),
|
||||
@@ -212,6 +218,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let target = self.expand_recursive((*target).clone())?;
|
||||
let value = self.expand_recursive((*value).clone())?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Assign {
|
||||
target: Rc::new(target),
|
||||
@@ -228,6 +235,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
expanded_elements.push(Rc::new(self.expand_recursive((*e).clone())?));
|
||||
}
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Tuple {
|
||||
elements: expanded_elements,
|
||||
@@ -245,6 +253,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
));
|
||||
}
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Record {
|
||||
fields: expanded_fields,
|
||||
@@ -257,6 +266,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
SyntaxKind::Expansion { original_call, expanded } => {
|
||||
let expanded = self.expand_recursive((*expanded).clone())?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Expansion {
|
||||
original_call,
|
||||
@@ -269,6 +279,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
SyntaxKind::Again { args } => {
|
||||
let expanded_args = self.expand_recursive((*args).clone())?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Again {
|
||||
args: Rc::new(expanded_args),
|
||||
@@ -316,9 +327,11 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
};
|
||||
|
||||
let original_call = SyntaxNode {
|
||||
comments: std::rc::Rc::from([]),
|
||||
identity: identity.clone(),
|
||||
kind: SyntaxKind::Call {
|
||||
callee: Rc::new(SyntaxNode {
|
||||
comments: std::rc::Rc::from([]),
|
||||
identity: identity.clone(),
|
||||
kind: SyntaxKind::Identifier {
|
||||
symbol: Symbol::from(name),
|
||||
@@ -327,6 +340,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
ty: (),
|
||||
}),
|
||||
args: Rc::new(SyntaxNode {
|
||||
comments: std::rc::Rc::from([]),
|
||||
identity: identity.clone(),
|
||||
kind: SyntaxKind::Tuple {
|
||||
elements: bindings.into_values().map(Rc::new).collect(),
|
||||
@@ -338,6 +352,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
};
|
||||
|
||||
Ok(SyntaxNode {
|
||||
comments: std::rc::Rc::from([]),
|
||||
identity,
|
||||
kind: SyntaxKind::Expansion {
|
||||
original_call: Rc::new(original_call),
|
||||
@@ -371,6 +386,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
// Inside a template, all internal identifiers are colored.
|
||||
symbol.context = Some(state.expansion_id.clone());
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Identifier {
|
||||
symbol,
|
||||
@@ -406,6 +422,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let pattern = self.expand_template((*pattern).clone(), state)?;
|
||||
let val = self.expand_template((*value).clone(), state)?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Def {
|
||||
pattern: Rc::new(pattern),
|
||||
@@ -420,6 +437,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let target = self.expand_template((*target).clone(), state)?;
|
||||
let value = self.expand_template((*value).clone(), state)?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Assign {
|
||||
target: Rc::new(target),
|
||||
@@ -441,6 +459,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
}
|
||||
}
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Tuple {
|
||||
elements: new_elements,
|
||||
@@ -460,6 +479,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
}
|
||||
}
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Block { exprs: new_exprs },
|
||||
ty: (),
|
||||
@@ -475,6 +495,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
));
|
||||
}
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Record {
|
||||
fields: new_fields,
|
||||
@@ -488,6 +509,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let expanded_callee = self.expand_template((*callee).clone(), state)?;
|
||||
let expanded_args = self.expand_template((*args).clone(), state)?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Call {
|
||||
callee: Rc::new(expanded_callee),
|
||||
@@ -510,6 +532,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
None
|
||||
};
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::If {
|
||||
cond: Rc::new(cond),
|
||||
@@ -524,6 +547,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let expanded_params = self.expand_template((*params).clone(), state)?;
|
||||
let body = self.expand_template((*body).clone(), state)?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Lambda {
|
||||
params: Rc::new(expanded_params),
|
||||
@@ -537,6 +561,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
SyntaxKind::Again { args } => {
|
||||
let expanded_args = self.expand_template((*args).clone(), state)?;
|
||||
Ok(SyntaxNode {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity,
|
||||
kind: SyntaxKind::Again {
|
||||
args: Rc::new(expanded_args),
|
||||
@@ -582,6 +607,7 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
match val {
|
||||
Value::Quote(rc) => rc.as_ref().clone(),
|
||||
_ => SyntaxNode {
|
||||
comments: std::rc::Rc::from([]),
|
||||
identity,
|
||||
kind: SyntaxKind::Constant(val),
|
||||
ty: (),
|
||||
|
||||
@@ -724,6 +724,7 @@ impl Optimizer {
|
||||
Rc::new(Node {
|
||||
identity: node.identity.clone(),
|
||||
kind: new_kind,
|
||||
comments: node.comments.clone(),
|
||||
ty: metrics,
|
||||
})
|
||||
}
|
||||
@@ -780,6 +781,7 @@ impl Optimizer {
|
||||
_ => return node_rc.clone(),
|
||||
};
|
||||
Rc::new(Node {
|
||||
comments: node.comments.clone(),
|
||||
identity: node.identity.clone(),
|
||||
kind: new_kind,
|
||||
ty: node.ty.clone(),
|
||||
|
||||
@@ -19,11 +19,13 @@ impl<'a> Folder<'a> {
|
||||
let typed_original = Rc::new(Node {
|
||||
identity: template.identity.clone(),
|
||||
kind: NodeKind::Constant(val.clone()),
|
||||
comments: template.comments.clone(),
|
||||
ty: ty.clone(),
|
||||
});
|
||||
Node {
|
||||
identity: template.identity.clone(),
|
||||
kind: NodeKind::Constant(val),
|
||||
comments: template.comments.clone(),
|
||||
ty: NodeMetrics {
|
||||
original: typed_original,
|
||||
purity: Purity::Pure,
|
||||
@@ -36,11 +38,13 @@ impl<'a> Folder<'a> {
|
||||
let typed_original = Rc::new(Node {
|
||||
identity: template.identity.clone(),
|
||||
kind: NodeKind::Nop,
|
||||
comments: template.comments.clone(),
|
||||
ty: StaticType::Void,
|
||||
});
|
||||
Node {
|
||||
identity: template.identity.clone(),
|
||||
kind: NodeKind::Nop,
|
||||
comments: template.comments.clone(),
|
||||
ty: NodeMetrics {
|
||||
original: typed_original,
|
||||
purity: Purity::Pure,
|
||||
|
||||
@@ -231,6 +231,7 @@ impl SubstitutionMap {
|
||||
Rc::new(Node {
|
||||
identity: node.identity.clone(),
|
||||
kind: new_kind,
|
||||
comments: node.comments.clone(),
|
||||
ty: metrics,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ impl Specializer {
|
||||
identity: node.identity,
|
||||
kind: new_kind,
|
||||
ty: metrics,
|
||||
comments: node.comments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +263,7 @@ impl Specializer {
|
||||
identity: template.identity.clone(),
|
||||
kind: NodeKind::Constant(val.clone()),
|
||||
ty: ty.clone(),
|
||||
comments: template.comments.clone(),
|
||||
});
|
||||
Node {
|
||||
identity: template.identity.clone(),
|
||||
@@ -271,6 +273,7 @@ impl Specializer {
|
||||
purity: Purity::Pure,
|
||||
is_recursive: false,
|
||||
},
|
||||
comments: template.comments.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +206,7 @@ impl TypeChecker {
|
||||
},
|
||||
},
|
||||
ty: fn_ty,
|
||||
comments: node.comments.clone(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@@ -269,6 +270,7 @@ impl TypeChecker {
|
||||
},
|
||||
},
|
||||
ty: fn_ty,
|
||||
comments: node.comments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,11 +305,13 @@ impl TypeChecker {
|
||||
},
|
||||
},
|
||||
ty: specialized_ty.clone(),
|
||||
comments: pattern.comments.clone(),
|
||||
}),
|
||||
value: Rc::new(Node {
|
||||
identity: node.identity.clone(),
|
||||
kind: NodeKind::Nop,
|
||||
ty: specialized_ty.clone(),
|
||||
comments: Rc::from([]),
|
||||
}),
|
||||
info: DefBinding {
|
||||
captured_by: info.captured_by.clone(),
|
||||
@@ -338,11 +342,13 @@ impl TypeChecker {
|
||||
identity: node.identity.clone(),
|
||||
kind: NodeKind::Nop,
|
||||
ty: specialized_ty.clone(),
|
||||
comments: Rc::from([]),
|
||||
}),
|
||||
value: Rc::new(Node {
|
||||
identity: node.identity.clone(),
|
||||
kind: NodeKind::Nop,
|
||||
ty: specialized_ty.clone(),
|
||||
comments: Rc::from([]),
|
||||
}),
|
||||
info: AssignBinding {
|
||||
addr: info.addr,
|
||||
@@ -385,6 +391,7 @@ impl TypeChecker {
|
||||
identity: node.identity.clone(),
|
||||
kind,
|
||||
ty,
|
||||
comments: node.comments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,6 +423,7 @@ impl TypeChecker {
|
||||
identity: node.identity.clone(),
|
||||
kind: NodeKind::Error,
|
||||
ty: StaticType::Error,
|
||||
comments: node.comments.clone(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -447,6 +455,7 @@ impl TypeChecker {
|
||||
elements: typed_elements,
|
||||
},
|
||||
ty: StaticType::Tuple(elem_types),
|
||||
comments: node.comments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,6 +504,7 @@ impl TypeChecker {
|
||||
},
|
||||
},
|
||||
ty,
|
||||
comments: node.comments.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -519,6 +529,7 @@ impl TypeChecker {
|
||||
_ => NodeKind::Error,
|
||||
},
|
||||
ty: ty.clone(),
|
||||
comments: pattern.comments.clone(),
|
||||
};
|
||||
|
||||
(
|
||||
@@ -617,6 +628,7 @@ impl TypeChecker {
|
||||
identity: node.identity.clone(),
|
||||
kind: NodeKind::Nop,
|
||||
ty: ty.clone(),
|
||||
comments: Rc::from([]),
|
||||
})
|
||||
};
|
||||
|
||||
@@ -776,6 +788,7 @@ impl TypeChecker {
|
||||
elements: final_elements,
|
||||
},
|
||||
ty: StaticType::Tuple(elem_types),
|
||||
comments: args.comments.clone(),
|
||||
}
|
||||
} else {
|
||||
self.check_node(args, ctx, diag)
|
||||
@@ -819,6 +832,7 @@ impl TypeChecker {
|
||||
elements: typed_elements,
|
||||
},
|
||||
ty: StaticType::Tuple(elem_types),
|
||||
comments: args.comments.clone(),
|
||||
}
|
||||
} else {
|
||||
self.check_node(args, ctx, diag)
|
||||
@@ -948,6 +962,7 @@ impl TypeChecker {
|
||||
identity: node.identity.clone(),
|
||||
kind,
|
||||
ty,
|
||||
comments: node.comments.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,6 +549,7 @@ impl Environment {
|
||||
identity: bound_ast.identity.clone(),
|
||||
kind: NodeKind::Tuple { elements: vec![] },
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}),
|
||||
body: std::rc::Rc::new(bound_ast),
|
||||
info: LambdaBinding {
|
||||
@@ -557,6 +558,7 @@ impl Environment {
|
||||
},
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
};
|
||||
Some(checker.check(&wrapped_ast, &[], diagnostics))
|
||||
|
||||
+66
-5
@@ -27,12 +27,15 @@ pub enum TokenKind {
|
||||
pub struct Token {
|
||||
pub kind: TokenKind,
|
||||
pub location: SourceLocation,
|
||||
pub comments: Rc<[Rc<str>]>,
|
||||
}
|
||||
|
||||
pub struct Lexer<'a> {
|
||||
input: Peekable<Chars<'a>>,
|
||||
line: u32,
|
||||
col: u32,
|
||||
at_line_start: bool,
|
||||
comments_buffer: Vec<Rc<str>>,
|
||||
}
|
||||
|
||||
impl<'a> Lexer<'a> {
|
||||
@@ -41,11 +44,29 @@ impl<'a> Lexer<'a> {
|
||||
input: input.chars().peekable(),
|
||||
line: 1,
|
||||
col: 1,
|
||||
at_line_start: true,
|
||||
comments_buffer: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_token(&mut self) -> Result<Token, String> {
|
||||
self.skip_whitespace();
|
||||
self.skip_whitespace_and_comments()?;
|
||||
|
||||
let comments: Rc<[Rc<str>]> = if self.comments_buffer.is_empty() {
|
||||
Rc::from([])
|
||||
} else {
|
||||
let mut start = 0;
|
||||
while start < self.comments_buffer.len() && self.comments_buffer[start].is_empty() {
|
||||
start += 1;
|
||||
}
|
||||
let mut end = self.comments_buffer.len();
|
||||
while end > start && self.comments_buffer[end - 1].is_empty() {
|
||||
end -= 1;
|
||||
}
|
||||
let res: Rc<[Rc<str>]> = self.comments_buffer[start..end].iter().cloned().collect();
|
||||
self.comments_buffer.clear();
|
||||
res
|
||||
};
|
||||
|
||||
let start_location = SourceLocation {
|
||||
line: self.line,
|
||||
@@ -62,6 +83,7 @@ impl<'a> Lexer<'a> {
|
||||
return Ok(Token {
|
||||
kind: TokenKind::EOF,
|
||||
location: start_location,
|
||||
comments,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -119,6 +141,7 @@ impl<'a> Lexer<'a> {
|
||||
Ok(Token {
|
||||
kind,
|
||||
location: start_location,
|
||||
comments,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -126,28 +149,66 @@ impl<'a> Lexer<'a> {
|
||||
self.input.peek()
|
||||
}
|
||||
|
||||
fn skip_whitespace(&mut self) {
|
||||
fn skip_whitespace_and_comments(&mut self) -> Result<(), String> {
|
||||
let mut consecutive_newlines = 0;
|
||||
while let Some(&c) = self.peek() {
|
||||
if c.is_whitespace() || is_invisible(c) || c == ',' {
|
||||
if c == '\n' {
|
||||
self.line += 1;
|
||||
self.col = 1;
|
||||
self.at_line_start = true;
|
||||
consecutive_newlines += 1;
|
||||
} else {
|
||||
self.col += 1;
|
||||
}
|
||||
self.input.next();
|
||||
} else if c == ';' || c == '#' {
|
||||
for c in self.input.by_ref() {
|
||||
if c == '\n' {
|
||||
} else if c == ';' {
|
||||
if !self.at_line_start {
|
||||
return Err(format!("Inline comments are not allowed at {}:{}", self.line, self.col));
|
||||
}
|
||||
if !self.comments_buffer.is_empty() && consecutive_newlines > 1 {
|
||||
for _ in 0..(consecutive_newlines - 1) {
|
||||
self.comments_buffer.push(Rc::from(""));
|
||||
}
|
||||
}
|
||||
consecutive_newlines = 0;
|
||||
|
||||
self.input.next(); // consume ';'
|
||||
self.col += 1;
|
||||
|
||||
if let Some(&' ') = self.peek() {
|
||||
self.input.next();
|
||||
self.col += 1;
|
||||
}
|
||||
|
||||
let mut comment_text = String::new();
|
||||
while let Some(&cc) = self.peek() {
|
||||
if cc == '\n' {
|
||||
break;
|
||||
}
|
||||
comment_text.push(self.input.next().unwrap());
|
||||
self.col += 1;
|
||||
}
|
||||
self.comments_buffer.push(Rc::from(comment_text));
|
||||
} else if c == '#' {
|
||||
if !self.at_line_start {
|
||||
return Err(format!("Inline directives are not allowed at {}:{}", self.line, self.col));
|
||||
}
|
||||
for cc in self.input.by_ref() {
|
||||
if cc == '\n' {
|
||||
self.line += 1;
|
||||
self.col = 1;
|
||||
self.at_line_start = true;
|
||||
consecutive_newlines += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.at_line_start = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_while<F>(&mut self, mut predicate: F) -> String
|
||||
|
||||
@@ -250,6 +250,7 @@ pub struct Node<P: CompilerPhase = BoundPhase> {
|
||||
pub identity: Identity,
|
||||
pub kind: NodeKind<P>,
|
||||
pub ty: P::Metadata,
|
||||
pub comments: Rc<[Rc<str>]>,
|
||||
}
|
||||
|
||||
impl<P: CompilerPhase> Clone for Node<P> {
|
||||
@@ -258,6 +259,7 @@ impl<P: CompilerPhase> Clone for Node<P> {
|
||||
identity: self.identity.clone(),
|
||||
kind: self.kind.clone(),
|
||||
ty: self.ty.clone(),
|
||||
comments: self.comments.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-7
@@ -21,6 +21,7 @@ impl<'a> Parser<'a> {
|
||||
Token {
|
||||
kind: TokenKind::EOF,
|
||||
location: SourceLocation { line: 1, col: 1 },
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -40,6 +41,7 @@ impl<'a> Parser<'a> {
|
||||
Token {
|
||||
kind: TokenKind::EOF,
|
||||
location: self.current_token.location,
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -59,7 +61,7 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::LeftBracket => self.parse_vector_literal(),
|
||||
TokenKind::LeftBrace => self.parse_record_literal(),
|
||||
TokenKind::Quote => {
|
||||
self.advance(); // consume '
|
||||
let token = self.advance(); // consume '
|
||||
let expr = self.parse_expression();
|
||||
SyntaxNode {
|
||||
identity: identity.clone(),
|
||||
@@ -71,22 +73,25 @@ impl<'a> Parser<'a> {
|
||||
elements: vec![Rc::new(expr)],
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}),
|
||||
},
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
TokenKind::Backtick => {
|
||||
self.advance(); // consume `
|
||||
let token = self.advance(); // consume `
|
||||
let expr = self.parse_expression();
|
||||
SyntaxNode {
|
||||
identity,
|
||||
kind: SyntaxKind::Template(Rc::new(expr)),
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
TokenKind::Tilde => {
|
||||
self.advance(); // consume ~
|
||||
let token = self.advance(); // consume ~
|
||||
if *self.peek() == TokenKind::At {
|
||||
self.advance(); // consume @
|
||||
let expr = self.parse_expression();
|
||||
@@ -94,6 +99,7 @@ impl<'a> Parser<'a> {
|
||||
identity,
|
||||
kind: SyntaxKind::Splice(Rc::new(expr)),
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
} else {
|
||||
let expr = self.parse_expression();
|
||||
@@ -101,6 +107,7 @@ impl<'a> Parser<'a> {
|
||||
identity,
|
||||
kind: SyntaxKind::Placeholder(Rc::new(expr)),
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,12 +166,13 @@ impl<'a> Parser<'a> {
|
||||
identity,
|
||||
kind,
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_list(&mut self) -> SyntaxNode {
|
||||
let start_loc = self.advance().location; // consume '('
|
||||
let identity = NodeIdentity::new(start_loc);
|
||||
let token = self.advance(); // consume '('
|
||||
let identity = NodeIdentity::new(token.location);
|
||||
|
||||
if *self.peek() == TokenKind::RightParen {
|
||||
self.diagnostics.push_error(
|
||||
@@ -176,12 +184,13 @@ impl<'a> Parser<'a> {
|
||||
identity,
|
||||
kind: SyntaxKind::Error,
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
};
|
||||
}
|
||||
|
||||
let head = self.parse_expression();
|
||||
|
||||
let node = if let SyntaxKind::Identifier { ref symbol, .. } = head.kind {
|
||||
let mut node = if let SyntaxKind::Identifier { ref symbol, .. } = head.kind {
|
||||
match symbol.name.as_ref() {
|
||||
"if" => self.parse_if(identity),
|
||||
"fn" => self.parse_fn(identity),
|
||||
@@ -197,6 +206,7 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
self.expect(TokenKind::RightParen);
|
||||
node.comments = token.comments;
|
||||
node
|
||||
}
|
||||
|
||||
@@ -211,6 +221,7 @@ impl<'a> Parser<'a> {
|
||||
identity: identity.clone(),
|
||||
kind: SyntaxKind::Tuple { elements },
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
};
|
||||
|
||||
SyntaxNode {
|
||||
@@ -219,6 +230,7 @@ impl<'a> Parser<'a> {
|
||||
args: Rc::new(args_node),
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,6 +251,7 @@ impl<'a> Parser<'a> {
|
||||
else_br,
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +267,7 @@ impl<'a> Parser<'a> {
|
||||
info: (),
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +284,7 @@ impl<'a> Parser<'a> {
|
||||
info: (),
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +297,7 @@ impl<'a> Parser<'a> {
|
||||
identity,
|
||||
kind: SyntaxKind::Block { exprs },
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,6 +313,7 @@ impl<'a> Parser<'a> {
|
||||
info: (),
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +339,7 @@ impl<'a> Parser<'a> {
|
||||
body: Rc::new(body),
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,6 +356,7 @@ impl<'a> Parser<'a> {
|
||||
identity: NodeIdentity::new(self.current_token.location),
|
||||
kind: SyntaxKind::Error,
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
};
|
||||
}
|
||||
self.parse_pattern()
|
||||
@@ -359,6 +378,7 @@ impl<'a> Parser<'a> {
|
||||
binding: (),
|
||||
},
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
TokenKind::LeftBracket => {
|
||||
@@ -375,6 +395,7 @@ impl<'a> Parser<'a> {
|
||||
identity,
|
||||
kind: SyntaxKind::Tuple { elements },
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
TokenKind::Tilde => {
|
||||
@@ -386,6 +407,7 @@ impl<'a> Parser<'a> {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: SyntaxKind::Splice(Rc::new(expr)),
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
} else {
|
||||
let expr = self.parse_expression();
|
||||
@@ -393,6 +415,7 @@ impl<'a> Parser<'a> {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: SyntaxKind::Placeholder(Rc::new(expr)),
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,11 +427,12 @@ impl<'a> Parser<'a> {
|
||||
),
|
||||
Some(NodeIdentity::new(self.current_token.location)),
|
||||
);
|
||||
self.advance();
|
||||
let token = self.advance();
|
||||
SyntaxNode {
|
||||
identity: NodeIdentity::new(self.current_token.location),
|
||||
kind: SyntaxKind::Error,
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -426,6 +450,7 @@ impl<'a> Parser<'a> {
|
||||
identity: identity.clone(),
|
||||
kind: SyntaxKind::Tuple { elements },
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
};
|
||||
|
||||
SyntaxNode {
|
||||
@@ -435,6 +460,7 @@ impl<'a> Parser<'a> {
|
||||
args: Rc::new(args_node),
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,6 +479,7 @@ impl<'a> Parser<'a> {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: SyntaxKind::Tuple { elements },
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,6 +522,7 @@ impl<'a> Parser<'a> {
|
||||
layout: (),
|
||||
},
|
||||
ty: (),
|
||||
comments: token.comments,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,6 +539,7 @@ impl<'a> Parser<'a> {
|
||||
Token {
|
||||
kind,
|
||||
location: self.current_token.location,
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -523,6 +552,7 @@ impl<'a> Parser<'a> {
|
||||
binding: (),
|
||||
},
|
||||
ty: (),
|
||||
comments: Rc::from([]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user