support for date literals
This commit is contained in:
parent
c64fa00611
commit
3feadcce19
6 changed files with 70 additions and 32 deletions
|
|
@ -1,14 +1,12 @@
|
||||||
use crate::ast_compiler::Expression::{
|
use crate::ast_compiler::Expression::{FunctionCall, NamedParameter, Stop, Variable};
|
||||||
FunctionCall, NamedParameter, Stop, Variable,
|
|
||||||
};
|
|
||||||
use crate::errors::CompilerError::{
|
use crate::errors::CompilerError::{
|
||||||
self, Expected, IncompatibleTypes, ParseError, TooManyParameters, TypeError,
|
self, Expected, IncompatibleTypes, ParseError, TooManyParameters, TypeError,
|
||||||
UndeclaredVariable, UnexpectedIndent, UninitializedVariable,
|
UndeclaredVariable, UnexpectedIndent, UninitializedVariable,
|
||||||
};
|
};
|
||||||
use crate::errors::CompilerErrorAtLine;
|
use crate::errors::CompilerErrorAtLine;
|
||||||
use crate::tokens::TokenType::{
|
use crate::tokens::TokenType::{
|
||||||
Bang, Bool, Char, Colon, Date, Dot, Eof, Eol, Equal, F32, F64, False, FloatingPoint, Fn,
|
Bang, Bool, Char, Colon, Date, DateTime, Dot, Eof, Eol, Equal, F32, F64, False, FloatingPoint,
|
||||||
Greater, GreaterEqual, GreaterGreater, I32, I64, Identifier, Indent, Integer, LeftBrace,
|
Fn, Greater, GreaterEqual, GreaterGreater, I32, I64, Identifier, Indent, Integer, LeftBrace,
|
||||||
LeftBracket, LeftParen, Less, LessEqual, LessLess, Let, ListType, MapType, Minus, Object, Plus,
|
LeftBracket, LeftParen, Less, LessEqual, LessLess, Let, ListType, MapType, Minus, Object, Plus,
|
||||||
Print, RightBrace, RightBracket, RightParen, SignedInteger, SingleRightArrow, Slash, Star,
|
Print, RightBrace, RightBracket, RightParen, SignedInteger, SingleRightArrow, Slash, Star,
|
||||||
StringType, True, U32, U64, UnsignedInteger,
|
StringType, True, U32, U64, UnsignedInteger,
|
||||||
|
|
@ -469,7 +467,7 @@ impl AstCompiler {
|
||||||
Expression::Literal {
|
Expression::Literal {
|
||||||
line: self.peek().line,
|
line: self.peek().line,
|
||||||
literaltype: StringType,
|
literaltype: StringType,
|
||||||
value: Value::String(self.previous().lexeme.to_string()),
|
value: Value::String(self.previous().lexeme.clone()),
|
||||||
}
|
}
|
||||||
} else if self.match_token(vec![Char]) {
|
} else if self.match_token(vec![Char]) {
|
||||||
Expression::Literal {
|
Expression::Literal {
|
||||||
|
|
@ -477,6 +475,19 @@ impl AstCompiler {
|
||||||
literaltype: Char,
|
literaltype: Char,
|
||||||
value: Value::Char(self.previous().lexeme.chars().next().unwrap()),
|
value: Value::Char(self.previous().lexeme.chars().next().unwrap()),
|
||||||
}
|
}
|
||||||
|
} else if self.match_token(vec![DateTime]) {
|
||||||
|
Expression::Literal {
|
||||||
|
line: self.peek().line,
|
||||||
|
literaltype: DateTime,
|
||||||
|
value: Value::DateTime(
|
||||||
|
chrono::DateTime::parse_from_str(
|
||||||
|
&self.previous().lexeme,
|
||||||
|
"%Y-%m-%d %H:%M:%S%.3f %z",
|
||||||
|
)
|
||||||
|
.map_err(|e| self.raise(ParseError(self.previous().lexeme.clone())))?
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
}
|
||||||
} else if self.match_token(vec![LeftParen]) {
|
} else if self.match_token(vec![LeftParen]) {
|
||||||
let expr = self.expression()?;
|
let expr = self.expression()?;
|
||||||
self.consume(RightParen, Expected("')' after expression."))?;
|
self.consume(RightParen, Expected("')' after expression."))?;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{compile, run};
|
use crate::{compile, run};
|
||||||
|
use chrono::{DateTime, FixedOffset, NaiveDate, TimeZone};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_int() {
|
fn literal_int() {
|
||||||
|
|
@ -118,20 +119,20 @@ object Person:
|
||||||
assert!(r.is_ok()); // does nothing runtime
|
assert!(r.is_ok()); // does nothing runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn object_() {
|
// fn object_() {
|
||||||
// let r = run(
|
// let r = run(
|
||||||
// r#"
|
// r#"
|
||||||
// object Person:
|
// object Person:
|
||||||
// name: string
|
// name: string
|
||||||
//
|
//
|
||||||
// let p = Person(name: "Sander")
|
// let p = Person(name: "Sander")
|
||||||
// print p
|
// print p
|
||||||
// "#,
|
// "#,
|
||||||
// );
|
// );
|
||||||
// println!("{:?}", r);
|
// println!("{:?}", r);
|
||||||
// assert!(r.is_ok());
|
// assert!(r.is_ok());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn literal_map() {
|
fn literal_map() {
|
||||||
|
|
@ -202,6 +203,16 @@ m"#);
|
||||||
assert_eq!(run(r#"0x10 + 0x20"#), Ok(Value::U32(48)));
|
assert_eq!(run(r#"0x10 + 0x20"#), Ok(Value::U32(48)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn date_literal() {
|
||||||
|
assert_eq!(
|
||||||
|
run(r#"t"2025-11-09 16:44:28.000 +0100""#),
|
||||||
|
Ok(Value::DateTime(
|
||||||
|
DateTime::parse_from_str("2025-11-09 16:44:28.000 +0100", "%Y-%m-%d %H:%M:%S%.3f %z").unwrap().into()
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn package() {
|
// fn package() {
|
||||||
// assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48)));
|
// assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48)));
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,11 @@ impl Scanner {
|
||||||
}
|
}
|
||||||
'\'' => self.char()?,
|
'\'' => self.char()?,
|
||||||
'"' => self.string()?,
|
'"' => self.string()?,
|
||||||
|
't' => {
|
||||||
|
if self.match_next('"') {
|
||||||
|
self.datetime()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
'\r' | '\t' | ' ' => {}
|
'\r' | '\t' | ' ' => {}
|
||||||
'\n' => {
|
'\n' => {
|
||||||
self.line += 1;
|
self.line += 1;
|
||||||
|
|
@ -220,6 +225,18 @@ impl Scanner {
|
||||||
CompilerErrorAtLine::raise(error, self.line)
|
CompilerErrorAtLine::raise(error, self.line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn datetime(&mut self) -> Result<(), CompilerErrorAtLine> {
|
||||||
|
while self.peek() != '"' && !self.is_at_end() {
|
||||||
|
self.advance();
|
||||||
|
}
|
||||||
|
self.advance();
|
||||||
|
let value: String = self.chars[self.start + 2..self.current - 1]
|
||||||
|
.iter()
|
||||||
|
.collect();
|
||||||
|
self.add_token_with_value(TokenType::DateTime, value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn string(&mut self) -> Result<(), CompilerErrorAtLine> {
|
fn string(&mut self) -> Result<(), CompilerErrorAtLine> {
|
||||||
while self.peek() != '"' && !self.is_at_end() {
|
while self.peek() != '"' && !self.is_at_end() {
|
||||||
if self.peek() == '\n' {
|
if self.peek() == '\n' {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@ use crate::ast_compiler::{Expression, Parameter, Statement};
|
||||||
use crate::errors::CompilerError;
|
use crate::errors::CompilerError;
|
||||||
use crate::errors::CompilerError::{IncompatibleTypes, TypeError};
|
use crate::errors::CompilerError::{IncompatibleTypes, TypeError};
|
||||||
use crate::tokens::{Token, TokenType};
|
use crate::tokens::{Token, TokenType};
|
||||||
use crate::tokens::TokenType::{
|
use crate::tokens::TokenType::{Bool, Date, F32, F64, FloatingPoint, Greater, GreaterEqual, I32, I64, Integer, Less, LessEqual, ListType, MapType, Minus, Object, Plus, SignedInteger, StringType, U32, U64, Unknown, UnsignedInteger, DateTime};
|
||||||
Bool, Date, F32, F64, FloatingPoint, Greater, GreaterEqual, I32, I64, Integer, Less, LessEqual,
|
|
||||||
ListType, MapType, Minus, Object, Plus, SignedInteger, StringType, U32, U64, Unknown,
|
|
||||||
UnsignedInteger,
|
|
||||||
};
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
@ -139,6 +135,7 @@ pub fn calculate_type(
|
||||||
FloatingPoint => F64,
|
FloatingPoint => F64,
|
||||||
Bool => Bool,
|
Bool => Bool,
|
||||||
Date => Date,
|
Date => Date,
|
||||||
|
DateTime => DateTime,
|
||||||
ListType => ListType,
|
ListType => ListType,
|
||||||
MapType => MapType,
|
MapType => MapType,
|
||||||
Object => Object,
|
Object => Object,
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ pub enum TokenType {
|
||||||
Star,
|
Star,
|
||||||
StringType,
|
StringType,
|
||||||
True,
|
True,
|
||||||
|
DateTime,
|
||||||
U32,
|
U32,
|
||||||
U64,
|
U64,
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
@ -156,6 +157,7 @@ impl fmt::Display for TokenType {
|
||||||
TokenType::SingleRightArrow => write!(f, "->"),
|
TokenType::SingleRightArrow => write!(f, "->"),
|
||||||
TokenType::Slash => write!(f, "/"),
|
TokenType::Slash => write!(f, "/"),
|
||||||
TokenType::Star => write!(f, "*"),
|
TokenType::Star => write!(f, "*"),
|
||||||
|
TokenType::DateTime => write!(f, "t\""),
|
||||||
TokenType::True => write!(f, "true"),
|
TokenType::True => write!(f, "true"),
|
||||||
TokenType::Unknown => write!(f, "?"),
|
TokenType::Unknown => write!(f, "?"),
|
||||||
TokenType::Void => write!(f, "()"),
|
TokenType::Void => write!(f, "()"),
|
||||||
|
|
|
||||||
14
src/value.rs
14
src/value.rs
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::errors::ValueError;
|
use crate::errors::ValueError;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Local, Utc};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
@ -23,7 +23,7 @@ pub enum Value {
|
||||||
String(String),
|
String(String),
|
||||||
Char(char),
|
Char(char),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Date(DateTime<Utc>),
|
DateTime(DateTime<Utc>),
|
||||||
Enum,
|
Enum,
|
||||||
List(Vec<Value>),
|
List(Vec<Value>),
|
||||||
Map(HashMap<Value, Value>),
|
Map(HashMap<Value, Value>),
|
||||||
|
|
@ -144,7 +144,7 @@ impl Into<Value> for bool {
|
||||||
|
|
||||||
impl Into<Value> for DateTime<Utc> {
|
impl Into<Value> for DateTime<Utc> {
|
||||||
fn into(self) -> Value {
|
fn into(self) -> Value {
|
||||||
Value::Date(self)
|
Value::DateTime(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ impl Display for Value {
|
||||||
&Value::F32(v) => write!(f, "{}", v),
|
&Value::F32(v) => write!(f, "{}", v),
|
||||||
&Value::F64(v) => write!(f, "{}", v),
|
&Value::F64(v) => write!(f, "{}", v),
|
||||||
&Value::Char(v) => write!(f, "{}", v),
|
&Value::Char(v) => write!(f, "{}", v),
|
||||||
&Value::Date(v) => write!(f, "{}", v),
|
&Value::DateTime(v) => write!(f, "{}", v),
|
||||||
&Value::Enum => write!(f, "enum"),
|
&Value::Enum => write!(f, "enum"),
|
||||||
&Value::ObjectType(o) => write!(f, "{}: {:?}", o.definition, o.fields),
|
&Value::ObjectType(o) => write!(f, "{}: {:?}", o.definition, o.fields),
|
||||||
&Value::List(v) => write!(f, "{:?}", v),
|
&Value::List(v) => write!(f, "{:?}", v),
|
||||||
|
|
@ -383,7 +383,7 @@ impl PartialEq for Value {
|
||||||
(Value::Bool(a), Value::Bool(b)) => a == b,
|
(Value::Bool(a), Value::Bool(b)) => a == b,
|
||||||
(Value::String(a), Value::String(b)) => a == b,
|
(Value::String(a), Value::String(b)) => a == b,
|
||||||
(Value::Char(a), Value::Char(b)) => a == b,
|
(Value::Char(a), Value::Char(b)) => a == b,
|
||||||
(Value::Date(a), Value::Date(b)) => a == b,
|
(Value::DateTime(a), Value::DateTime(b)) => a == b,
|
||||||
(Value::List(a), Value::List(b)) => a == b,
|
(Value::List(a), Value::List(b)) => a == b,
|
||||||
(Value::Map(a), Value::Map(b)) => {
|
(Value::Map(a), Value::Map(b)) => {
|
||||||
let mut equal = true;
|
let mut equal = true;
|
||||||
|
|
@ -415,7 +415,7 @@ impl PartialOrd for Value {
|
||||||
(Value::F64(a), Value::F64(b)) => Some(a.partial_cmp(b)?),
|
(Value::F64(a), Value::F64(b)) => Some(a.partial_cmp(b)?),
|
||||||
(Value::String(a), Value::String(b)) => Some(a.partial_cmp(b)?),
|
(Value::String(a), Value::String(b)) => Some(a.partial_cmp(b)?),
|
||||||
(Value::Char(a), Value::Char(b)) => Some(a.partial_cmp(b)?),
|
(Value::Char(a), Value::Char(b)) => Some(a.partial_cmp(b)?),
|
||||||
(Value::Date(a), Value::Date(b)) => Some(a.partial_cmp(b)?),
|
(Value::DateTime(a), Value::DateTime(b)) => Some(a.partial_cmp(b)?),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -436,7 +436,7 @@ impl Hash for Value {
|
||||||
Value::String(s) => s.hash(state),
|
Value::String(s) => s.hash(state),
|
||||||
Value::Char(c) => c.hash(state),
|
Value::Char(c) => c.hash(state),
|
||||||
Value::Bool(b) => b.hash(state),
|
Value::Bool(b) => b.hash(state),
|
||||||
Value::Date(d) => d.hash(state),
|
Value::DateTime(d) => d.hash(state),
|
||||||
Value::List(l) => l.hash(state),
|
Value::List(l) => l.hash(state),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue