conlang: Add break
, true
, false
keywords, and example file
This commit is contained in:
parent
f25685560a
commit
48f5e5248c
31
dummy.cl
31
dummy.cl
@ -1,9 +1,24 @@
|
|||||||
#!/ this is a shebang comment!
|
#!/usr/local/bin/conlang
|
||||||
// This is an example Conlang file.
|
// This is a Conlang file. Conlang is an expression-based language designed for maximum flexibility etc. etc. whatever
|
||||||
|
|
||||||
/* Conlang supports block comments! */
|
// This is a function. It can be called with the call operator.
|
||||||
ident // Identifier
|
// The function called `main` is the program's entrypoint
|
||||||
.1 // literal float
|
fn main() {
|
||||||
0.1 // literal float
|
let x = 100;
|
||||||
0x1234 // literal integer
|
|
||||||
"str" // literal string
|
// An if expression is like the ternary conditional operator in C
|
||||||
|
let y = if x < 50 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
};
|
||||||
|
|
||||||
|
// A `for` expression is like the for-else construct in Python, but it returns a value via the `break` keyword
|
||||||
|
let z = for i in 0..y {
|
||||||
|
// do a thing repeatedly
|
||||||
|
break true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
// TODO: decide how to do IO
|
||||||
|
}
|
||||||
|
@ -11,12 +11,15 @@ pub mod token {
|
|||||||
Comment,
|
Comment,
|
||||||
Identifier,
|
Identifier,
|
||||||
// Keywords
|
// Keywords
|
||||||
|
KwBreak,
|
||||||
KwElse,
|
KwElse,
|
||||||
|
KwFalse,
|
||||||
KwFor,
|
KwFor,
|
||||||
KwFn,
|
KwFn,
|
||||||
KwIf,
|
KwIf,
|
||||||
KwIn,
|
KwIn,
|
||||||
KwLet,
|
KwLet,
|
||||||
|
KwTrue,
|
||||||
KwWhile,
|
KwWhile,
|
||||||
// Literals
|
// Literals
|
||||||
LitInteger,
|
LitInteger,
|
||||||
@ -151,12 +154,15 @@ pub mod lexer {
|
|||||||
}
|
}
|
||||||
/// Attempts to produce a Keyword
|
/// Attempts to produce a Keyword
|
||||||
pub fn keyword(&mut self) -> Option<Token> {
|
pub fn keyword(&mut self) -> Option<Token> {
|
||||||
None.or_else(|| self.kw_else())
|
None.or_else(|| self.kw_break())
|
||||||
|
.or_else(|| self.kw_else())
|
||||||
|
.or_else(|| self.kw_false())
|
||||||
.or_else(|| self.kw_for())
|
.or_else(|| self.kw_for())
|
||||||
.or_else(|| self.kw_fn())
|
.or_else(|| self.kw_fn())
|
||||||
.or_else(|| self.kw_if())
|
.or_else(|| self.kw_if())
|
||||||
.or_else(|| self.kw_in())
|
.or_else(|| self.kw_in())
|
||||||
.or_else(|| self.kw_let())
|
.or_else(|| self.kw_let())
|
||||||
|
.or_else(|| self.kw_true())
|
||||||
.or_else(|| self.kw_while())
|
.or_else(|| self.kw_while())
|
||||||
}
|
}
|
||||||
/// Attempts to produce a [Type::LitString], [Type::LitFloat], or [Type::LitInteger]
|
/// Attempts to produce a [Type::LitString], [Type::LitFloat], or [Type::LitInteger]
|
||||||
@ -230,9 +236,15 @@ pub mod lexer {
|
|||||||
self.map_rule(|r| r.comment(), Type::Comment)
|
self.map_rule(|r| r.comment(), Type::Comment)
|
||||||
}
|
}
|
||||||
// keywords
|
// keywords
|
||||||
|
pub fn kw_break(&mut self) -> Option<Token> {
|
||||||
|
self.map_rule(|r| r.str("break"), Type::KwBreak)
|
||||||
|
}
|
||||||
pub fn kw_else(&mut self) -> Option<Token> {
|
pub fn kw_else(&mut self) -> Option<Token> {
|
||||||
self.map_rule(|r| r.str("else"), Type::KwElse)
|
self.map_rule(|r| r.str("else"), Type::KwElse)
|
||||||
}
|
}
|
||||||
|
pub fn kw_false(&mut self) -> Option<Token> {
|
||||||
|
self.map_rule(|r| r.str("false"), Type::KwFalse)
|
||||||
|
}
|
||||||
pub fn kw_for(&mut self) -> Option<Token> {
|
pub fn kw_for(&mut self) -> Option<Token> {
|
||||||
self.map_rule(|r| r.str("for"), Type::KwFor)
|
self.map_rule(|r| r.str("for"), Type::KwFor)
|
||||||
}
|
}
|
||||||
@ -248,6 +260,9 @@ pub mod lexer {
|
|||||||
pub fn kw_let(&mut self) -> Option<Token> {
|
pub fn kw_let(&mut self) -> Option<Token> {
|
||||||
self.map_rule(|r| r.str("let"), Type::KwLet)
|
self.map_rule(|r| r.str("let"), Type::KwLet)
|
||||||
}
|
}
|
||||||
|
pub fn kw_true(&mut self) -> Option<Token> {
|
||||||
|
self.map_rule(|r| r.str("true"), Type::KwTrue)
|
||||||
|
}
|
||||||
pub fn kw_while(&mut self) -> Option<Token> {
|
pub fn kw_while(&mut self) -> Option<Token> {
|
||||||
self.map_rule(|r| r.str("while"), Type::KwWhile)
|
self.map_rule(|r| r.str("while"), Type::KwWhile)
|
||||||
}
|
}
|
||||||
@ -696,11 +711,19 @@ mod tests {
|
|||||||
mod keyword {
|
mod keyword {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
|
fn kw_break() {
|
||||||
|
assert_whole_input_is_token("break", Lexer::kw_break, Type::KwBreak);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
fn kw_else() {
|
fn kw_else() {
|
||||||
assert_whole_input_is_token("else", Lexer::kw_else, Type::KwElse);
|
assert_whole_input_is_token("else", Lexer::kw_else, Type::KwElse);
|
||||||
assert_has_type_and_range(" else ", Lexer::kw_else, Type::KwElse, 2..6);
|
assert_has_type_and_range(" else ", Lexer::kw_else, Type::KwElse, 2..6);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
fn kw_false() {
|
||||||
|
assert_whole_input_is_token("false", Lexer::kw_false, Type::KwFalse);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
fn kw_for() {
|
fn kw_for() {
|
||||||
assert_whole_input_is_token("for", Lexer::kw_for, Type::KwFor);
|
assert_whole_input_is_token("for", Lexer::kw_for, Type::KwFor);
|
||||||
}
|
}
|
||||||
@ -721,6 +744,10 @@ mod tests {
|
|||||||
assert_whole_input_is_token("let", Lexer::kw_let, Type::KwLet);
|
assert_whole_input_is_token("let", Lexer::kw_let, Type::KwLet);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
fn kw_true() {
|
||||||
|
assert_whole_input_is_token("true", Lexer::kw_true, Type::KwTrue);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
fn kw_while() {
|
fn kw_while() {
|
||||||
assert_whole_input_is_token("while", Lexer::kw_while, Type::KwWhile);
|
assert_whole_input_is_token("while", Lexer::kw_while, Type::KwWhile);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user