add support for 'if else', change hex escapes to '\ab'

This commit is contained in:
2022-05-06 09:03:13 +02:00
parent 4cfc7ae8a8
commit 1e746be750
2 changed files with 42 additions and 35 deletions

View File

@@ -5,11 +5,20 @@ import "env.printChar" fn printChar(i32);
export fn upd() { export fn upd() {
printChar(12); printChar(12);
printChar('Test'); printChar('Test');
printChar('\x1f\x10\x10'); printChar('\1f\10\10');
printChar('abc\n'); printChar('abc\n');
printString(0); printString(0);
let t = 32!32 / 1000 #% 3;
if t == 0 {
printChar('one');
} else if t == 1 {
printChar('two');
} else {
printChar('many');
}
} }
data 0 { data 0 {
"\x0e\x64\"Colors!!!\"\x0e\1\0" "\0e\64\"Colors!!!\"\0e\1\r\n\0"
} }

View File

@@ -310,7 +310,10 @@ fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = LexerError> {
let s = parse_string_escapes(s); let s = parse_string_escapes(s);
let mut value = 0; let mut value = 0;
for (i, c) in s.chars().enumerate() { for (i, c) in s.chars().enumerate() {
value |= (c as u32) << (i * 8); // TODO: generate error on overflow
if i < 4 {
value |= (c as u32) << (i * 8);
}
} }
Token::Int(value as i32) Token::Int(value as i32)
}); });
@@ -397,37 +400,22 @@ fn map_token<O>(
fn parse_string_escapes(s: String) -> String { fn parse_string_escapes(s: String) -> String {
let mut result = String::new(); let mut result = String::new();
let mut chars = s.chars(); let mut chars = s.chars().peekable();
while let Some(c) = chars.next() { while let Some(c) = chars.next() {
if c != '\\' { if c != '\\' {
result.push(c); result.push(c);
} else if let Some(c) = chars.next() { } else if let Some(c) = chars.next() {
match c { match c {
'0' => result.push('\0'), '0'..='9' | 'a'..='f' | 'A'..='F' => {
let mut number = c.to_string();
if let Some('0'..='9' | 'a' ..= 'f' | 'A'..='F') = chars.peek() {
number.push(chars.next().unwrap());
}
result.push(u8::from_str_radix(&number, 16).unwrap() as char);
},
'n' => result.push('\n'), 'n' => result.push('\n'),
'r' => result.push('\r'), 'r' => result.push('\r'),
't' => result.push('\t'), 't' => result.push('\t'),
'x' => {
if let Some(high) = chars.next() {
if let Some(low) = chars.next() {
if let Ok(c) = u8::from_str_radix(&format!("{}{}", high, low), 16) {
result.push(c as char);
} else {
result.push('\\');
result.push('x');
result.push(high);
result.push(low);
}
} else {
result.push('\\');
result.push('x');
result.push(high);
}
} else {
result.push('\\');
result.push('x');
}
}
other => result.push(other), other => result.push(other),
} }
} else { } else {
@@ -514,15 +502,25 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
block: Box::new(block), block: Box::new(block),
}); });
let if_expr = just(Token::If) let if_expr = recursive::<_, ast::Expr, _, _, _>(|if_expr| {
.ignore_then(expression.clone()) just(Token::If)
.then(block.clone()) .ignore_then(expression.clone())
.then(just(Token::Else).ignore_then(block.clone()).or_not()) .then(block.clone())
.map(|((condition, if_true), if_false)| ast::Expr::If { .then(
condition: Box::new(condition), just(Token::Else)
if_true: Box::new(if_true), .ignore_then(
if_false: if_false.map(Box::new), block
}); .clone()
.or(if_expr.map_with_span(|expr, span| expr.with_span(span))),
)
.or_not(),
)
.map(|((condition, if_true), if_false)| ast::Expr::If {
condition: Box::new(condition),
if_true: Box::new(if_true),
if_false: if_false.map(Box::new),
})
});
let block_expr = loop_expr.or(label_block_expr).or(if_expr).boxed(); let block_expr = loop_expr.or(label_block_expr).or(if_expr).boxed();