Compare commits

..

No commits in common. "dde1da8656ac70a9d577bfd7335b31114d606b37" and "872c8e356db86c9a3ee374b55eec58953ee56a9d" have entirely different histories.

12 changed files with 79 additions and 620 deletions

View file

@ -1,22 +0,0 @@
# Attribute errors
# Missing attribute name
@ 42
# Invalid attribute argument
@deprecated invalid
# Missing equals in key-value attribute
@version "1.0"
# Missing closing parenthesis in attribute
@deprecated("old", reason = "new"
# Invalid attribute syntax (missing value after =)
@version =
# Attribute on invalid location
fn test() -> int
@inline
let x = 5
x

View file

@ -1,50 +0,0 @@
# Bracket and parenthesis mismatch errors
# Missing closing parenthesis in function call
fn test() -> int do
let f = lambda(x) x
f(5
42
end
# Missing closing bracket in array access
fn test() -> int do
let arr = [1, 2, 3]
arr[0
42
end
struct Point
x: int,
y: int
end
# Missing closing brace in struct literal
fn test() -> int do
let p = Point { x: 5, y: 10
p.x
end
# Missing closing parenthesis in tuple
fn test() -> int do
let t = (1, 2, 3
42
end
# Missing closing angle bracket in generic
fn test() -> int do
let v = Vec<int
42
end
# Extra closing parenthesis
fn test() -> int do
let x = (5))
x
end
# Missing opening parenthesis in expression
fn test() -> int do
let x = 5 + 3)
x
end

View file

@ -1,44 +0,0 @@
# Control flow errors
# Missing condition in if
fn test() -> int
if
42
else
0
# Missing body in if
fn test() -> int
if true
else
0
# Missing variable in for loop
fn test() -> int
for in [1, 2, 3]
item
# Missing 'in' keyword in for loop
fn test() -> int
for item [1, 2, 3]
item
# Missing iterable in for loop
fn test() -> int
for item in
item
# Invalid while syntax
fn test() -> int
while
42
# Missing parameters in lambda
fn test() -> int
let f = lambda
42
# Missing closing parenthesis in lambda
fn test() -> int
let f = lambda(x
x

View file

@ -1,24 +0,0 @@
# Function syntax errors
# Missing function name
fn -> int
42
# Missing parameter type annotation
fn add(x, y: int) -> int
x + y
# Missing comma in parameters
fn add(x: int y: int) -> int
x + y
# Missing closing parenthesis
fn add(x: int, y: int -> int
x + y
# Missing return type arrow
fn add(x: int, y: int) int
x + y
# Invalid function body (missing expression)
fn test() -> int

View file

@ -1,44 +0,0 @@
# Pattern matching errors
struct Point
x: int,
y: int,
end
enum Result
Ok(int)
Err(string)
end
# Invalid pattern in match
fn test() -> int
match 42
x => x
end
# Missing colon in struct pattern
fn test() -> int do
let p = Point { x: 5, y: 10 }
match p
Point { x 5, y: 10 } => 1
end
end
# Invalid enum pattern
fn test() -> int do
let r = Result::Ok(42)
match r
Result::Ok value => value
end
end
# Missing pattern in match arm
fn test() -> int
match 42
=> 0
end
# Missing fat arrow in match arm
fn test() -> int
match 42
x 0
end

View file

@ -1,30 +0,0 @@
# Struct syntax errors
# Missing struct name
struct
x: int,
y: int
end
# Missing field type
struct Point
x
y: int
end
# Missing colon in field
struct Point
x int,
y: int
end
# Missing end keyword
struct Point
x: int,
y: int,
# Invalid field separator (semicolon instead of comma)
struct Point
x: int;
y: int
end

View file

@ -1,45 +0,0 @@
# Top-level declaration errors
# Invalid top-level token
invalid_token
# Incomplete use statement
use
# Missing path in use
use as alias
# Invalid use syntax
use "path" invalid
# Incomplete load statement
load
# Missing alias in load
load "lib"
# Invalid load syntax
load "lib" invalid alias
# Incomplete extern declaration
extern
# Missing return type in extern
extern add(x: int, y: int)
# Invalid extern syntax
extern add(x: int, y: int) -> int invalid
# Incomplete impl declaration
impl
# Missing methods in impl
impl MyType
end
# Incomplete trait declaration
trait
# Missing methods in trait
trait MyTrait
end

View file

@ -1,29 +0,0 @@
# Type annotation errors
# Invalid type name
fn test() -> invalidtype
42
# Missing closing bracket in array type
fn test() -> [int
[]
# Missing type parameter
fn test() -> Option
none
# Invalid generic syntax
fn test() -> Vec int
[]
# Missing closing angle bracket
fn test() -> HashMap<string, int
{}
# Invalid pointer syntax
fn test() -> *int
42
# Invalid function type syntax
fn test() -> fn int -> int
42

View file

@ -44,57 +44,6 @@ fn run_test_suite() {
}
}
fn format_parse_error(source: &str, error: &suicmez::parser::ParseError) -> String {
// Find the line containing the error
let lines: Vec<&str> = source.lines().collect();
let mut current_pos = 0;
for (line_idx, line) in lines.iter().enumerate() {
let line_start = current_pos;
let line_end = current_pos + line.len();
// Check if the error span intersects with this line
if error.span.start < line_end && error.span.end > line_start {
let mut result = String::new();
// Print the error message
result.push_str(&format!("Parse error: {}\n", error.message));
// Print the line number and content
result.push_str(&format!("{} | {}\n", line_idx + 1, line));
// Calculate column positions within the line
let line_start_col = error.span.start.saturating_sub(line_start);
let line_end_col = (error.span.end - line_start).min(line.len());
// Print spaces and squiggly line for the span
result.push_str(&format!("{} | ", " ".repeat((line_idx + 1).to_string().len())));
for _ in 0..line_start_col {
result.push(' ');
}
for _ in line_start_col..line_end_col {
result.push('~');
}
result.push('\n');
// Print caret at the start position
result.push_str(&format!("{} | ", " ".repeat((line_idx + 1).to_string().len())));
for _ in 0..line_start_col {
result.push(' ');
}
result.push('^');
return result;
}
current_pos = line_end + 1; // +1 for the newline character
}
// Fallback if we can't find the line
format!("Parse error: {} (at byte {})", error.message, error.span.start)
}
fn run_file(filename: &str) -> Result<(), String> {
// Read the source file
let source = fs::read_to_string(filename)
@ -120,7 +69,7 @@ fn run_file(filename: &str) -> Result<(), String> {
let mut parser = Parser::new(filename.to_string(), tokens);
let ast_nodes = parser
.parse()
.map_err(|e| format_parse_error(&source, &e))?;
.map_err(|e| format!("Parse error: {}", e.message))?;
println!("Parsed {} AST nodes successfully", ast_nodes.len());

View file

@ -57,52 +57,16 @@ impl Parser {
Ok(span)
}
Some((token, span)) => Err(ParseError {
message: self.expect_error_message(&expected, &token),
message: format!("Expected {:?}, found {:?}", expected, token),
span: Span::new(&span, self.file.clone()),
}),
None => Err(ParseError {
message: self.expect_error_message(&expected, &Token::Variable("EOF".to_string())),
message: format!("Expected {:?}, found EOF", expected),
span: Span::new(&(0..0), self.file.clone()),
}),
}
}
fn expect_error_message(&self, expected: &Token, found: &Token) -> String {
match expected {
Token::LParen => format!(
"Expected '(' to start parameter list or grouping. Found {:?}",
found
),
Token::RParen => format!(
"Expected ')' to close parameter list or grouping. Found {:?}",
found
),
Token::LBrace => format!(
"Expected '{{' to start block or struct literal. Found {:?}",
found
),
Token::RBrace => format!(
"Expected '}}' to close block or struct literal. Found {:?}",
found
),
Token::LBracket => format!("Expected '[' to start array literal. Found {:?}", found),
Token::RBracket => format!("Expected ']' to close array literal. Found {:?}", found),
Token::Colon => format!(
"Expected ':' for type annotation or struct field. Found {:?}",
found
),
Token::Semicolon => format!("Expected ';' to end statement. Found {:?}", found),
Token::Comma => format!("Expected ',' to separate items. Found {:?}", found),
Token::Arrow => format!("Expected '->' for function return type. Found {:?}", found),
Token::Assign => format!(
"Expected '=' for assignment or initialization. Found {:?}",
found
),
Token::KeywordEnd => format!("Expected 'end' to close block. Found {:?}", found),
_ => format!("Expected {:?}, found {:?}", expected, found),
}
}
fn error<T>(&self, msg: String, span: Range<usize>) -> Result<T, ParseError> {
Err(ParseError {
message: msg,
@ -126,10 +90,10 @@ impl Parser {
let path = match self.next() {
Some((Token::String(s), _)) => s,
Some((_, span)) => {
return self.error("Expected library path after 'use'. Example: use \"std/io\"".to_string(), span);
return self.error("Expected string after 'use'".to_string(), span);
}
None => {
return self.error("Expected library path after 'use'. Example: use \"std/io\"".to_string(), start..start);
return self.error("Expected string after 'use'".to_string(), start..start);
}
};
let end = self.peek_span().unwrap_or(start..start).end;
@ -211,9 +175,9 @@ impl Parser {
}
Some(token) => {
let span = self.peek_span().unwrap_or(start..start);
self.error(format!("Unexpected token at top level: {:?}. Expected declarations like 'fn', 'struct', 'enum', 'impl', 'trait', 'use', 'load', or 'extern'", token), span)
self.error(format!("Unexpected token at top level: {:?}", token), span)
}
None => self.error("Unexpected end of file at top level. Expected declarations like 'fn', 'struct', 'enum', etc.".to_string(), start..start),
None => self.error("Unexpected EOF".to_string(), start..start),
}
}
@ -222,18 +186,8 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let name = match self.next() {
Some((Token::Variable(name), _)) => name,
Some((_, span)) => {
return self.error(
"Expected attribute name after '@'. Example: @deprecated".to_string(),
span,
);
}
None => {
return self.error(
"Expected attribute name after '@'. Example: @deprecated".to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected attribute name".to_string(), span),
None => return self.error("Expected attribute name".to_string(), start..start),
};
// Parentheses are optional
@ -261,11 +215,11 @@ impl Parser {
args.push(AttributeArg::KeyValue(id, val))
}
Some((_, span)) => {
return self.error("Expected attribute value after '='. Example: @version = \"1.0\"".to_string(), span);
return self.error("Expected value after =".to_string(), span);
}
None => {
return self
.error("Expected attribute value after '='. Example: @version = \"1.0\"".to_string(), start..start);
.error("Expected value after =".to_string(), start..start);
}
}
} else {
@ -278,7 +232,7 @@ impl Parser {
.error(format!("Unexpected token in attribute: {:?}", token), span);
}
None => {
return self.error("Expected attribute argument. Examples: \"value\", key = \"value\", or just key".to_string(), start..start);
return self.error("Expected attribute argument".to_string(), start..start);
}
}
let next_token = self.peek().cloned();
@ -289,7 +243,7 @@ impl Parser {
} else {
{
let span = self.peek_span().unwrap_or(start..start);
return self.error("Expected ',' to separate arguments or ')' to close attribute. Example: @deprecated(\"old\", reason = \"use new\")".to_string(), span);
return self.error("Expected , or )".to_string(), span);
}
}
}
@ -306,8 +260,8 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => return self.error("Expected function name after 'fn' keyword. Example: fn add(x: int, y: int) -> int x + y".to_string(), span),
None => return self.error("Expected function name after 'fn' keyword. Example: fn add(x: int, y: int) -> int x + y ".to_string(), start..start),
Some((_, span)) => return self.error("Expected function name".to_string(), span),
None => return self.error("Expected function name".to_string(), start..start),
};
// Parse type parameters if present
@ -329,20 +283,8 @@ impl Parser {
let arg_name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => {
return self.error(
"Expected argument name. Arguments should be like: x: int, y: int"
.to_string(),
span,
);
}
None => {
return self.error(
"Expected argument name. Arguments should be like: x: int, y: int"
.to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected argument name".to_string(), span),
None => return self.error("Expected argument name".to_string(), start..start),
};
let arg_type = if matches!(self.peek(), Some(Token::Colon)) {
@ -358,7 +300,7 @@ impl Parser {
self.next();
} else if !matches!(self.peek(), Some(Token::RParen)) {
let span = self.peek_span().unwrap_or(start..start);
return self.error("Expected ',' between arguments or ')' to close parameter list. Example: fn add(x: int, y: int)".to_string(), span);
return self.error("Expected , or )".to_string(), span);
}
}
@ -386,8 +328,8 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => return self.error("Expected struct name after 'struct' keyword. Example: struct Point { x: int, y: int }".to_string(), span),
None => return self.error("Expected struct name after 'struct' keyword. Example: struct Point { x: int, y: int }".to_string(), start..start),
Some((_, span)) => return self.error("Expected struct name".to_string(), span),
None => return self.error("Expected struct name".to_string(), start..start),
};
// Parse type parameters if present
@ -409,18 +351,8 @@ impl Parser {
let field_start = self.peek_span().unwrap_or(0..0).start;
let field_name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => {
return self.error(
"Expected field name. Fields should be like: name: string,".to_string(),
span,
);
}
None => {
return self.error(
"Expected field name. Fields should be like: name: string,".to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected field name".to_string(), span),
None => return self.error("Expected field name".to_string(), start..start),
};
self.expect(Token::Colon)?;
@ -449,16 +381,8 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => return self.error(
"Expected enum name after 'enum' keyword. Example: enum Color { Red(int), Green(int), Blue(int) }"
.to_string(),
span,
),
None => return self.error(
"Expected enum name after 'enum' keyword. Example: enum Color { Red(int), Green(int), Blue(int) }"
.to_string(),
start..start,
),
Some((_, span)) => return self.error("Expected enum name".to_string(), span),
None => return self.error("Expected enum name".to_string(), start..start),
};
// Parse type parameters if present
@ -480,20 +404,8 @@ impl Parser {
let variant_start = self.peek_span().unwrap_or(0..0).start;
let variant_name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => {
return self.error(
"Expected variant name. Variants should be like: Red, or Ok(T),"
.to_string(),
span,
);
}
None => {
return self.error(
"Expected variant name. Variants should be like: Red, or Ok(T),"
.to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected variant name".to_string(), span),
None => return self.error("Expected variant name".to_string(), start..start),
};
let mut fields = Vec::new();
@ -546,32 +458,23 @@ impl Parser {
TypeAnnot::Cons(name, _) => name,
_ => {
return self.error(
"Expected type name for impl target. Example: impl MyType { ... }".to_string(),
"Expected type name for impl target".to_string(),
start..start,
);
}
};
// Parse optional trait name
let trait_name =
if matches!(self.peek(), Some(Token::Colon)) {
self.next();
match self.next() {
Some((Token::Variable(n), _)) => Some(n),
Some((_, span)) => return self.error(
"Expected trait name after colon. Example: impl MyType : MyTrait { ... }"
.to_string(),
span,
),
None => return self.error(
"Expected trait name after colon. Example: impl MyType : MyTrait { ... }"
.to_string(),
start..start,
),
}
} else {
None
};
let trait_name = if matches!(self.peek(), Some(Token::Colon)) {
self.next();
match self.next() {
Some((Token::Variable(n), _)) => Some(n),
Some((_, span)) => return self.error("Expected trait name".to_string(), span),
None => return self.error("Expected trait name".to_string(), start..start),
}
} else {
None
};
// Parse methods
let mut methods = Vec::new();
@ -596,8 +499,8 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => return self.error("Expected trait name after 'trait' keyword. Example: trait Display { fn to_string() -> string; }".to_string(), span),
None => return self.error("Expected trait name after 'trait' keyword. Example: trait Display { fn to_string() -> string; }".to_string(), start..start),
Some((_, span)) => return self.error("Expected trait name".to_string(), span),
None => return self.error("Expected trait name".to_string(), start..start),
};
// Parse type parameters if present
@ -642,18 +545,8 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => {
return self.error(
"Expected function name after 'extern'. Example: extern add".to_string(),
span,
);
}
None => {
return self.error(
"Expected function name after 'extern'. Example: extern add".to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected extern name".to_string(), span),
None => return self.error("Expected extern name".to_string(), start..start),
};
// Parse argument types (with optional parameter names)
@ -680,16 +573,8 @@ impl Parser {
self.expect(Token::KeywordFrom)?;
let from = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => return self.error(
"Expected library name after 'from'. Example: extern add() -> int from \"libc\""
.to_string(),
span,
),
None => return self.error(
"Expected library name after 'from'. Example: extern add() -> int from \"libc\""
.to_string(),
start..start,
),
Some((_, span)) => return self.error("Expected library identifier".to_string(), span),
None => return self.error("Expected library identifier".to_string(), start..start),
};
let end = self.peek_span().unwrap_or(start..start).end;
@ -706,37 +591,15 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let library = match self.next() {
Some((Token::String(s), _)) => s,
Some((_, span)) => {
return self.error(
"Expected library name after 'load'. Example: load \"mylib\" as mylib"
.to_string(),
span,
);
}
None => {
return self.error(
"Expected library name after 'load'. Example: load \"mylib\" as mylib"
.to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected library name".to_string(), span),
None => return self.error("Expected library name".to_string(), start..start),
};
self.expect(Token::KeywordAs)?;
let alias = match self.next() {
Some((Token::Variable(a), _)) => a,
Some((_, span)) => {
return self.error(
"Expected alias after 'as'. Example: load \"mylib\" as mylib".to_string(),
span,
);
}
None => {
return self.error(
"Expected alias after 'as'. Example: load \"mylib\" as mylib".to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected alias".to_string(), span),
None => return self.error("Expected alias".to_string(), start..start),
};
let end = self.peek_span().unwrap_or(start..start).end;
@ -760,18 +623,8 @@ impl Parser {
let param_start = self.peek_span().unwrap_or(0..0).start;
let param_name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => {
return self.error(
"Expected type parameter name. Example: <T, U>".to_string(),
span,
);
}
None => {
return self.error(
"Expected type parameter name. Example: <T, U>".to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected parameter name".to_string(), span),
None => return self.error("Expected parameter name".to_string(), start..start),
};
let bounds = if matches!(self.peek(), Some(Token::Colon)) {
@ -809,18 +662,8 @@ impl Parser {
loop {
match self.next() {
Some((Token::Variable(n), _)) => bounds.push(n),
Some((_, span)) => {
return self.error(
"Expected trait name in bounds. Example: T: Clone + Debug".to_string(),
span,
);
}
None => {
return self.error(
"Expected trait name in bounds. Example: T: Clone + Debug".to_string(),
0..0,
);
}
Some((_, span)) => return self.error("Expected trait name".to_string(), span),
None => return self.error("Expected trait name".to_string(), 0..0),
}
if !matches!(self.peek(), Some(Token::Plus)) {
@ -916,20 +759,8 @@ impl Parser {
TypeAnnot::Array(Box::new(inner))
}
Some((Token::Bang, _)) => TypeAnnot::Cons("never".to_string(), vec![]),
Some((_, span)) => {
return self.error(
"Expected type name. Examples: int, string, bool, MyStruct, Option<int>"
.to_string(),
span,
);
}
None => {
return self.error(
"Expected type name. Examples: int, string, bool, MyStruct, Option<int>"
.to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected type name".to_string(), span),
None => return self.error("Expected type name".to_string(), start..start),
};
// Parse type arguments if present
@ -950,11 +781,7 @@ impl Parser {
base_type = match base_type {
TypeAnnot::Cons(name, _) => TypeAnnot::Cons(name, args),
_ => {
return self.error(
"Expected type name for generic. Example: Vec<int>, HashMap<string, int>"
.to_string(),
start..start,
);
return self.error("Expected type name for generic".to_string(), start..start);
}
};
}
@ -973,20 +800,8 @@ impl Parser {
let start = self.peek_span().unwrap_or(0..0).start;
let name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => {
return self.error(
"Expected function name in signature. Example: fn to_string() -> string"
.to_string(),
span,
);
}
None => {
return self.error(
"Expected function name in signature. Example: fn to_string() -> string"
.to_string(),
start..start,
);
}
Some((_, span)) => return self.error("Expected function name".to_string(), span),
None => return self.error("Expected function name".to_string(), start..start),
};
self.expect(Token::LParen)?;
@ -998,20 +813,11 @@ impl Parser {
}
let param_start = self.peek_span().unwrap_or(0..0).start;
let param_name =
match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => return self.error(
"Expected parameter name in trait method. Example: fn method(self, x: int)"
.to_string(),
span,
),
None => return self.error(
"Expected parameter name in trait method. Example: fn method(self, x: int)"
.to_string(),
start..start,
),
};
let param_name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => return self.error("Expected parameter name".to_string(), span),
None => return self.error("Expected parameter name".to_string(), start..start),
};
// Parameters in trait methods may have type annotations
if matches!(self.peek(), Some(Token::Colon)) {
@ -1325,7 +1131,7 @@ impl Parser {
let field = match self.next() {
Some((Token::Variable(f), _)) => f,
Some((_, span)) => {
return self.error("Expected field name in struct pattern. Example: Point { x: 5, y: 10 }".to_string(), span);
return self.error("Expected field name".to_string(), span);
}
None => return self.error("Expected field name".to_string(), start..start),
};
@ -1343,7 +1149,7 @@ impl Parser {
let field = match self.next() {
Some((Token::Variable(f), _)) => f,
Some((_, span)) => {
return self.error("Expected field name in struct pattern. Example: Point { x: 5, y: 10 }".to_string(), span);
return self.error("Expected field name".to_string(), span);
}
None => return self.error("Expected field name".to_string(), start..start),
};
@ -1440,7 +1246,7 @@ impl Parser {
let field_name = match self.next() {
Some((Token::Variable(f), _)) => f,
Some((_, span)) => {
return self.error("Expected field name in struct pattern. Example: Point { x: 5, y: 10 }".to_string(), span);
return self.error("Expected field name".to_string(), span);
}
None => {
return self.error("Expected field name".to_string(), start..start);
@ -1468,7 +1274,7 @@ impl Parser {
let variant = match self.next() {
Some((Token::Variable(v), _)) => v,
Some((_, span)) => {
return self.error("Expected variant name in enum pattern. Example: Result::Ok(value) or Color::Red()".to_string(), span);
return self.error("Expected variant name".to_string(), span);
}
None => {
return self.error("Expected variant name".to_string(), start..start);
@ -1597,9 +1403,9 @@ impl Parser {
let var_name = match self.next() {
Some((Token::Variable(n), _)) => n,
Some((_, span)) => {
return self.error("Expected variable name after 'let'. Example: let x = 5; or let mut y = 10;".to_string(), span);
return self.error("Expected variable name".to_string(), span);
}
None => return self.error("Expected variable name after 'let'. Example: let x = 5; or let mut y = 10;".to_string(), start..start),
None => return self.error("Expected variable name".to_string(), start..start),
};
// Parse optional type annotation
@ -1686,7 +1492,7 @@ impl Parser {
let var = match self.next() {
Some((Token::Variable(v), _)) => v,
Some((_, span)) => {
return self.error("Expected variable name in for loop. Example: for item in collection { ... }".to_string(), span);
return self.error("Expected variable name".to_string(), span);
}
None => return self.error("Expected variable name".to_string(), start..start),
};
@ -1739,7 +1545,7 @@ impl Parser {
let param_name = match self.next() {
Some((Token::Variable(p), _)) => p,
Some((_, span)) => {
return self.error("Expected parameter name in lambda. Example: lambda(x, y) { x + y }".to_string(), span);
return self.error("Expected parameter name".to_string(), span);
}
None => {
return self.error("Expected parameter name".to_string(), start..start);
@ -1809,12 +1615,9 @@ impl Parser {
}
Some(token) => {
let span = self.peek_span().unwrap_or(start..start);
self.error(format!("Unexpected token in pattern: {:?}. Expected variable names, struct patterns like Struct {{ field }}, or enum patterns like Enum::Variant", token), span)
self.error(format!("Unexpected token: {:?}", token), span)
}
None => self.error(
"Unexpected end of file in pattern. Expected a complete pattern.".to_string(),
start..start,
),
None => self.error("Unexpected EOF".to_string(), start..start),
}
}
@ -1841,7 +1644,7 @@ impl Parser {
let field_name = match self.next() {
Some((Token::Variable(f), _)) => f,
Some((_, span)) => {
return self.error("Expected field name in struct pattern. Example: Point { x: 5, y: 10 }".to_string(), span);
return self.error("Expected field name".to_string(), span);
}
None => {
return self.error("Expected field name".to_string(), start..start);
@ -1868,7 +1671,7 @@ impl Parser {
let variant = match self.next() {
Some((Token::Variable(v), _)) => v,
Some((_, span)) => {
return self.error("Expected variant name in enum pattern. Example: Result::Ok(value) or Color::Red()".to_string(), span);
return self.error("Expected variant name".to_string(), span);
}
None => {
return self.error("Expected variant name".to_string(), start..start);
@ -1966,12 +1769,9 @@ impl Parser {
}
Some(token) => {
let span = self.peek_span().unwrap_or(start..start);
self.error(format!("Unexpected token in expression: {:?}. Expected literals, variables, or keywords like 'let', 'if', etc.", token), span)
self.error(format!("Unexpected token in pattern: {:?}", token), span)
}
None => self.error(
"Unexpected end of file in expression. Expected a complete expression.".to_string(),
start..start,
),
None => self.error("Unexpected EOF".to_string(), start..start),
}
}

View file

@ -1629,7 +1629,9 @@ impl TypeChecker {
TypeAnnot::Array(inner) => {
Type::Array(Box::new(self.substitute_type(inner, subst_map)))
}
TypeAnnot::Ptr(inner) => Type::Ptr(Box::new(self.substitute_type(inner, subst_map))),
TypeAnnot::Ptr(inner) => {
Type::Ptr(Box::new(self.substitute_type(inner, subst_map)))
}
TypeAnnot::Tuple(types) => {
let substituted_types: Vec<Type> = types
.iter()

View file

@ -1,11 +1,7 @@
fn test_scoping() -> int do
let x = 5
let f = lambda (y) y + 1 # simple lambda
# f = lambda (z) z+1
f = lambda (z) z+1
let x = 10 # shadow x
f(3) # should work
end
fn stuff(f: fn(int, int) -> int, v: int) -> int do
f(v, v)
end