string literal.

main
bog 2024-03-01 17:06:10 +01:00
parent efdbafb645
commit a0b8cda00d
6 changed files with 100 additions and 2 deletions

View File

@ -1,4 +1,8 @@
MODULE ::= INSTR*
INSTR ::= EXPR semicolon
EXPR ::= BUILTIN
BUILTIN ::= bool | float | int
BUILTIN ::=
| bool
| float
| int
| string

View File

@ -53,6 +53,55 @@ impl Lexer {
false
}
fn scan_string(&mut self) -> Option<Token> {
let mut value : String;
let mut length = 1;
if let Some('"') = self.text.chars().nth(self.cursor) {
value = String::from("");
} else {
return None;
}
let mut escape = false;
let mut closed = false;
for c in self.text.chars().skip(length + self.cursor) {
if !escape && c == '\\' {
escape = true;
length += 1;
continue;
}
if escape {
match c {
'"' => value.push('"'),
'\\' => value.push('\\'),
'n' => value.push('\n'),
't' => value.push('\t'),
'r' => value.push('\r'),
_ => {}
}
} else if c == '"' {
closed = true;
break;
} else {
value.push(c);
}
escape = false;
length += 1;
}
if length >= 2 && closed {
return Some(Token {
position: 1 + self.cursor + length,
value
});
}
None
}
fn scan_int(&self) -> Option<Token> {
let mut value = String::from("");
@ -205,6 +254,11 @@ impl Iterator for Lexer {
return Some(Node::Semicolon);
}
if let Some(token) = self.scan_string() {
self.cursor = token.position;
return Some(Node::String(token.value.clone()));
}
if let Some(token) = self.scan_float() {
if let Ok(val) = token.value.parse::<f64>() {
self.cursor = token.position;
@ -320,4 +374,18 @@ mod test {
Ok(())
}
#[test]
fn test_string() -> Result<(), error::AstError> {
let mut lex = Lexer::new();
let res = lexer_run(&mut lex,
" \"s\\ta\\\"lut\\n\" ")?;
assert_eq!(1, res.len());
assert_eq!(Node::String(String::from("s\ta\"lut\n")),
*res.get(0).unwrap());
Ok(())
}
}

View File

@ -5,6 +5,7 @@ pub enum Node {
Bool(bool),
Int(i32),
Float(f64),
String(String),
Semicolon
}

View File

@ -77,6 +77,9 @@ impl Parser {
Some(Node::Bool(value))
=> Ok(Some(Node::Bool(value))),
Some(Node::String(value))
=> Ok(Some(Node::String(value))),
Some(other) => {
Err(error::AstError {
msg: String::from(format!("unexpected {:?}", other)),
@ -164,4 +167,16 @@ mod test {
Ok(())
}
#[test]
fn strings() -> TestResult {
test_parser(
Node::Module("mod".to_owned(), vec![
Node::String(String::from("pizza! "))
]),
" \"pizza! \"; "
)?;
Ok(())
}
}

View File

@ -33,6 +33,7 @@ impl Evaluator {
Node::Bool(value) => Ok(Some(Value::Bool(*value))),
Node::Int(value) => Ok(Some(Value::Int(*value))),
Node::Float(value) => Ok(Some(Value::Float(*value))),
Node::String(value) => Ok(Some(Value::String(value.clone()))),
_ => Ok(None)
}
@ -94,4 +95,12 @@ mod test {
Ok(())
}
#[test]
fn strings() -> TestResult {
test_eval_value(Value::String(String::from(" pizzza!!!")),
" \" pizzza!!!\"; ")?;
Ok(())
}
}

View File

@ -3,6 +3,7 @@
pub enum Value {
Bool(bool),
Int(i32),
Float(f64)
Float(f64),
String(String)
}