[Compiler] Fix error in val/var error messages when the offending token is a string

master
Araozu 2023-03-28 09:53:26 -05:00
parent d7bddfd549
commit 8a72b9308d
5 changed files with 113 additions and 44 deletions

View File

@ -25,7 +25,9 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult>
} }
}; };
// var/val keyword /*
* val/var keyword
*/
let (is_val, binding_token) = { let (is_val, binding_token) = {
let res1 = try_token_type(tokens, pos, TokenType::VAL); let res1 = try_token_type(tokens, pos, TokenType::VAL);
match res1 { match res1 {
@ -42,6 +44,9 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult>
} }
}; };
/*
* identifier
*/
let identifier = match try_token_type(tokens, pos + 1, TokenType::Identifier) { let identifier = match try_token_type(tokens, pos + 1, TokenType::Identifier) {
Result3::Ok(t) => t, Result3::Ok(t) => t,
Result3::Err(t) => { Result3::Err(t) => {
@ -52,11 +57,10 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult>
if is_val { "val" } else { "var" } if is_val { "val" } else { "var" }
), ),
error_start: t.position, error_start: t.position,
error_end: t.position + t.value.len(), error_end: t.get_end_position(),
})); }));
} }
Result3::None => { Result3::None => {
// TODO: Differentiate between no token found and incorrect token found.
// The parser didn't find an Identifier after VAL/VAR // The parser didn't find an Identifier after VAL/VAR
return Some(SyntaxResult::Err(SyntaxError { return Some(SyntaxResult::Err(SyntaxError {
reason: format!( reason: format!(
@ -64,29 +68,30 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult>
if is_val { "val" } else { "var" } if is_val { "val" } else { "var" }
), ),
error_start: binding_token.position, error_start: binding_token.position,
error_end: binding_token.position + binding_token.value.len(), error_end: binding_token.get_end_position(),
})); }));
} }
}; };
/*
* Equal (=) operator
*/
let _equal_operator: &Token = match try_operator(tokens, pos + 2, String::from("=")) { let _equal_operator: &Token = match try_operator(tokens, pos + 2, String::from("=")) {
Result3::Ok(t) => t, Result3::Ok(t) => t,
Result3::Err(t) => { Result3::Err(t) => {
// TODO: Differentiate between no token found and incorrect token found. // The parser found a token, but it's not the `=` operator
// The parser didn't find the `=` operator after the identifier
return Some(SyntaxResult::Err(SyntaxError { return Some(SyntaxResult::Err(SyntaxError {
reason: format!("There should be an equal sign `=` after the identifier",), reason: format!("There should be an equal sign `=` after the identifier"),
error_start: identifier.position, error_start: t.position,
error_end: identifier.position + identifier.value.len(), error_end: t.get_end_position(),
})); }));
} }
Result3::None => { Result3::None => {
// TODO: Differentiate between no token found and incorrect token found.
// The parser didn't find the `=` operator after the identifier // The parser didn't find the `=` operator after the identifier
return Some(SyntaxResult::Err(SyntaxError { return Some(SyntaxResult::Err(SyntaxError {
reason: format!("There should be an equal sign `=` after the identifier",), reason: format!("There should be an equal sign `=` after the identifier",),
error_start: identifier.position, error_start: identifier.position,
error_end: identifier.position + identifier.value.len(), error_end: identifier.get_end_position(),
})); }));
} }
}; };
@ -128,6 +133,7 @@ fn try_token_type(tokens: &Vec<Token>, pos: usize, token_type: TokenType) -> Res
fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result3<&Token> { fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result3<&Token> {
match tokens.get(pos) { match tokens.get(pos) {
Some(t) if t.token_type == TokenType::Operator && t.value == operator => Result3::Ok(t), Some(t) if t.token_type == TokenType::Operator && t.value == operator => Result3::Ok(t),
Some(t) if t.token_type == TokenType::Semicolon || t.token_type == TokenType::EOF => Result3::None,
Some(t) => Result3::Err(t), Some(t) => Result3::Err(t),
None => Result3::None, None => Result3::None,
} }
@ -233,7 +239,6 @@ mod tests {
} }
// ERROR: when computing the length of the token "hello" the quotes are not considered
let tokens = get_tokens(&String::from("val \"hello\"")).unwrap(); let tokens = get_tokens(&String::from("val \"hello\"")).unwrap();
let binding = try_parse(&tokens, 0).unwrap(); let binding = try_parse(&tokens, 0).unwrap();
@ -245,4 +250,18 @@ mod tests {
_ => panic!("Error expected") _ => panic!("Error expected")
} }
} }
#[test]
fn should_return_error_when_equal_op_is_wrong() {
let tokens = get_tokens(&String::from("val id \"error\"")).unwrap();
let binding = try_parse(&tokens, 0).unwrap();
match binding {
SyntaxResult::Err(error) => {
assert_eq!(7, error.error_start);
assert_eq!(14, error.error_end);
}
_ => panic!("Error expected")
}
}
} }

View File

