Summary Files Commits Branches @commit @diff @stats
path: root / src
diff options
context:
space:
mode:
Commitb43c94ca62a747f2f9fb222cdf887c041dd544bb (patch)
Author
 Syndamia <kamen@syndamia.com>
2025-11-01 16:28:08 +0200
Committer
 Syndamia <kamen@syndamia.com>
2025-11-01 16:28:08 +0200
Files43e0ea846844257cf46055e68cc2661056b05965 /src
cool-self-hosted-b43c94ca62a747f2f9fb222cdf887c041dd544bb.tar
cool-self-hosted-b43c94ca62a747f2f9fb222cdf887c041dd544bb.tar.gz
cool-self-hosted-b43c94ca62a747f2f9fb222cdf887c041dd544bb.zip
Parent0830615386f036acc55a72b2548efb65526c761f (diff)
feat!: Add basic lexer components
diff --git a/src/StringConsumer/ConsumerList.cl b/src/StringConsumer/ConsumerList.cl
new file mode 100644
index 0000000..526996c
--- /dev/null
+++ b/src/StringConsumer/ConsumerList.cl
@@ -0,0 +1,52 @@
+class ConsumerList inherits System {
+ item: IStringConsumer;
+ next: ConsumerList;
+
+ init(value: IStringConsumer, tail: Object) : ConsumerList {{
+ assert(not (isvoid value), "init", "value argument cannot be void!");
+ assert(isvoid item, "init", "List has already been initialised!");
+
+ item <- value;
+ if isvoid tail then
+ void
+ else
+ case tail of
+ cl: ConsumerList => next <- cl;
+ o: Object => assert(false, "init", "tail argument can be either a ConsumerList or void!");
+ esac
+ fi;
+
+ self;
+ }};
+
+ push(value: IStringConsumer) : ConsumerList {{
+ assert(not (isvoid value), "push", "value argument cannot be void!");
+
+ if isvoid item
+ then
+ item <- value
+ else if isvoid next
+ then
+ next <- (new ConsumerList).init(value, void)
+ else
+ next.push(value)
+ fi
+ fi;
+ self;
+ }};
+
+ find(s: String) : Object {{
+ assert(not (isvoid item), "find", "list isn't initialised!");
+
+ if 0 < item.consume(s)
+ then
+ item
+ else if isvoid next
+ then
+ void
+ else
+ next.find(s)
+ fi
+ fi;
+ }};
+};
diff --git a/src/StringConsumer/IStringConsumer.cl b/src/StringConsumer/IStringConsumer.cl
new file mode 100644
index 0000000..20a4f3a
--- /dev/null
+++ b/src/StringConsumer/IStringConsumer.cl
@@ -0,0 +1,20 @@
+class IStringConsumer inherits System {
+ consume(s: String) : Int {
+ not_implemented_retint("consume")
+ };
+
+ token() : IToken {{
+ not_implemented("token");
+ new IToken;
+ }};
+
+ out() : Object {
+ not_implemented("out")
+ };
+
+---
+ consumed_length: Int;
+ consumed_length() : Int {
+ consumed_length
+ };
+};
diff --git a/src/StringConsumer/StringConsumerEngine.cl b/src/StringConsumer/StringConsumerEngine.cl
new file mode 100644
index 0000000..dc7e202
--- /dev/null
+++ b/src/StringConsumer/StringConsumerEngine.cl
@@ -0,0 +1,36 @@
+class StringConsumerEngine inherits System {
+ consumers: ConsumerList <- (new ConsumerList)
+ .push(new WhitespaceConsumer)
+ ;
+
+ str: String;
+
+ init(code: String) : Object {{
+ assert(not (code = ""), "init", "input code cannot be empty!");
+ assert(str = "", "init", "already initialised!");
+
+ str <- code;
+ }};
+
+ try_consume() : Bool {
+ let
+ consumer: Object <- consumers.find(str)
+ in
+ if isvoid consumer
+ then
+ false
+ else
+ case consumers.find(str) of
+ c: IStringConsumer => {
+ str <- str.substr(c.consumed_length(), str.length() - c.consumed_length());
+ true;
+ };
+ o: Object => false;
+ esac
+ fi
+ };
+
+ out() : Object {
+ out_string(str)
+ };
+};
diff --git a/src/StringConsumer/WhitespaceConsumer.cl b/src/StringConsumer/WhitespaceConsumer.cl
new file mode 100644
index 0000000..4c0b8b5
--- /dev/null
+++ b/src/StringConsumer/WhitespaceConsumer.cl
@@ -0,0 +1,15 @@
+class WhitespaceConsumer inherits IStringConsumer {
+ consume(s: String) : Int {{
+ consumed_length <- 0;
+ while or(s.substr(consumed_length, 1) = " ",
+ s.substr(consumed_length, 1) = "\t")
+ loop
+ consumed_length <- consumed_length + 1
+ pool;
+ consumed_length;
+ }};
+
+ token() : IToken {
+ new WhitespaceToken
+ };
+};
diff --git a/src/System.cl b/src/System.cl
new file mode 100644
index 0000000..12f2210
--- /dev/null
+++ b/src/System.cl
@@ -0,0 +1,60 @@
+-- "Global" constructs
+
+class System inherits IO {
+ void: Object <- while false loop 0 pool;
+
+ or(p: Bool, q: Bool) : Bool {
+ if p then true
+ else
+ if q then true
+ else false
+ fi
+ fi
+ };
+
+ and(p: Bool, q: Bool) : Bool {
+ if p then
+ if q then true
+ else false
+ fi
+ else false
+ fi
+ };
+
+ assert(condition: Bool, method_name: String, error_msg: String) : Object {
+ if not condition then
+ {
+ out_string("\n")
+ .out_string("Assertion failed at ")
+ .out_string(type_name())
+ .out_string(".")
+ .out_string(method_name)
+ .out_string("(): ")
+ .out_string(error_msg)
+ .out_string("\n");
+ abort();
+ }
+ else
+ void
+ fi
+ };
+
+ not_implemented(method_name: String) : Object {{
+ out_string("\n")
+ .out_string("Method ")
+ .out_string(type_name())
+ .out_string(".")
+ .out_string(method_name)
+ .out_string("() isn't implemented!")
+ .out_string("\n");
+ abort();
+ }};
+ not_implemented_retint(method_name: String) : Int {{
+ not_implemented(method_name);
+ 0;
+ }};
+ not_implemented_retstr(method_name: String) : String {{
+ not_implemented(method_name);
+ "";
+ }};
+};
diff --git a/src/Token/IToken.cl b/src/Token/IToken.cl
new file mode 100644
index 0000000..05282ab
--- /dev/null
+++ b/src/Token/IToken.cl
@@ -0,0 +1,24 @@
+class IToken inherits System {
+---
+ name() : String {
+ not_implemented_retstr("name")
+ };
+
+ value() : String {
+ not_implemented_retstr("value")
+ };
+
+---
+ id: Int;
+
+ id() : Int {
+ id
+ };
+
+ init(iid: Int) : Object {{
+ assert(iid = 0, "init", "ID 0 is not allowed for a token!");
+ assert(not (id = 0), "init", "token object '".concat(name()).concat("' is already initialized!"));
+ id <- iid;
+ void;
+ }};
+};
diff --git a/src/Token/WhitespaceToken.cl b/src/Token/WhitespaceToken.cl
new file mode 100644
index 0000000..e0d70c0
--- /dev/null
+++ b/src/Token/WhitespaceToken.cl
@@ -0,0 +1,10 @@
+class WhitespaceToken inherits IToken {
+ name() : String {
+ "WHITESPACE"
+ };
+
+ -- We'll never use the whitespace value
+ value() : String {
+ ""
+ };
+};
diff --git a/src/main.cl b/src/main.cl
new file mode 100644
index 0000000..9ebb87b
--- /dev/null
+++ b/src/main.cl
@@ -0,0 +1,10 @@
+class Main inherits System {
+ sce: StringConsumerEngine <- new StringConsumerEngine;
+
+ main() : Object {{
+ sce.init(" abc");
+ sce.try_consume();
+ sce.try_consume();
+ sce.out();
+ }};
+};