]> ocean-lang.org Git - ocean/blobdiff - csrc/oceani.mdc
parsergen: require all terms to be declared if any are.
[ocean] / csrc / oceani.mdc
index 520212be6d144365a586638bf695098689460058..3474508cf6a7018b186c795196f1822ee1332116 100644 (file)
@@ -287,14 +287,6 @@ consistent across all the branches.  When the variable is not used
 outside the if, the variables in the different branches are distinct
 and can be of different types.
 
 outside the if, the variables in the different branches are distinct
 and can be of different types.
 
-Determining the types of all variables early is important for
-processing command line arguments.  These can be assigned to any of
-several types of variable, but we must first know the correct type so
-any required conversion can happen.  If a variable is associated with
-a command line argument but no type can be interpreted (e.g. the
-variable is only ever used in a `print` statement), then the type is
-set to 'string'.
-
 Undeclared names may only appear in "use" statements and "case" expressions.
 These names are given a type of "label" and a unique value.
 This allows them to fill the role of a name in an enumerated type, which
 Undeclared names may only appear in "use" statements and "case" expressions.
 These names are given a type of "label" and a unique value.
 This allows them to fill the role of a name in an enumerated type, which
@@ -407,11 +399,11 @@ various entities.
 ### Types
 
 Values come in a wide range of types, with more likely to be added.
 ### Types
 
 Values come in a wide range of types, with more likely to be added.
-Each type needs to be able to parse and print its own values (for
-convenience at least) as well as to compare two values, at least for
-equality and possibly for order.  For now, values might need to be
-duplicated and freed, though eventually such manipulations will be
-better integrated into the language.
+Each type needs to be able to print its own values (for convenience at
+least) as well as to compare two values, at least for equality and
+possibly for order.  For now, values might need to be duplicated and
+freed, though eventually such manipulations will be better integrated
+into the language.
 
 Rather than requiring every numeric type to support all numeric
 operations (add, multiple, etc), we allow types to be able to present
 
 Rather than requiring every numeric type to support all numeric
 operations (add, multiple, etc), we allow types to be able to present
@@ -437,7 +429,6 @@ Named type are stored in a simple linked list.  Objects of each type are
                struct type *next;
                int size, align;
                void (*init)(struct type *type, struct value *val);
                struct type *next;
                int size, align;
                void (*init)(struct type *type, struct value *val);
-               int (*parse)(struct type *type, char *str, struct value *val);
                void (*print)(struct type *type, struct value *val);
                void (*print_type)(struct type *type, FILE *f);
                int (*cmp_order)(struct type *t1, struct type *t2,
                void (*print)(struct type *type, struct value *val);
                void (*print_type)(struct type *type, FILE *f);
                int (*cmp_order)(struct type *t1, struct type *t2,
@@ -541,14 +532,6 @@ Named type are stored in a simple linked list.  Objects of each type are
                        printf("*Unknown*");            // NOTEST
        }
 
                        printf("*Unknown*");            // NOTEST
        }
 
-       static int parse_value(struct type *type, char *arg, 
-                              struct value *val)
-       {
-               if (type && type->parse)
-                       return type->parse(type, arg, val);
-               return 0;                               // NOTEST
-       }
-
        static struct value *val_alloc(struct type *t, struct value *init)
        {
                struct value *ret;
        static struct value *val_alloc(struct type *t, struct value *init)
        {
                struct value *ret;
@@ -574,7 +557,6 @@ Named type are stored in a simple linked list.  Objects of each type are
        static int value_cmp(struct type *tl, struct type *tr,
                             struct value *left, struct value *right);
        static void print_value(struct type *type, struct value *v);
        static int value_cmp(struct type *tl, struct type *tr,
                             struct value *left, struct value *right);
        static void print_value(struct type *type, struct value *v);
-       static int parse_value(struct type *type, char *arg, struct value *val);
 
 ###### free context types
 
 
 ###### free context types
 
@@ -627,9 +609,6 @@ A separate function encoding these cases will simplify some code later.
                return require == have;
        }
 
                return require == have;
        }
 
-When assigning command line arguments to variables, we need to be able
-to parse each type from a string.
-
 ###### includes
        #include <gmp.h>
        #include "parse_string.h"
 ###### includes
        #include <gmp.h>
        #include "parse_string.h"
