added: single quote character literals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 8 Mar 2023 12:24:45 +0000 (06:24 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 8 Mar 2023 12:24:45 +0000 (06:24 -0600)
changed: no re-declaration specifier is now `~`

18 files changed:
compiler/include/lex.h
compiler/src/lex.c
compiler/src/parser.c
core/conv/format.onyx
core/string/string.onyx
core/time/date.onyx
examples/50_misc.onyx
misc/onyx-mode.el
misc/onyx.sublime-syntax
misc/onyx.vim
misc/vscode/onyx-0.1.5.vsix
tests/aoc-2020/day11.onyx
tests/aoc-2020/day14.onyx
tests/aoc-2020/day17.onyx
tests/aoc-2020/day19.onyx
tests/aoc-2020/day20.onyx
tests/char_literals [new file with mode: 0644]
tests/char_literals.onyx [new file with mode: 0644]

index cd437ece6776251a44345fc878c41cb39378c91b..23818d58a11711dc768ed1a8ef9e745891ea91d3 100644 (file)
@@ -74,6 +74,7 @@ typedef enum TokenType {
 
     Token_Type_Symbol,
     Token_Type_Literal_String,
+    Token_Type_Literal_Char,
     Token_Type_Literal_Integer,
     Token_Type_Literal_Float,
     Token_Type_Literal_True,
index 46c466b91ce046076b277e4d2a8f8f8187e157e5..3e4a91c758e5ba5391b48fad2227ea553856ac1a 100644 (file)
@@ -71,6 +71,7 @@ static const char* token_type_names[] = {
 
     "TOKEN_TYPE_SYMBOL",
     "TOKEN_TYPE_LITERAL_STRING",
+    "TOKEN_TYPE_LITERAL_CHAR",
     "TOKEN_TYPE_LITERAL_INTEGER",
     "TOKEN_TYPE_LITERAL_FLOAT",
     "true",
@@ -243,14 +244,15 @@ whitespace_skipped:
         goto token_parsed;
     }
 
-    // String literal
-    if (*tk.text == '"') {
+    // String/Character literal
+    if (*tk.text == '"' || *tk.text == '\'') {
         u64 len = 0;
         u64 slash_count = 0;
 
+        char ch = *tk.text;
         INCREMENT_CURR_TOKEN(tokenizer);
 
-        while (!(*tokenizer->curr == '"' && slash_count == 0)) {
+        while (!(*tokenizer->curr == ch && slash_count == 0)) {
             len++;
 
             // if (*tokenizer->curr == '\n') {
@@ -270,7 +272,7 @@ whitespace_skipped:
         INCREMENT_CURR_TOKEN(tokenizer);
 
         tk.text++;
-        tk.type = Token_Type_Literal_String;
+        tk.type = ch == '"' ? Token_Type_Literal_String : Token_Type_Literal_Char;
         tk.length = len;
         goto token_parsed;
     }
index 465ae7938d90f452087fc13bfc81eeca2fcd4d4d..c6cbccceb96c15ce2d580232b141964cbb36c264 100644 (file)
@@ -605,6 +605,25 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             break;
         }
 
+        case Token_Type_Literal_Char: {
+            AstNumLit* char_lit = make_node(AstNumLit, Ast_Kind_NumLit);
+            char_lit->flags |= Ast_Flag_Comptime;
+            char_lit->type_node = (AstType *) &basic_type_int_unsized;
+            char_lit->token = expect_token(parser, Token_Type_Literal_Char);
+            char_lit->was_char_literal = 1;
+
+            i8 dest = '\0';
+            i32 length = string_process_escape_seqs((char *) &dest, char_lit->token->text, 1);
+            char_lit->value.i = (u32) dest;
+
+            if (length != 1) {
+                onyx_report_error(char_lit->token->pos, Error_Critical, "Expected only a single character in character literal.");
+            }
+
+            retval = (AstTyped *) char_lit;
+            break;
+        }
+
         case '#': {
             if (parse_possible_directive(parser, "file_contents")) {
                 AstFileContents* fc = make_node(AstFileContents, Ast_Kind_File_Contents);
@@ -1322,7 +1341,7 @@ static i32 parse_possible_compound_symbol_declaration(OnyxParser* parser, AstNod
     while (peek_token(token_offset)->type == Token_Type_Symbol) {
         token_offset += 1;
 
-        if (peek_token(token_offset)->type == '\'') token_offset += 1;
+        if (peek_token(token_offset)->type == '~') token_offset += 1;
 
         if (peek_token(token_offset)->type != ',') break;
         token_offset += 1;
@@ -1344,7 +1363,7 @@ static i32 parse_possible_compound_symbol_declaration(OnyxParser* parser, AstNod
         AstNode* sym_node = make_symbol(parser->allocator, local_sym);
         bh_arr_push(local_compound->exprs, (AstTyped *) sym_node);
 
-        if (!consume_token_if_next(parser, '\'')) {
+        if (!consume_token_if_next(parser, '~')) {
             AstLocal* new_local = make_local(parser->allocator, local_sym, NULL);
             if (prev_local == NULL) {
                 first_local = new_local;
@@ -1394,7 +1413,7 @@ static i32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret)
 
     // If the token after the symbol is a comma, assume this is a compound declaration.
     if (peek_token(1)->type == ',' ||
-        (peek_token(1)->type == '\'' && peek_token(2)->type == ',')) {
+        (peek_token(1)->type == '~' && peek_token(2)->type == ',')) {
         return parse_possible_compound_symbol_declaration(parser, ret);
     }
 
index e6e3a564ab1aa3b3be40999edbe638866379f438..3c0dc1459a71b5fd6d5bc5a52462bfbc623b8cab 100644 (file)
@@ -443,7 +443,7 @@ format_any :: (output: &Format_Output, formatting: &Format, v: any) {
         case u8 {
             value := *(cast(&u8) v.data);
 
-            if value > 31 {
+            if formatting.interpret_numbers {
                 output->write(value);
 
             } else {
index ba6e4c66db40e7da5be96ad74745859f47a891ef..07fa5d97cd3bde47d4fb12a268725f254689bd95 100644 (file)
@@ -651,6 +651,10 @@ bisect :: (s: str, substr: str) -> (str, str) {
 // Used by dyn_str
 //
 
+to_dyn_str :: (x: str, allocator := context.allocator) -> dyn_str {
+    return (package core.array).make(x, allocator);
+}
+
 delete  :: macro (x: &dyn_str, idx: u32) -> u8 {
     return (package core.array).delete(x, idx);
 }
index ec86541473c0cbcb93d912e962b815275e563afa..9e2e99cdd9c441fdafd6b98f13b293b8c78b1c68 100644 (file)
@@ -81,8 +81,8 @@ Date :: struct {
 @conv.Custom_Parse_Proc.{ Date }
 (d: &Date, text: str, _: Allocator) -> bool {
     year,  t  := string.bisect(text, #char "-");
-    month, t' := string.bisect(t,    #char "-");
-    day,   t' := string.bisect(t,    #char "-");
+    month, t~ := string.bisect(t,    #char "-");
+    day,   t~ := string.bisect(t,    #char "-");
 
     d.year  = ~~  conv.str_to_i64(year);
     d.month = ~~ (conv.str_to_i64(month) - 1);
index feb89ef5d2f80578469b03b6a39087ce529b525a..4b0e4b753d79f028d72d1ed30db1a3581d9cf434 100644 (file)
@@ -47,10 +47,10 @@ multiple_declaration_improvements :: () {
     // You're trying to declare a new variable k, while using the old variable
     // s in the same declaration. To get around this issue, there is a special
     // syntax you can use that tell the compiler that s is a not a new
-    // variable, but the same one as above. You simple place a ' after the
+    // variable, but the same one as above. You simple place a ~ after the
     // variable that you want to reuse.
 
-    k, s' := multiple_returns();
+    k, s~ := multiple_returns();
     printf("k: {}\ns: {}\n\n", k, s);
 
     //
index 5f8e5ab67e9e50a5d7599825ac5467d924678969..338e7c4d74162e9232ebec0cf3870f6ac1fb21d1 100644 (file)
@@ -97,6 +97,8 @@
     ;; Strings
     ("\\\".*\\\"" . font-lock-string-face)
 
+    ("\\\'.*\\\'" . font-lock-string-face)
+
     ;; Numbers
     (,(onyx-wrap-word-rx onyx-number-rx) . font-lock-constant-face)
 
index 1bbf0fea98004965fcbd8ca08eee52fd6c07d9d3..3f917e2857ac40f36b03132a81fc73f48c19d919 100644 (file)
@@ -15,6 +15,9 @@ contexts:
     - match: '"'
       scope: punctuation.definition.string.begin.onyx
       push: double_quoted_string
+    - match: "'"
+      scope: punctuation.definition.string.begin.onyx
+      push: single_quoted_string
 
     # Comments begin with a '//' and finish at the end of the line
     - match: '//'
@@ -92,6 +95,14 @@ contexts:
     #     1: variable
     #     2: variable
 
+  single_quoted_string:
+    - meta_scope: string.quoted.single.onyx
+    - match: '\\.'
+      scope: constant.character.escape.onyx
+    - match: "'"
+      scope: punctuation.definition.string.end.onyx
+      pop: true
+
   double_quoted_string:
     - meta_scope: string.quoted.double.onyx
     - match: '\\.'
index 53eccd91ceb0af812aa128594761045c48de6f3c..0eb3647a96ba6be7e24a3864ba545195796faf86 100644 (file)
@@ -49,6 +49,7 @@ syn match onyxDirective         "\#[a-zA-Z_]\+"
 syn match onyxTag               "@[a-zA-Z0-9_]\+"
 
 syn region onyxString              start=+"+ skip=+\\\\\|\\"+ end=+"\|$+ extend contains=@Spell
+syn region onyxString           start=+'+ skip=+\\\\\|\\'+ end=+'\|$+ extend contains=@Spell
 syn region onyxMultiString      start=+"""+ end=+"""+ extend contains=@Spell
 
 hi def link onyxKeyword          Statement
index 82722466d1202c47bded8a01025f07baa107567a..e0dbf32bf12798099c1d710523401f74f33ea430 100644 (file)
Binary files a/misc/vscode/onyx-0.1.5.vsix and b/misc/vscode/onyx-0.1.5.vsix differ
index e8be0fa71a68e53197d99a09b6ad260974e5ed1c..ca09764b67ef725eae0b85f7c832f57e03bc61c5 100644 (file)
@@ -76,7 +76,7 @@ main :: (args: [] cstr) {
     gos.height = 0;
 
     while !string.empty(file) {
-        line, file' := string.bisect(file, #char "\n");
+        line, file~ := string.bisect(file, #char "\n");
         for ch: line do switch ch {
             case #char "." do array.push(&gos.seats, SeatState.Floor);
             case #char "L" do array.push(&gos.seats, SeatState.Empty);
index 080c7c1cefec387cc714615f17730e2f9bfdf6f5..f031e09b740ff3b66022ddf560ccc5a9dd1d78a6 100644 (file)
@@ -89,7 +89,7 @@ main :: (args: [] cstr) {
             string.advance(&file, 3);
 
                        i := 35;
-            m, file' := string.bisect(file, #char "\n");
+            m, file~ := string.bisect(file, #char "\n");
             for ch: m {
                                switch ch {
                                        case #char "0" do mask[i] = 0;
index 59f7709183e88bb4f5a6a9f83075d464f4b2d7ae..eb3ef5968ea2f18554c7bb6b481fc827c485d2f7 100644 (file)
@@ -60,7 +60,7 @@ main :: (args: [] cstr) {
 
     z := 0;
     while !string.empty(file) {
-        line, file' := string.bisect(file, #char "\n");
+        line, file~ := string.bisect(file, #char "\n");
 
         x := 0;
         for ch: line {
index 6d14bfb536de0b96d9b29285e6ab1aa90af38c5a..955f5602d74369dabcfbd8d83539f29ddd3f2410 100644 (file)
@@ -162,7 +162,7 @@ main :: (args: [] cstr) {
     valid_count := 0;
     string.advance_line(&file);
     while !string.empty(file) {
-        line, file' := string.bisect(file, #char "\n");
+        line, file~ := string.bisect(file, #char "\n");
         if cyk_algorithm(&grammar, line) do valid_count += 1;
     }
 
index 7a4eecd413d2d1c539f22a33c13d8a60b3054fd3..7ddf6a8a52e5cba099a5632b508ae80cae8d62d2 100644 (file)
@@ -267,7 +267,7 @@ main :: (args: [] cstr) {
                td := cast(&bool) raw_alloc(tile_allocator, sizeof TileData);
 
                for y: 0 .. 10 {
-                       line, file' := string.bisect(file, #char "\n");
+                       line, file~ := string.bisect(file, #char "\n");
 
                        for x: 0 .. 10 {
                                td[x + y * TILE_DATA_WIDTH] = (line[x] == #char "#");
diff --git a/tests/char_literals b/tests/char_literals
new file mode 100644 (file)
index 0000000..03d094e
--- /dev/null
@@ -0,0 +1,4 @@
+az
+r is the 17 of the alphabet.
+
+Something else
diff --git a/tests/char_literals.onyx b/tests/char_literals.onyx
new file mode 100644 (file)
index 0000000..af73600
--- /dev/null
@@ -0,0 +1,20 @@
+use core
+
+
+main :: () {
+    s: dyn_str;
+    defer string.free(&s);
+
+    string.append(&s, .['a', 'z']);
+
+    println(s);
+
+
+
+    x := 'r' - 'a';
+    printf("{} is the {} of the alphabet.\n", 'r', x);
+
+    a_newline := '\n';
+    printf("{}", a_newline);
+    println("Something else");
+}
\ No newline at end of file