forked from AbleScript/ablescript
Chars are no longer special case of identifiers
This commit is contained in:
parent
f7cba4b2b6
commit
b346995bfd
|
@ -8,7 +8,7 @@
|
||||||
//! just plain subroutines and they do not return any value,
|
//! just plain subroutines and they do not return any value,
|
||||||
//! so their calls are statements.
|
//! so their calls are statements.
|
||||||
|
|
||||||
use crate::variables::Value;
|
use crate::{base_55::char2num, variables::Value};
|
||||||
use std::{fmt::Debug, hash::Hash};
|
use std::{fmt::Debug, hash::Hash};
|
||||||
|
|
||||||
type Span = std::ops::Range<usize>;
|
type Span = std::ops::Range<usize>;
|
||||||
|
@ -165,6 +165,7 @@ pub enum Expr {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
|
Char(char),
|
||||||
Int(isize),
|
Int(isize),
|
||||||
Str(String),
|
Str(String),
|
||||||
}
|
}
|
||||||
|
@ -172,6 +173,7 @@ pub enum Literal {
|
||||||
impl From<Literal> for Value {
|
impl From<Literal> for Value {
|
||||||
fn from(lit: Literal) -> Self {
|
fn from(lit: Literal) -> Self {
|
||||||
match lit {
|
match lit {
|
||||||
|
Literal::Char(c) => Self::Int(char2num(c)),
|
||||||
Literal::Int(i) => Self::Int(i),
|
Literal::Int(i) => Self::Int(i),
|
||||||
Literal::Str(s) => Self::Str(s),
|
Literal::Str(s) => Self::Str(s),
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Assignable, AssignableKind, Expr, Spanned, Stmt},
|
ast::{Assignable, AssignableKind, Expr, Spanned, Stmt},
|
||||||
base_55,
|
|
||||||
consts::ablescript_consts,
|
consts::ablescript_consts,
|
||||||
error::{Error, ErrorKind},
|
error::{Error, ErrorKind},
|
||||||
variables::{Functio, Value, ValueRef, Variable},
|
variables::{Functio, Value, ValueRef, Variable},
|
||||||
|
@ -516,14 +515,7 @@ impl ExecEnv {
|
||||||
/// Get the value of a variable. Throw an error if the variable is
|
/// Get the value of a variable. Throw an error if the variable is
|
||||||
/// inaccessible or banned.
|
/// inaccessible or banned.
|
||||||
fn get_var(&self, name: &Spanned<String>) -> Result<Value, Error> {
|
fn get_var(&self, name: &Spanned<String>) -> Result<Value, Error> {
|
||||||
// One-letter names are reserved as base55 numbers.
|
// Search for the name in the stack from top to bottom.
|
||||||
let mut chars = name.item.chars();
|
|
||||||
if let (Some(first), None) = (chars.next(), chars.next()) {
|
|
||||||
return Ok(Value::Int(base_55::char2num(first)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, search for the name in the stack from top to
|
|
||||||
// bottom.
|
|
||||||
match self
|
match self
|
||||||
.stack
|
.stack
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -116,8 +116,12 @@ pub enum Token {
|
||||||
#[regex(r"-?[0-9]+", get_value)]
|
#[regex(r"-?[0-9]+", get_value)]
|
||||||
Integer(isize),
|
Integer(isize),
|
||||||
|
|
||||||
|
// A character (to be base-55 converted)
|
||||||
|
#[regex(r"\p{XID_Start}", get_value)]
|
||||||
|
Char(char),
|
||||||
|
|
||||||
/// An identifier
|
/// An identifier
|
||||||
#[regex(r"\p{XID_Start}[\p{XID_Continue}]*", get_ident)]
|
#[regex(r"\p{XID_Start}[\p{XID_Continue}]+", get_ident)]
|
||||||
Identifier(String),
|
Identifier(String),
|
||||||
|
|
||||||
#[regex(r"owo .*")]
|
#[regex(r"owo .*")]
|
||||||
|
|
|
@ -101,6 +101,7 @@ impl<'source> Parser<'source> {
|
||||||
Token::Identifier(_)
|
Token::Identifier(_)
|
||||||
| Token::String(_)
|
| Token::String(_)
|
||||||
| Token::Integer(_)
|
| Token::Integer(_)
|
||||||
|
| Token::Char(_)
|
||||||
| Token::Aint
|
| Token::Aint
|
||||||
| Token::LeftBracket
|
| Token::LeftBracket
|
||||||
| Token::LeftParen => Ok(Spanned::new(
|
| Token::LeftParen => Ok(Spanned::new(
|
||||||
|
@ -183,6 +184,10 @@ impl<'source> Parser<'source> {
|
||||||
})),
|
})),
|
||||||
start..self.lexer.span().end,
|
start..self.lexer.span().end,
|
||||||
)),
|
)),
|
||||||
|
Token::Char(c) => Ok(Spanned::new(
|
||||||
|
Expr::Literal(Literal::Char(c)),
|
||||||
|
start..self.lexer.span().end,
|
||||||
|
)),
|
||||||
|
|
||||||
Token::LeftBracket => match buf.take() {
|
Token::LeftBracket => match buf.take() {
|
||||||
Some(buf) => Ok(Spanned::new(
|
Some(buf) => Ok(Spanned::new(
|
||||||
|
@ -416,12 +421,10 @@ impl<'source> Parser<'source> {
|
||||||
/// Consists of condition and block, there is no else
|
/// Consists of condition and block, there is no else
|
||||||
fn if_flow(&mut self) -> Result<Stmt, Error> {
|
fn if_flow(&mut self) -> Result<Stmt, Error> {
|
||||||
self.require(Token::LeftParen)?;
|
self.require(Token::LeftParen)?;
|
||||||
|
Ok(Stmt::If {
|
||||||
let cond = self.expr_flow(Token::RightParen)?;
|
cond: self.expr_flow(Token::RightParen)?,
|
||||||
|
body: self.get_block()?,
|
||||||
let body = self.get_block()?;
|
})
|
||||||
|
|
||||||
Ok(Stmt::If { cond, body })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse functio flow
|
/// Parse functio flow
|
||||||
|
@ -429,7 +432,6 @@ impl<'source> Parser<'source> {
|
||||||
/// functio $ident (a, b, c) { ... }
|
/// functio $ident (a, b, c) { ... }
|
||||||
fn functio_flow(&mut self) -> Result<Stmt, Error> {
|
fn functio_flow(&mut self) -> Result<Stmt, Error> {
|
||||||
let ident = self.get_ident()?;
|
let ident = self.get_ident()?;
|
||||||
|
|
||||||
self.require(Token::LeftParen)?;
|
self.require(Token::LeftParen)?;
|
||||||
|
|
||||||
let mut params = vec![];
|
let mut params = vec![];
|
||||||
|
@ -606,7 +608,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_math() {
|
fn simple_math() {
|
||||||
let code = "1 * (a + 3) / 666 print;";
|
let code = "1 * (num + 3) / 666 print;";
|
||||||
let expected = &[Spanned {
|
let expected = &[Spanned {
|
||||||
item: Stmt::Print(Spanned {
|
item: Stmt::Print(Spanned {
|
||||||
item: Expr::BinOp {
|
item: Expr::BinOp {
|
||||||
|
@ -619,7 +621,7 @@ mod tests {
|
||||||
rhs: Box::new(Spanned {
|
rhs: Box::new(Spanned {
|
||||||
item: Expr::BinOp {
|
item: Expr::BinOp {
|
||||||
lhs: Box::new(Spanned {
|
lhs: Box::new(Spanned {
|
||||||
item: Expr::Variable("a".to_owned()),
|
item: Expr::Variable("num".to_owned()),
|
||||||
span: 5..6,
|
span: 5..6,
|
||||||
}),
|
}),
|
||||||
rhs: Box::new(Spanned {
|
rhs: Box::new(Spanned {
|
||||||
|
@ -651,11 +653,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn variable_declaration() {
|
fn variable_declaration() {
|
||||||
let code = "dim a 42;";
|
let code = "dim var 42;";
|
||||||
let expected = &[Spanned {
|
let expected = &[Spanned {
|
||||||
item: Stmt::Dim {
|
item: Stmt::Dim {
|
||||||
ident: Spanned {
|
ident: Spanned {
|
||||||
item: "a".to_owned(),
|
item: "var".to_owned(),
|
||||||
span: 4..5,
|
span: 4..5,
|
||||||
},
|
},
|
||||||
init: Some(Spanned {
|
init: Some(Spanned {
|
||||||
|
@ -672,13 +674,13 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_flow() {
|
fn if_flow() {
|
||||||
let code = "if (a = always) { /*Buy Able products!*/ print; }";
|
let code = "if (var = always) { /*Buy Able products!*/ print; }";
|
||||||
let expected = &[Spanned {
|
let expected = &[Spanned {
|
||||||
item: Stmt::If {
|
item: Stmt::If {
|
||||||
cond: Spanned {
|
cond: Spanned {
|
||||||
item: Expr::BinOp {
|
item: Expr::BinOp {
|
||||||
lhs: Box::new(Spanned {
|
lhs: Box::new(Spanned {
|
||||||
item: Expr::Variable("a".to_owned()),
|
item: Expr::Variable("var".to_owned()),
|
||||||
span: 4..5,
|
span: 4..5,
|
||||||
}),
|
}),
|
||||||
rhs: Box::new(Spanned {
|
rhs: Box::new(Spanned {
|
||||||
|
|
Loading…
Reference in a new issue