@@ -747,57 +726,10 @@ to parse each type from a string.
                }
        }
 
                }
        }
 
-       static int _parse_value(struct type *type, char *arg, struct value *val)
-       {
-               struct text tx;
-               int neg = 0;
-               char tail[3] = "";
-
-               switch(type->vtype) {
-               case Vlabel:                            // NOTEST
-               case Vnone:                             // NOTEST
-                       return 0;                       // NOTEST
-               case Vstr:
-                       val->str.len = strlen(arg);
-                       val->str.txt = malloc(val->str.len);
-                       memcpy(val->str.txt, arg, val->str.len);
-                       break;
-               case Vnum:
-                       if (*arg == '-') {
-                               neg = 1;
-                               arg++;
-                       }
-                       tx.txt = arg; tx.len = strlen(tx.txt);
-                       if (number_parse(val->num, tail, tx) == 0)
-                               mpq_init(val->num);
-                       else if (neg)
-                               mpq_neg(val->num, val->num);
-                       if (tail[0]) {
-                               printf("Unsupported suffix: %s\n", arg);
-                               return 0;
-                       }
-                       break;
-               case Vbool:
-                       if (strcasecmp(arg, "true") == 0 ||
-                           strcmp(arg, "1") == 0)
-                               val->bool = 1;
-                       else if (strcasecmp(arg, "false") == 0 ||
-                                strcmp(arg, "0") == 0)
-                               val->bool = 0;
-                       else {
-                               printf("Bad bool: %s\n", arg);
-                               return 0;
-                       }
-                       break;
-               }
-               return 1;
-       }
-
        static void _free_value(struct type *type, struct value *v);
 
        static struct type base_prototype = {
                .init = _val_init,
        static void _free_value(struct type *type, struct value *v);
 
        static struct type base_prototype = {
                .init = _val_init,
-               .parse = _parse_value,
                .print = _print_value,
                .cmp_order = _value_cmp,
                .cmp_eq = _value_cmp,
                .print = _print_value,
                .cmp_order = _value_cmp,
                .cmp_eq = _value_cmp,
@@ -1650,6 +1582,9 @@ make a copy of an array with controllable recursive depth.
                .free = array_free,
        };
 
                .free = array_free,
        };
 
