Summary Files Commits Branches @commit @diff @stats
path: root / src / StringConsumer
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/StringConsumer
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
+ };
+};