ospl 0.2.0

the (UNFINISHED!!!) OSPL programming language
Documentation

            // CFFI load literal
            if self.match_next(Self::OSPL_CFFI_LOAD_KW) {
                self.skip_ws();
                let path = self.expr()
                    .unwrap_or_else(|| self.parse_error("expected path after CFFI_Load"));
                lhs = self.new_spanned_expr(
                    Expr::CffiLoad { path: Box::new(path) }
                );
                continue;
            }

            // CFFI function binding
            if self.match_next(Self::OSPL_CFFI_FN_KW) {
                self.skip_ws();

                let target_expr = self.expr()
                    .unwrap_or_else(|| self.parse_error("expected expression after ?!CFFI_Fn"));

                self.skip_ws();
                self.expect_char('(')
                    .unwrap_or_else(|| self.parse_error("expected '(' before argument type list"));

                let mut arg_types = Vec::new();
                loop {
                    self.skip_ws();
                    if self.peek_or_consume(')') { break; }

                    let ty = self.identifier()
                        .unwrap_or_else(|| self.parse_error("expected argument type identifier"));
                    arg_types.push(ty);

                    self.skip_ws();
                    if self.peek_or_consume(',') {
                        continue;
                    } else if self.peek_or_consume(')') {
                        break;
                    } else {
                        self.parse_error("expected ',' or ')' in argument type list");
                    }
                }

                self.skip_ws();
                self.match_next("-> ")
                    .then_some(())
                    .unwrap_or_else(|| self.parse_error("expected '->' before return type"));

                self.skip_ws();
                let return_type = self.identifier()
                    .unwrap_or_else(|| self.parse_error("expected return type identifier"));

                lhs = self.new_spanned_expr(
                    Expr::CffiFn {
                        target: Box::new(target_expr),
                        arg_types,
                        return_type,
                    }
                );
                continue;
            }