From 5a2ef79fe659c650e7fd8307eb83514823aee212 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 5 Sep 2023 14:36:17 +0200 Subject: [PATCH] Update "not working" examples. --- resources/examples/notworking/globals.c3 | 9 +- resources/examples/notworking/http.c3 | 8 +- resources/examples/notworking/madlibs.c3 | 10 +- .../examples/notworking/toml_parser_c2.c3 | 759 ------------------ .../examples/notworking/toml_tokenizer_c2.c3 | 357 -------- resources/examples/notworking/window.c3 | 9 +- 6 files changed, 17 insertions(+), 1135 deletions(-) delete mode 100644 resources/examples/notworking/toml_parser_c2.c3 delete mode 100644 resources/examples/notworking/toml_tokenizer_c2.c3 diff --git a/resources/examples/notworking/globals.c3 b/resources/examples/notworking/globals.c3 index 23ab78b40..e0f35f721 100644 --- a/resources/examples/notworking/globals.c3 +++ b/resources/examples/notworking/globals.c3 @@ -1,19 +1,19 @@ module globals; -const string CLICK_ME = "Click Me"; -var uint counter = 0; +const String CLICK_ME = "Click Me"; +uint counter = 0; fn void clickedme(GtkButton *o, void *d) { (GtkLabel*)(d).set_text(string.format("You clicked me %d times", ++counter)); } -int main(int argc as string[] argv) +fn void main(String[] argv) { gtk::init(&argc, &argv); - GtkWindow *win = gtk::windowCreate(GtkWindow::TOPLEVEL); + GtkWindow *win = gtk::windowCreate(GtkWindow.TOPLEVEL); win.set_title(CLICK_ME); GtkButton *button = gtk::buttonCreateWithLabel(CLICK_ME); @@ -32,5 +32,4 @@ int main(int argc as string[] argv) win.showAll(); gtk::main(); - return 0; } diff --git a/resources/examples/notworking/http.c3 b/resources/examples/notworking/http.c3 index 1ccd084b7..c21c9ef94 100644 --- a/resources/examples/notworking/http.c3 +++ b/resources/examples/notworking/http.c3 @@ -4,18 +4,18 @@ fn int main(void) { Curl curl; - catch (e = curl.init()) + if (catch e = curl.init()) { - printf("Failed to create new curl: %s\n", e.message); + io::printfn("Failed to create new curl: %s\n", e); exit(FAILURE); } curl.setopt(URL, "http://www.rosettacode.org/"); curl.setopt(FOLLOWLOCATION, 1); - catch (e = curl.perform()) + if (catch err = curl.perform()) { - printf("Error making request: %s\n", e.message); + io::printfn("Error making request: %s\n", e); exit(FAILURE); } diff --git a/resources/examples/notworking/madlibs.c3 b/resources/examples/notworking/madlibs.c3 index 412e5d212..8bbd9b4a3 100644 --- a/resources/examples/notworking/madlibs.c3 +++ b/resources/examples/notworking/madlibs.c3 @@ -4,24 +4,24 @@ import regex, stdio; fn void main() { printn("Enter a story template, terminated by an empty line:"); - VarString story = ""; - while (1) + String story = ""; + while (try String line = stdin().readline().strip()) { - VarString line = stdin.readln().strip() else break; + story = story.append(line); story = story.append("\n"); } Regex r; - r.initWithOptions("<.+?>", RegexOpt.GLOBAL) else unreachable; + r.initWithOptions("<.+?>", RegexOpt.GLOBAL)!!; defer r.destroy(); foreach (RegexMatch* match : r.match(story)) { VarString s = match.string; printf("Enter a value for '%s': ", s[1..^2]); - string word = stdin.readln().strip() else return; + String word = stdin().readline().strip()!; story = story.replace(s, word); } diff --git a/resources/examples/notworking/toml_parser_c2.c3 b/resources/examples/notworking/toml_parser_c2.c3 deleted file mode 100644 index b47a14a13..000000000 --- a/resources/examples/notworking/toml_parser_c2.c3 +++ /dev/null @@ -1,759 +0,0 @@ -// This is the toml_parser.c2 changed to c3 to compare - -module toml; - -import stdio; -import stdlib; -import string; -import file_utils; -import csetjmp; - -const uint NamesCacheSize = 8; -const uint MaxNodes = 1024; -const uint MaxNames = 4096; -const uint MaxValues = 4096 * 128; -const uint MaxDepth = 8; - -//#define DEBUG_NODES - -$if DEBUG_NODES: - -fn void Blocks.dump(Blocks* b) -{ - printf("Nodes (%u/%u) (%u bytes)\n", b.nodeCount, b.maxNodes, b.nodeCount * sizeof(Node)); - for (uint i = 0; i < b.nodeCount; i++) - { - // @ensure const(n) - Node* n = &b.nodes[i]; - uint nameOffset = getValue(n.nameOffset); - NodeKind kind = getKind(n.nameOffset); - switch (kind) - { - case NodeKind.TABLE: - case NodeKind.TABLE_ARRAY: - printf(" [%3u] %s name %3u next %3u child %3u (%s)\n", - i, kind.name, nameOffset, n.nextNode, n.child, &b.names[nameOffset]); - case NodeKind.VALUE_ARRAY: - case NodeKind.VALUE: - ValueType t = getRawType(n.rawValue); - uint offset = getRawValue(n.rawValue); - printf(" [%3u] %s name %3u next %3u value %5u(%s) (%s)\n", - i, kind.name, nameOffset, n.nextNode, offset, type2str(t), &b.names[nameOffset]); - case NodeKind.ARRAY_CHILD: - printf(" [%3u] %s name --- next %3u child %3u\n", - i, kind.name, n.nextNode, n.child); - } - } - printf("Names (%u/%u)\n", b.namesOffset, b.namesSize); - uint i = 1; - uint start = i; - while (i < b.namesOffset) - { - if (b.names[i] == 0) { - printf(" [%3u] %s\n", start, &b.names[start]); - i++; - start = i; - } - else - { - i++; - } - } - printf("Values (%u/%u)\n", b.valuesOffset, b.valuesSize); - i = 1; - start = i; - while (i < b.valuesOffset) - { - if (b.values[i] == 0) - { - printf(" [%3u] %s\n", start, &b.values[start]); - i++; - start = i; - } - else - { - i++; - } - } -} - -$endif - -/** - * @ensure const(a), const(b) - */ -fn bool same(char* a, char* b) -{ - uint i = 0; - while (a[i] == b[i]) - { - if (a[i] == 0) return true; - ++i; - } - return false; -} - -struct Parser -{ - Tokenizer tokenizer; - Token tok; - JmpBuf jump_err; - char* errorMsg; - - Blocks* blocks; - Node*[MaxDepth] parents; - Node*[MaxDepth] lastChild; - uint numParents; - Node* topParent; -} - -/** - * @ensure const(input) - */ -fn void! Parser.parse(Parser* p, char* input, char* diagMsg, Blocks* blocks) -{ - p.tokenizer.init(input); - p.tok.init(); - p.errorMsg = diagMsg; - p.errorMsg[0] = 0; - - p.blocks = blocks; - mem::set(p.parents, 0, sizeof(Node*)*MaxDepth); - mem::set(p.lastChild, 0, sizeof(Node*)*MaxDepth); - p.numParents = 0; - p.topParent = nil; - - try p.consumeToken(); - try p.parseTopLevel(); -} - -fn void! Parser.parseTopLevel(Parser* p) -{ - // key = value - // | [[array]] - // | [table] - while (p.tok.isNot(TokenKind.EOF)) - { - switch (p.tok.kind) - { - case WORD: - p.parseKeyValue(); - case LBRACE: - p.parseTable(); - case LBRACE2: - p.parseTableArray(); - default: - sprintf(p.errorMsg, "syntax error %s", p.tok.loc.str()); - return SyntaxError!; - } - } -} - -fn uint getRawValue(uint raw) @(inline) -{ - return raw & ~RawValueMask; -} - -fn ValueType getRawType(uint raw) @(inline) -{ - return (ValueType)((raw >> ValueTypeOffset) & 0x3); -} - -fn uint addType(uint raw, ValueType t) @(inline) -{ - return raw | (t << ValueTypeOffset); -} - -fn void! Parser.parseKeyValue(Parser* p) -{ - //printf("parseKeyValue()\n"); - char[MaxText] key; - strcpy(key, p.tok.text); - try p.consumeToken(); - try p.expectAndConsume(TokenKind.Equals); - u32 value = try p.parseValue(); - bool isArray = value & ValueIsArray != 0; - u32 off = p.blocks.addNode(key, isArray ? NodeKind.ValueArray : NodeKind.Value); - Node* node = &p.blocks.nodes[off]; - node.rawValue = value; - if (p.lastChild[p.numParents]) - { - p.lastChild[p.numParents].nextNode = off; - } - else - { - if (p.topParent) p.topParent.child = off; - } - p.lastChild[p.numParents] = node; -} - -fn void! Parser.parseTable(Parser* p) -{ - //printf("parseTable()\n"); - try p.consumeToken(); - try p.expect(TokenKind.Word); - char* name = p.tok.text; - uint depth = 0; - bool isTop = p.nextToken().isNot(TokenKind.DOT); - depth += p.addTable(name, depth, isTop, NodeKind.Table); - p.consumeToken(); - - while (p.tok.is(TokenKind.DOT)) - { - depth++; - p.consumeToken(); - p.expect(TokenKind.WORD); - name = p.tok.text; - isTop = p.nextToken().isNot(TokenKind.DOT); - depth += p.addTable(name, depth, isTop, NodeKind.TABLE); - p.consumeToken(); - } - p.expectAndConsume(TokenKind.Rbrace); -} - -fn void Parser.parseTableArray(Parser* p) -{ - //printf("parseTableArray()\n"); - p.consumeToken(); - p.expect(TokenKind.Word); - const char* name = p.tok.text; - u32 depth = 0; - bool isTop = p.nextToken().isNot(TokenKind.Dot); - depth += p.addTable(name, depth, isTop, NodeKind.TableArray); - p.consumeToken(); - - while (p.tok.is(TokenKind.Dot)) { - depth++; - p.consumeToken(); - p.expect(TokenKind.Word); - name = p.tok.text; - isTop = p.nextToken().isNot(TokenKind.Dot); - depth += p.addTable(name, depth, isTop, NodeKind.TableArray); - p.consumeToken(); - } - p.expectAndConsume(TokenKind.Rbrace2); -} - -fn u32 Parser.parseValue(Parser* p) { - //printf("parseValue()\n"); - u32 value = 0; - switch (p.tok.kind) { - case TokenKind.Word: - sprintf(p.errorMsg, "unexpected word at %s", p.tok.loc.str()); - longjmp(p.jump_err, 1); - break; - case TokenKind.Text: - value = p.blocks.addValue(p.tok.text); - value = addType(value, ValueType.Text); - p.consumeToken(); - break; - case TokenKind.Number: - // TODO negative numbers - value = addType(p.tok.number, ValueType.Number); - p.consumeToken(); - break; - case TokenKind.Kw_true: fallthrough; - case TokenKind.Kw_false: - value = addType(p.tok.number, ValueType.Boolean); - p.consumeToken(); - break; - case TokenKind.Lbrace: - value = p.parseArrayValues(); - break; - default: - break; - } - return value; -} - -fn u32 Parser.parseArrayValues(Parser* p) { - //printf("parseArrayValues()\n"); - p.consumeToken(); - u32 value = p.parseValue() | ValueIsArray; - while (p.tok.is(TokenKind.Comma)) { - p.consumeToken(); - if (p.tok.is(TokenKind.Rbrace)) break; // trailing comma is allowed - p.parseValue(); - } - p.expectAndConsume(TokenKind.Rbrace); - p.blocks.addNull(); - return value; -} - -fn u32 Parser.addTable(Parser* p, const char* name, u32 depth, bool isTop, NodeKind kind) { - //printf("addTable %s\n", name); - Blocks* blocks = p.blocks; - if (!isTop && p.numParents > depth && same(blocks.getName(p.parents[depth]), name)) { - if (getKind(p.parents[depth].nameOffset) == NodeKind.TableArray) return 1; - // Do nothing - } else { - if (kind == NodeKind.TableArray) { - // TODO also check if previous is also TableArray - if (p.numParents > depth && same(blocks.getName(p.parents[depth]), name)) { - p.numParents = depth + 1; - } else { - u32 off = blocks.addNode(name, kind); - if (p.numParents > depth) p.parents[depth].nextNode = off; - Node* node = &blocks.nodes[off]; - p.parents[depth] = node; - - if (p.lastChild[depth]) { - p.lastChild[depth].nextNode = off; - } else { - if (depth > 0) p.parents[depth - 1].child = off; - } - p.numParents = depth + 1; - p.topParent = node; - p.lastChild[depth] = node; - p.lastChild[depth + 1] = nil; - } - if (isTop) { - // add iterator node as child or next - u32 off = blocks.addNode("", NodeKind.ArrayChild); - Node* iter = &blocks.nodes[off]; - if (p.lastChild[depth].child) { // already has children - p.lastChild[depth + 1].nextNode = off; - } else { - p.lastChild[depth].child = off; - } - p.lastChild[depth + 1] = iter; - p.parents[depth + 1] = iter; - p.lastChild[depth + 2] = nil; - p.topParent = iter; - p.numParents++; - } - return 1; - } - u32 off = blocks.addNode(name, kind); - if (p.numParents > depth) p.parents[depth].nextNode = off; - Node* node = &blocks.nodes[off]; - p.parents[depth] = node; - - if (p.lastChild[depth]) { - p.lastChild[depth].nextNode = off; - } else { - if (depth > 0) p.parents[depth-1].child = off; - } - p.numParents = depth + 1; - p.topParent = node; - p.lastChild[depth] = node; - p.lastChild[depth + 1] = nil; - } - return 0; -} - -fn Location! Parser.consumeToken(Parser* p) -{ - Location prev = p.tok.loc; - try p.tokenizer.lex(&p.tok); - return prev; -} - -fn Token* Parser.nextToken(Parser* p) { - return p.tokenizer.lookahead(); -} - -fn void! Parser.expectAndConsume(Parser* p, TokenKind k) { - if (p.tok.isNot(k)) - { - sprintf(p.errorMsg, "expected '%s' at %s", token2str(k), p.tok.loc.str()); - longjmp(p.jump_err, 1); - } - try p.consumeToken(); -} - -fn void Parser.expect(Parser* p, TokenKind k) -{ - if (p.tok.isNot(k)) - { - sprintf(p.errorMsg, "expected '%s' at %s", token2str(k), p.tok.loc.str()); - longjmp(p.jump_err, 1); - } -} - -const u32 MaxDiag = 128; - -public struct TomlReader -{ - char[MaxDiag] message; - Blocks* blocks; -} - -public fn TomlReader* new_toml() -{ - TomlReader* r = @malloc(TomlReader); - r.blocks = @malloc(Blocks); - r.blocks.init(); - return r; -} - -public fn void TomlReader.destroy(TomlReader* r) -{ - r.blocks.destroy(); - free(r.blocks); - free(r); -} - -public fn const char* TomlReader.getMsg(const TomlReader* r) -{ - return r.message; -} - -error EmptyFileError; - -public fn void! TomlReader.parse(TomlReader* r, string filename) -{ - Reader file; - - try file.open(filename); - - defer file.close(); - - if (file.isEmpty()) - { - printf("file %s is empty\n", filename); - raise EmptyFileError; - } - - Parser parser; - parser.parse(file.data(), r.message, r.blocks); - -$if DEBUG_NODES: - r.blocks.dump(); -$endif - return status; -} - -// -------------------------------------------------------------- -// Getters+iters - -fn const Node* Reader.findNode(const Reader* r, const char* key) -{ - char[MaxText] name; - const char* cp = key; - const char* start = cp; - u32 len = 0; - Node* node = nil; - while (1) { - switch (*cp) { - case 0 - len = cast(cp - start); - mem::copy(name, start, len); - name[len] = 0; - node = r.blocks.findNode(name, node); - return node; - case '.': - len = cast(cp - start); - mem::copy(name, start, len); - name[len] = 0; - start = cp + 1; - node = r.blocks.findNode(name, node); - if (!node) return nil; - if (getKind(node.nameOffset) == NodeKind.Value) return nil; - break; - default: - break; - } - cp++; - } - return nil; -} - -public fn const char* Reader.getValue(const Reader* r, const char* key) { - const Node* node = r.findNode(key); - if (!node) return nil; - if (getKind(node.nameOffset) != NodeKind.Value) return nil; - ValueType t = getRawType(node.rawValue); - if (t != ValueType.Text) return nil; - return &r.blocks.values[getRawValue(node.rawValue)]; -} - -public fn bool Reader.getNumber(const Reader* r, const char* key, u32* result) { - const Node* node = r.findNode(key); - if (!node) return false; - if (getKind(node.nameOffset) != NodeKind.Value) return false; - ValueType t = getRawType(node.rawValue); - if (t != ValueType.Number) return false; - *result = getRawValue(node.rawValue); - return true; -} - -public fn bool Reader.getBool(const Reader* r, const char* key, bool* result) { - const Node* node = r.findNode(key); - if (!node) return false; - if (getKind(node.nameOffset) != NodeKind.Value) return false; - ValueType t = getRawType(node.rawValue); - if (t != ValueType.Boolean) return false; - *result = getRawValue(node.rawValue); - return true; -} - -public type NodeIter struct { - const Blocks* blocks; - const Node* node; -} - -public fn bool NodeIter.done(const NodeIter* i) { - return i.node == nil; -} - -public fn void NodeIter.next(NodeIter* i) { - if (i.node == nil) return; - u32 next = i.node.nextNode; - if (next == 0) i.node = nil; - else i.node = &i.blocks.nodes[next]; -} - -public fn const char* NodeIter.getValue(const NodeIter* i, const char* key) { - const Node* child = i.blocks.findNode(key, i.node); - if (!child) return nil; - if (getKind(child.nameOffset) != NodeKind.Value) return nil; - ValueType t = getRawType(child.rawValue); - if (t != ValueType.Text) return nil; - return &i.blocks.values[getRawValue(child.rawValue)]; -} - -public fn bool NodeIter.getNumber(const NodeIter* i, const char* key, u32* result) { - const Node* child = i.blocks.findNode(key, i.node); - if (!child) return false; - if (getKind(child.nameOffset) != NodeKind.Value) return false; - ValueType t = getRawType(child.rawValue); - if (t != ValueType.Number) return false; - *result = getRawValue(child.rawValue); - return true; -} - -public fn bool NodeIter.getBool(const NodeIter* i, const char* key, bool* result) { - const Node* child = i.blocks.findNode(key, i.node); - if (!child) return false; - if (getKind(child.nameOffset) != NodeKind.Value) return false; - ValueType t = getRawType(child.rawValue); - if (t != ValueType.Boolean) return false; - *result = getRawValue(child.rawValue); - return true; -} - -public fn NodeIter Reader.getNodeIter(const Reader* r, const char* key) { - const Node* node = r.findNode(key); - if (node && getKind(node.nameOffset) == NodeKind.TableArray) { - node = &r.blocks.nodes[node.child]; - } - NodeIter iter = { r.blocks, node} - return iter; -} - - -public type ValueIter struct { - const char* values; - bool isArray; -} - -fn ValueIter ValueIter.create(const char* values, bool isArray) { - ValueIter iter = { values, isArray } - return iter; -} - -public fn bool ValueIter.done(const ValueIter* i) { - return i.values[0] == 0; -} - -public fn void ValueIter.next(ValueIter* i) { - if (i.values[0] == 0) return; - while (i.values[0] != 0) i.values++; - if (i.isArray) i.values++; // skip 0-terminator -} - -public fn const char* ValueIter.getValue(const ValueIter* i) { - return i.values; -} - -public fn ValueIter Reader.getValueIter(const Reader* r, const char* key) { - const Node* node = r.findNode(key); - if (node) { - switch (getKind(node.nameOffset)) { - case NodeKind.Table: fallthrough; - case NodeKind.TableArray: - break; - case NodeKind.ValueArray: - // TODO support arrays of Numbers/Booleans as well - return ValueIter.create(&r.blocks.values[getRawValue(node.rawValue)], true); - case NodeKind.Value: - return ValueIter.create(&r.blocks.values[getRawValue(node.rawValue)], false); - case NodeKind.ArrayChild: - // TODO - break; - } - } - return ValueIter.create(&r.blocks.values[0], false); -} - - -// -------------------------------------------------------------- -// Blocks - -type NodeKind enum u8 { - Table = 0, - TableArray, - ValueArray, - Value, - ArrayChild, -} - -type ValueType enum u8 { - Text = 0, - Number, - Boolean, -} -const u32 ValueIsArray = (1 << 31); -const u32 ValueTypeOffset = 29; -const u32 RawValueMask = (0x7 << 29); - -fn const char* type2str(ValueType t) { - switch (t) { - case ValueType.Text: return "T"; - case ValueType.Number: return "N"; - case ValueType.Boolean: return "B"; - } - return ""; -} - - -public type Node struct { - u32 nameOffset; - u32 nextNode; - union { - u32 child; - u32 rawValue; // bit 31 isArray, bit 29-30 ValueType - } -} @(opaque, packed) - -public type Blocks struct { - Node* nodes; - u32 nodeCount; - - char* names; - u32 namesOffset; - u32 namesSize; - - u32[NamesCacheSize] namesCache; - u32 lastCache; - - char* values; - u32 valuesOffset; - u32 valuesSize; -} @(opaque) - -fn void Blocks.init(Blocks* b) { - mem::set(b, 0, sizeof(Blocks)); - b.nodes = calloc(MaxNodes, sizeof(Node)); - - b.namesSize = MaxNames; - b.names = calloc(1, b.namesSize); - b.names[0] = 0; - b.namesOffset = 1; // 0 indicates no name - - b.valuesSize = MaxValues; - b.values = calloc(1, b.valuesSize); - b.values[0] = 0; - b.valuesOffset = 1; // 0 indicates no value - - b.lastCache = 0; - //memset(b.namesCache, 0, sizeof(b.namesCache)); // sizeof(struct member) not supported yet - mem::set(b.namesCache, 0, sizeof(u32)*NamesCacheSize); -} - -fn void Blocks.destroy(Blocks* b) { - free(b.values); - free(b.names); - free(b.nodes); -} - -fn u32 Blocks.searchNameCache(Blocks* b, const char* name) { - for (u32 i=0; i(strlen(name)) + 1; - nameOffset = b.namesOffset; - node.nameOffset = nameOffset; - char* newname = &b.names[nameOffset]; - mem::copy(newname, name, len); - b.namesCache[b.lastCache] = nameOffset; - b.lastCache = (b.lastCache + 1) % NamesCacheSize; - b.namesOffset += len; - } - } - node.nameOffset = addKind(node.nameOffset, k); - return off; -} - -fn u32 Blocks.addValue(Blocks* b, const char* value) { - if (value[0] == 0) return 0; - u32 off = b.valuesOffset; - u32 len = cast(strlen(value)) + 1; - mem::copy(&b.values[off], value, len); - b.valuesOffset += len; - return off; -} - -fn void Blocks.addNull(Blocks* b) { - b.values[b.valuesOffset] = 0; - b.valuesOffset++; -} - -fn Node* Blocks.findNode(const Blocks* b, const char* name, const Node* parent) { - if (b.nodeCount == 0) return nil; - Node* node = &b.nodes[0]; - if (parent) { - if (!parent.child) return nil; - node = &b.nodes[parent.child]; - } - while (1) { - const char* nodeName = &b.names[getValue(node.nameOffset)]; - if (same(name, nodeName)) return node; - if (!node.nextNode) return nil; - node = &b.nodes[node.nextNode]; - } - return nil; -} - - - -const u32 NodeKindOffset = 29; - -fn u32 addKind(u32 value, NodeKind k) @(inline) { - return value | (k << NodeKindOffset); -} - -fn NodeKind getKind(u32 value) @(inline) { - return cast()(value >> NodeKindOffset); -} - -fn u32 getValue(u32 value) @(inline) { - return value & ~(0x7 << NodeKindOffset); -} diff --git a/resources/examples/notworking/toml_tokenizer_c2.c3 b/resources/examples/notworking/toml_tokenizer_c2.c3 deleted file mode 100644 index 663b53724..000000000 --- a/resources/examples/notworking/toml_tokenizer_c2.c3 +++ /dev/null @@ -1,357 +0,0 @@ -// This is the toml_tokenizer.c2 changed to c3 to compare -module toml; -import stdio; -import string; -import ctype; -import stdlib; - -const uint MaxText = 1024; - -enum TokenKind : char (VarString name) -{ - WORD("word"), - TEXT("text"), - NUMBER("number"), - KW_TRUE("true"), - KW_FALSE("false"), - LBRACE("["), - LBRACE2("[[") - RBRACE("]"), - RBRACE2("]]"), - EQUALS("="), - DOT("."), - COMMA(","), - EOF("eof"), - ERROR("error"), -} - -fn void Location.init(Location* l, uint line = 0, uint col = 0) -{ - l.line = line; - l.column = col; -} - -fn string Location.str(Location* l) -{ - static char[32] msg; - sprintf(msg, "line %u:%u", l.line, l.column); - return msg; -} - -struct Token -{ - Location loc; - TokenKind kind; - // TODO union? - union - { - string text; - uint number; - } -} - -fn void Token.init(Token* t) -{ - t.loc.init(0, 0); - t.kind = TokenKind.EOF; - t.text = nil; - t.number = 0; -} - -fn void Token.clear(Token* t) -{ - t.text = nil; - t.number = 0; -} - -fn void Token.setLocation(Token* t, Location l) -{ - t.loc = l; -} - -fn bool Token.is(Token* t, TokenKind k) -{ - return t.kind == k; -} - -fn bool Token.isNot(Token* t, TokenKind k) -{ - return t.kind != k; -} - -fn string Token.getName(Token* t) -{ - return t.kind.name; -} - -struct Tokenizer -{ - char* dataStart; - char* current; - Location loc; - char[MaxText] text; - Token nextToken; - bool haveNext; -} - -fn void Tokenizer.init(Tokenizer* t, char* input) -{ - t.dataStart = input; - t.current = input; - t.loc.init(1, 1); - t.haveNext = false; - t.text[0] = 0; -} - -error LexedEOF; -error LexError -{ - string error_message; -} - -fn void! Tokenizer.lex(Tokenizer* t, Token* result) -{ - if (t.haveNext) - { - // Q: ptr assign or copy? - *result = t.nextToken; - t.haveNext = false; - return; - } - result.clear(); - while (1) - { - switch (t.current[0]) - { - case 0: - return! LexedEOF(); - case '#': - if (t.loc.column != 1) - { - sprintf(t.text, "unexpected '#' after line start at %s", t.loc.str()); - return! LexError(t.text); - } - t.parseComment(); - case ' ': - case '\t': - t.advance(1); - case '\n': - t.current++; - t.loc.line++; - t.loc.column = 1; - case '=': - result.loc = t.loc; - result.kind = EQUALS; - t.advance(1); - return; - case '.': - result.loc = t.loc; - result.kind = DOT; - t.advance(1); - return; - case ',': - result.loc = t.loc; - result.kind = COMMA; - t.advance(1); - return; - case '[': - result.loc = t.loc; - if (t.current[1] == '[') - { - t.advance(2); - result.kind = LBRACE2; - } - else - { - t.advance(1); - result.kind = LBRACE; - } - return; - case ']': - result.loc = t.loc; - if (t.current[1] == ']') - { - t.advance(2); - result.kind = RBRACE2; - } - else - { - t.advance(1); - result.kind = RBRACE; - } - return; - case '"': - if (t.current[1] == '"' && t.current[2] == '"') - { - t.parseMultiText(result); - } - else - { - t.parseText(result); - } - return; - default: - // key or number - result.loc = t.loc; - if (isdigit(t.current[0])) - { - t.parseNumber(result); - return; - } - if (t.current[0] == 'f' && strncmp("false", t.current, 5) == 0) { - t.advance(5); - result.number = 0; - result.kind = KW_FALSE; - return; - } - if (t.current[0] == 't' && strncmp("true", t.current, 4) == 0) { - t.advance(4); - result.number = 1; - result.kind = KW_TRUE; - return; - } - if (isalpha(t.current[0])) - { - t.parseKey(result); - return; - } - sprintf(t.text, "unexpected char '%c' at %s", t.current[0], t.loc.str()); - return LexError(t.text); - } - } -} - -fn Token*! Tokenizer.lookahead(Tokenizer* t) -{ - if (!t.haveNext) - { - try t.lex(&t.nextToken); - t.haveNext = true; - } - return &t.nextToken; -} - -fn void Tokenizer.advance(Tokenizer* t, uint amount) -{ - t.loc.column += amount; - t.current += amount; -} - -fn void Tokenizer.parseComment(Tokenizer* t) -{ - while (1) - { - switch (t.current[0]) - { - case 0: - return; - case '\n': - t.current++; - t.loc.line++; - t.loc.column = 1; - return; - default: - t.current++; - t.loc.column++; - break; - } - } -} - -fn void Tokenizer.parseText(Tokenizer* t, Token* result) -{ - // TODO handle literal strings ' .. ' -> no escaping - // TODO handle escape chars for normal strings " .. \" \r \n " - t.advance(1); - result.loc = t.loc; - const char* start = t.current; - while (t.current[0] && t.current[0] != '"') t.current++; - - uint len = (uint)(t.current - start); - // assert(len < MaxText); - mem::copy(t.text as start, len); - t.text[len] = 0; - result.kind = TokenKind.Text; - result.text = t.text; - t.loc.column += len; - t.advance(1); -} - -fn void! Tokenizer.parseMultiText(Tokenizer* t, Token* result) -{ - t.advance(3); - if (t.current[0] == '\n') - { - t.current++; - t.loc.line++; - t.loc.column = 1; - } - result.loc = t.loc; - char* start = t.current; - while (1) - { - if (t.current[0] == 0) - { - sprintf(t.text, "missing end \"\"\" %s", t.loc.str()); - return! LexError(t.text); - } - if (t.current[0] == '\n') - { - t.loc.line++; - t.loc.column = 1; - } - else - { - t.loc.column++; - } - if (t.current[0] == '"' && t.current[1] == '"' && t.current[2] == '"') break; - t.current++; - } - - uint len = uint(t.current - start); - // assert(len < MaxText); - mem::copy(t.text, start, len); - t.text[len] = 0; - result.kind = TokenKind.Text; - result.text = t.text; - t.advance(3); -} - -fn void Tokenizer.parseNumber(Tokenizer* t, Token* result) -{ - // TODO handle prefix +/- - // handle hexadecimal/ocal/binary number - // handle '_', like 1_000_000 - - uint number = uint(atoi(t.current)); - result.kind = TokenKind.Number; - result.number = number; - while (t.current[0] && isdigit(t.current[0])) - { - t.current++; - t.loc.column++; - } -} - -fn bool isKeyChar(u8 c) -{ - if (c >= 128) return true; - if (isalpha(c)) return true; - if (isdigit(c)) return true; - if (c == '_' || c == '-') return true; - return false; -} - -fn void Tokenizer.parseKey(Tokenizer* t, Token* result) -{ - char* start = t.current; - while (t.current[0] && isKeyChar((char)(t.current[0]))) t.current++; - - uint len = (uint)(t.current - start); - // assert(len < MaxText); - mem::copy(t.text, start, len); - t.text[len] = 0; - result.kind = TokenKind.Word; - result.text = t.text; - t.loc.column += len; -} diff --git a/resources/examples/notworking/window.c3 b/resources/examples/notworking/window.c3 index d3d32fce3..58a9d73af 100644 --- a/resources/examples/notworking/window.c3 +++ b/resources/examples/notworking/window.c3 @@ -1,6 +1,6 @@ import gtk; -const string CLICK_ME = "Click Me"; +const String CLICK_ME = "Click Me"; uint counter = 0; fn void clickedme(GtkButton *o, void *d) @@ -8,11 +8,11 @@ fn void clickedme(GtkButton *o, void *d) (GtkLabel*)(d).set_text(string.format("You clicked me %d times", ++counter)); } -int main(int argc as string[] argv) +fn void main(int argc, char** argv) { - gtk::init(&argc, &argv); + gtk::init(argc, argv); - GtkWindow *win = gtk::windowCreate(GtkWindow::TOPLEVEL); + GtkWindow *win = gtk::windowCreate(GtkWindow.TOPLEVEL); win.set_title(CLICK_ME); GtkButton *button = gtk::buttonCreateWithLabel(CLICK_ME); @@ -31,5 +31,4 @@ int main(int argc as string[] argv) win.showAll(); gtk::main(); - return 0; } \ No newline at end of file