+###### declare terminals
+       $TERM [ ]
+
 ###### type grammar
 
        | [ NUMBER ] Type ${
 ###### type grammar
 
        | [ NUMBER ] Type ${
@@ -1886,6 +1821,9 @@ function will be needed.
                free(e);
                break;
 
                free(e);
                break;
 
+###### declare terminals
+       $TERM struct .
+
 ###### variable grammar
 
        | Variable . IDENTIFIER ${ {
 ###### variable grammar
 
        | Variable . IDENTIFIER ${ {
@@ -2132,6 +2070,8 @@ an executable.
 
 ###### Grammar
 
 
 ###### Grammar
 
+       $TERM True False
+
        $*val
        Value ->  True ${
                        $0 = new_val(Tbool, $1);
        $*val
        Value ->  True ${
                        $0 = new_val(Tbool, $1);
@@ -2253,6 +2193,8 @@ link to find the primary instance.
 
 ###### Grammar
 
 
 ###### Grammar
 
+       $TERM : ::
+
        $*var
        VariableDecl -> IDENTIFIER : ${ {
                struct variable *v = var_decl(c, $1.txt);
        $*var
        VariableDecl -> IDENTIFIER : ${ {
                struct variable *v = var_decl(c, $1.txt);
@@ -2772,9 +2714,14 @@ expression operator, and the `CMPop` non-terminal will match one of them.
 
 ### Expressions: The rest
 
 
 ### Expressions: The rest
 
-The remaining expressions with the highest precedence are arithmetic and
-string concatenation.  String concatenation (`++`) has the same
-precedence as multiplication and division, but lower than the uniary.
+The remaining expressions with the highest precedence are arithmetic,
+string concatenation, and string conversion.  String concatenation
+(`++`) has the same precedence as multiplication and division, but lower
+than the uniary.
+
+String conversion is a temporary feature until I get a better type
+system.  `$` is a prefix operator which expects a string and returns
+a number.
 
 `+` and `-` are both infix and prefix operations (where they are
 absolute value and negation).  These have different operator names.
 
 `+` and `-` are both infix and prefix operations (where they are
 absolute value and negation).  These have different operator names.
@@ -2788,12 +2735,13 @@ should only insert brackets were needed for precedence.
        Times, Divide, Rem,
        Concat,
        Absolute, Negate,
        Times, Divide, Rem,
        Concat,
        Absolute, Negate,
+       StringConv,
        Bracket,
 
 ###### expr precedence
        $LEFT + - Eop
        $LEFT * / % ++ Top
        Bracket,
 
 ###### expr precedence
        $LEFT + - Eop
        $LEFT * / % ++ Top
-       $LEFT Uop
+       $LEFT Uop $
        $TERM ( )
 
 ###### expression grammar
        $TERM ( )
 
 ###### expression grammar
@@ -2834,6 +2782,7 @@ should only insert brackets were needed for precedence.
 
        Uop ->    + ${ $0.op = Absolute; }$
                | - ${ $0.op = Negate; }$
 
        Uop ->    + ${ $0.op = Absolute; }$
                | - ${ $0.op = Negate; }$
+               | $ ${ $0.op = StringConv; }$
 
        Top ->    * ${ $0.op = Times; }$
                | / ${ $0.op = Divide; }$
 
        Top ->    * ${ $0.op = Times; }$
                | / ${ $0.op = Divide; }$
@@ -2862,14 +2811,15 @@ should only insert brackets were needed for precedence.
                if (bracket) printf(")");
                break;
        case Absolute:
                if (bracket) printf(")");
                break;
        case Absolute:
-               if (bracket) printf("(");
-               printf("+");
-               print_exec(b->right, indent, bracket);
-               if (bracket) printf(")");
-               break;
        case Negate:
        case Negate:
+       case StringConv:
                if (bracket) printf("(");
                if (bracket) printf("(");
-               printf("-");
+               switch (b->op) {
+               case Absolute:   fputs("+", stdout); break;
+               case Negate:     fputs("-", stdout); break;
+               case StringConv: fputs("$", stdout); break;
+               default: abort();       // NOTEST
+               }                       // NOTEST
                print_exec(b->right, indent, bracket);
                if (bracket) printf(")");
                break;
                print_exec(b->right, indent, bracket);
                if (bracket) printf(")");
                break;
@@ -2906,6 +2856,15 @@ should only insert brackets were needed for precedence.
                                   Tstr, rules, type);
                return Tstr;
 
                                   Tstr, rules, type);
                return Tstr;
 
+       case StringConv:
+               /* op must be string, result is number */
+               propagate_types(b->left, c, ok, Tstr, 0);
+               if (!type_compat(type, Tnum, 0))
+                       type_err(c,
+                         "error: Can only convert string to number, not %1",
+                               prog, type, 0, NULL);
+               return Tnum;
+
        case Bracket:
                return propagate_types(b->right, c, ok, type, 0);
 
        case Bracket:
                return propagate_types(b->right, c, ok, type, 0);
 
@@ -2963,6 +2922,27 @@ should only insert brackets were needed for precedence.
                rvtype = Tstr;
                rv.str = text_join(left.str, right.str);
                break;
                rvtype = Tstr;
                rv.str = text_join(left.str, right.str);
                break;
+       case StringConv:
+               right = interp_exec(b->right, &rvtype);
+               rtype = Tstr;
+               rvtype = Tnum;
+
+               struct text tx = right.str;
+               char tail[3];
+               int neg = 0;
+               if (tx.txt[0] == '-') {
+                       neg = 1;
+                       tx.txt++;
+                       tx.len--;
+               }
+               if (number_parse(rv.num, tail, tx) == 0)
+                       mpq_init(rv.num);
+               else if (neg)
+                       mpq_neg(rv.num, rv.num);
+               if (tail[0])
+                       printf("Unsupported suffix: %.*s\n", tx.len, tx.txt);
+
+               break;
 
 ###### value functions
 
 
 ###### value functions
 
@@ -3032,11 +3012,10 @@ is in-place.
 ###### Binode types
        Block,
 
 ###### Binode types
        Block,
 
-###### expr precedence
-       $TERM pass
-
 ###### Grammar
 
 ###### Grammar
 
+       $TERM { } ;
+
        $*binode
        Block -> { IN OptNL Statementlist OUT OptNL } ${ $0 = $<Sl; }$
                | { SimpleStatements } ${ $0 = reorder_bilist($<SS); }$
        $*binode
        Block -> { IN OptNL Statementlist OUT OptNL } ${ $0 = $<Sl; }$
                | { SimpleStatements } ${ $0 = reorder_bilist($<SS); }$
@@ -3106,6 +3085,7 @@ is in-place.
                        $0->right = $<1;
                        }$
 
                        $0->right = $<1;
                        }$
 
+       $TERM pass
        SimpleStatement -> pass ${ $0 = NULL; }$
                | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$
                ## SimpleStatement Grammar
        SimpleStatement -> pass ${ $0 = NULL; }$
                | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$
                ## SimpleStatement Grammar
@@ -3281,6 +3261,9 @@ it is declared, and error will be raised as the name is created as
        Assign,
        Declare,
 
        Assign,
        Declare,
 
+###### declare terminals
+       $TERM =
+
 ###### SimpleStatement Grammar
        | Variable = Expression ${
                        $0 = new(binode);
 ###### SimpleStatement Grammar
        | Variable = Expression ${
                        $0 = new(binode);
@@ -3951,6 +3934,8 @@ various declarations in the parse context.
        $void
        Ocean -> OptNL DeclarationList
 
        $void
        Ocean -> OptNL DeclarationList
 
+       ## declare terminals
+
        OptNL ->
                | OptNL NEWLINE
        Newlines -> NEWLINE
        OptNL ->
                | OptNL NEWLINE
        Newlines -> NEWLINE
@@ -3994,6 +3979,8 @@ searching through for the Nth constant for decreasing N.
 
 ###### top level grammar
 
 
 ###### top level grammar
 
+       $TERM const
+
        DeclareConstant -> const { IN OptNL ConstList OUT OptNL } Newlines
                | const { SimpleConstList } Newlines
                | const IN OptNL ConstList OUT Newlines
        DeclareConstant -> const { IN OptNL ConstList OUT OptNL } Newlines
                | const { SimpleConstList } Newlines
                | const IN OptNL ConstList OUT Newlines
@@ -4100,6 +4087,8 @@ analysis is a bit more interesting at this level.
                        c->prog = $<1;
        } }$
 
                        c->prog = $<1;
        } }$
 
+       $TERM program
+
        $*binode
        Program -> program OpenScope Varlist ColonBlock Newlines ${
                $0 = new(binode);
        $*binode
        Program -> program OpenScope Varlist ColonBlock Newlines ${
                $0 = new(binode);
@@ -4209,8 +4198,9 @@ analysis is a bit more interesting at this level.
                                v->var->val = vl;
                        }
                        free_value(v->var->type, vl);
                                v->var->val = vl;
                        }
                        free_value(v->var->type, vl);
-                       if (!parse_value(v->var->type, argv[0], vl))
-                               exit(1);
+                       vl->str.len = strlen(argv[0]);
+                       vl->str.txt = malloc(vl->str.len);
+                       memcpy(vl->str.txt, argv[0], vl->str.len);
                        argv++;
                }
                v = interp_exec(p->right, &vtype);
                        argv++;
                }
                v = interp_exec(p->right, &vtype);
@@ -4248,11 +4238,13 @@ things which will likely grow as the languages grows.
                name:string
                alive:Boolean
 
                name:string
                alive:Boolean
 
-       program A B:
+       program Astr Bstr:
                print "Hello World, what lovely oceans you have!"
                print "Are there", five, "?"
                print pi, pie, "but", cake
 
                print "Hello World, what lovely oceans you have!"
                print "Are there", five, "?"
                print pi, pie, "but", cake
 
+               A := $Astr; B := $Bstr
+
                /* When a variable is defined in both branches of an 'if',
                 * and used afterwards, the variables are merged.
                 */
                /* When a variable is defined in both branches of an 'if',
                 * and used afterwards, the variables are merged.
                 */