@ -26,6 +26,19 @@ pub struct Token {
pub position: usize, pub position: usize,
} }
impl Token {
pub fn get_end_position(&self) -> usize {
match self.token_type {
TokenType::String => {
self.position + self.value.len() + 2
}
_ => {
self.position + self.value.len()
}
}
}
}
pub fn new_eof(position: usize) -> Token { pub fn new_eof(position: usize) -> Token {
Token { Token {
token_type: TokenType::EOF, token_type: TokenType::EOF,

View File

@ -12,53 +12,74 @@
<!-- Google fonts - Inter --> <!-- Google fonts - Inter -->
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;300;400;500;700&display=swap" rel="stylesheet">
<style> <style>
html { #transition {
font-size: 20px; width: 100%;
} height: 2vh;
:root {
--js-color: #FFE70B;
--dark-color: #0f0f0f;
}
body ::selection {
background-color: var(--js-color); background-color: var(--js-color);
color: var(--dark-color);
}
@media (prefers-color-scheme: light) {
body ::selection {
color: var(--js-color);
background-color: var(--dark-color);
}
} }
</style> </style>
</head> </head>
<body > <body >
<div class="text-center"> <!--
<div class="py-12 flex justify-center"> <div class="py-6 pt-12 flex justify-center">
<img src="/svg/logo_color.svg" alt="Misti logo" height="200" /> <img src="/svg/logo_color.svg" alt="Misti logo" height="200" />
</div> </div>
-->
<h2 class="text-xl px-2"> <div id="greeter" style="background-color: black; color: var(--js-color); min-height: 100vh;">
<b>A type-safe, consistent, compiled language for JS</b>
<h2 class="text-6xl px-4 py-6 font-bold leading-snug">
Typed.
<br>
Expressive.
<br>
Consistent.
<br>
Friendly.
</h2> </h2>
<p class="p-4" style="color: #ffdf90;">
Misti is <i>yet another</i> programming language that compiles to <b>JavaScript</b>.
</p>
<!-- Demo code --> <!-- Demo code -->
<div class="px-4"> <div class="px-4 py-4">
<!-- TODO: add colors from variables --> <a class="inline-block py-4 px-12 my-1 border-2 border-c5-primary
<a class="inline-block py-1 px-4 my-1 mx-2 border-js-color bg-bg-color text-main-color hover:text-dark-color hover:bg-js-color border-2 rounded-full cursor-pointer select-none"> bg-js-color
Learn text-dark-color
rounded-xl cursor-pointer select-none font-medium shadow-md hover:shadow-2xl"
href="/en/docs/latest/"
>
Get started
</a> </a>
<a class="inline-block py-1 px-4 my-1 mx-2 border-js-color bg-bg-color text-main-color hover:text-dark-color hover:bg-js-color border-2 rounded-full cursor-pointer select-none"> <br>
<a class="inline-block py-4 px-12 my-1 border-2 border-c2-primary
bg-c2-primary-container hover:bg-c2-primary
text-c2-on-primary-container hover:text-c2-on-primary
rounded-xl cursor-pointer select-none transition-colors"
href="/en/api/latest/"
>
API API
</a> </a>
</div> </div>
</div> </div>
<div id="transition"></div>
<script>
// Inter - Google fonts - load here as to not interrupt the page
const linkEl = document.createElement("link");
linkEl.href = "https://fonts.googleapis.com/css2?family=Inter:wght@100;300;400;500;700&display=swap";
linkEl.rel = "stylesheet";
document.head.appendChild(linkEl);
</script>
</body> </body>
</html> </html>

View File

@ -29,6 +29,9 @@ body ::selection {
/* C2 Material Colors */ /* C2 Material Colors */
--c2-primary: #90ccff; --c2-primary: #90ccff;
--c2-on-primary: #003351;
--c2-primary-container: #004b72;
--c2-on-primary-container: #cce5ff;
/* C3 Material Colors */ /* C3 Material Colors */
--c3-primary: #ffaed7; --c3-primary: #ffaed7;
@ -64,6 +67,9 @@ body ::selection {
/* C2 Material Colors */ /* C2 Material Colors */
--c2-primary: #006397; --c2-primary: #006397;
--c2-on-primary: #ffffff;
--c2-primary-container: #cce5ff;
--c2-on-primary-container: #001e31;
/* C3 Material Colors */ /* C3 Material Colors */
--c3-primary: #954170; --c3-primary: #954170;

View File

@ -5,6 +5,7 @@ module.exports = {
colors: { colors: {
transparent: 'transparent', transparent: 'transparent',
current: 'currentColor', current: 'currentColor',
white: "#ffffff",
"js-color": "var(--js-color)", "js-color": "var(--js-color)",
"dark-color": "var(--dark-color)", "dark-color": "var(--dark-color)",
@ -22,8 +23,14 @@ module.exports = {
"code-bg-color": "var(--code-bg-color)", "code-bg-color": "var(--code-bg-color)",
"code-color": "var(--code-color)", "code-color": "var(--code-color)",
"border-color": "var(--border-color)", "border-color": "var(--border-color)",
"c1-primary": "var(--c1-primary)", "c1-primary": "var(--c1-primary)",
"c2-primary": "var(--c2-primary)", "c2-primary": "var(--c2-primary)",
"c2-on-primary": "var(--c2-on-primary)",
"c2-primary-container": "var(--c2-primary-container)",
"c2-on-primary-container": "var(--c2-on-primary-container)",
"c3-primary": "var(--c3-primary)", "c3-primary": "var(--c3-primary)",
"c3-on-primary": "var(--c3-on-primary)", "c3-on-primary": "var(--c3-on-primary)",
"c3-primary-container": "var(--c3-primary-container)", "c3-primary-container": "var(--c3-primary-container)",
@ -35,6 +42,9 @@ module.exports = {
"c5-on-primary-container": "var(--c5-on-primary-container)", "c5-on-primary-container": "var(--c5-on-primary-container)",
"bg-color": "var(--bg-color)", "bg-color": "var(--bg-color)",
}, },
borderWidth: {
'1': '1px'
},
extend: {}, extend: {},
}, },
plugins: [], plugins: [],