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