15#define try_get_float(from, bind_to, do_) \
16 if (sscanf(from, "%lf", &bind_to) == 1) { \
20#define PS_GROUP_MISMATCH_REFER(tkn) \
21 ps_error(PS_SCOPE_NOTE, PS_ECODE_MISMATCH, ts->file_ctx->buffer, \
22 (tkn)->loc, (tkn)->length, "to match opening parentheses", \
23 "Group opened here", NULL)
25#define PS_END_STM(ctx) \
27 if (!ps_tstream_peek(ts, 0, PS_TOKEN_RBRACE)) { \
28 match(PS_TOKEN_NL, "at end of let statement") else { \
43 PS_TOKEN_LIT_STR_INTERP,
51 PS_TOKEN_FUNC_PRIVATE,
59static void ps_parser_skip(
struct ps_tstream* ts) {
83 match(PS_TOKEN_COMMA,
"separating tuple type elements")
else {
90 match(PS_TOKEN_RPAR,
"at end of tuple")
else {
102 "where type was expected", NULL);
105 switch (token->
type) {
109 case PS_TOKEN_LIT_UNIT:
115 ps_error(PS_SCOPE_ERROR, PS_ECODE_INVALID_TYPE,
117 "Invalid start of type", NULL, NULL);
140 bindmatch(next, PS_TOKEN_ID,
"after '::' in name")
else {
171 match(PS_TOKEN_RBRACE,
"at end of block")
else {
185 bool is_mutable =
false;
192 bindmatch(name, PS_TOKEN_ID,
"for variable name")
else {
207 match(PS_TOKEN_ASSIGN,
"in let statement")
else {
223#define _PS_IS_FN_QUAL() \
224 (ps_tstream_peek(ts, 0, PS_TOKEN_FUNC_INLINE) \
225 || ps_tstream_peek(ts, 0, PS_TOKEN_FUNC_PRIVATE) \
226 || ps_tstream_peek(ts, 0, PS_TOKEN_FUNC_PUBLIC) \
227 || ps_tstream_peek(ts, 0, PS_TOKEN_FUNC_STATIC))
243 "as function qualifier")
else {
246 switch (qualifier->type) {
247 case PS_TOKEN_FUNC_INLINE:
250 case PS_TOKEN_FUNC_PRIVATE:
254 case PS_TOKEN_FUNC_PUBLIC:
257 case PS_TOKEN_FUNC_STATIC:
265 match(PS_TOKEN_FUNC,
"after function qualifiers")
else {
270 bindmatch(name, PS_TOKEN_ID,
"for function name")
else {
281 bindmatch(open, PS_TOKEN_LPAR,
"after function name")
else {
292 match(PS_TOKEN_COLON,
"after argument name")
else {
304 .
name = param_name->
start, .type = param_type};
316 match(PS_TOKEN_RPAR,
"after arguments")
else {
326 struct ps_type* ret_type = NULL;
349 bindmatch(first, PS_TOKEN_ID,
"to start name")
else {
368 bindmatch(name, PS_TOKEN_ID,
"for external function name")
else {
444 struct ps_node_block* else_block = NULL;
501 if (!following_expr) {
504 ps_push(&
string, following_expr);
509 bindmatch(end_str_literal, PS_TOKEN_LIT_STR,
510 "at end of interpolated string")
else {
520 bindmatch_any(token, literals_token_types,
"in expression literal")
else {
525 switch (token->type) {
526 case PS_TOKEN_LIT_UNIT:
528 case PS_TOKEN_LIT_BIN:
531 case PS_TOKEN_LIT_OCT:
534 case PS_TOKEN_LIT_DEC:
536 case PS_TOKEN_LIT_HEX:
539 case PS_TOKEN_LIT_FLT: {
544 if (!eof() && tcur()->type == PS_TOKEN_E) {
546 bindmatch(exp_token, PS_TOKEN_LIT_DEC,
547 "for scientific notation exponent") else {
550 i64 exp_value = strtoll(exp_token->start, NULL, 10);
551 float_val *= pow(10.0, exp_value);
556 ps_abort(
"lexer tokenized invalid floating point literal");
560 case PS_TOKEN_LIT_CHR:
562 case PS_TOKEN_LIT_STR:
564 case PS_TOKEN_LIT_STR_INTERP: {
568 case PS_TOKEN_LIT_FALSE:
570 case PS_TOKEN_LIT_TRUE:
595 match(PS_TOKEN_COMMA,
"between arguments")
else {
602 match(PS_TOKEN_RPAR,
"at end of call")
else {
613 "where expression was expected", NULL);
626 "Binary operator used as unary", NULL);
635 if (cur->
type == PS_TOKEN_LPAR) {
646 bindmatch(rpar, PS_TOKEN_RPAR,
"in expression")
else {
655 if (cur->
type == PS_TOKEN_ID) {
680 struct ps_token* old_lookahead = lookahead;
726 case PS_TOKEN_FUNC_STATIC:
727 case PS_TOKEN_FUNC_INLINE:
728 case PS_TOKEN_FUNC_PRIVATE:
729 case PS_TOKEN_FUNC_PUBLIC:
732 case PS_TOKEN_IMPORT:
734 case PS_TOKEN_EXTERN:
736 case PS_TOKEN_LBRACE: {
740 case PS_TOKEN_STRUCT:
761struct ps_node_arr*
ps_parse(
struct ps_token_arr* tokens,
783 PS_LOC_NONE(), 1,
"Stopping after max errors received.",
Defines assertion and abortion functionality.
#define ps_abort(msg)
Aborts the program with the given message.
#define ps_assert(cond, msg)
Asserts the given condition cond, aborting via ps_abort with the given msg otherwise.
#define PS_NO_IMPL()
Aborts the program due to a function taking a path not yet implemented.
Defines an arena allocator for the compiler.
#define ast_sprintf(fmt,...)
struct ps_expr * ps_expr_lit_new_f64(f64 value, struct ps_token *token)
Creates a new literal expression for a floating point number (of at most 64 bits).
struct ps_expr * ps_expr_unary_new(struct ps_token *op, struct ps_expr *rhs)
Creates a new unary expression.
struct ps_expr * ps_expr_lit_new_unit(struct ps_token *token)
Creates a new literal expression for a unit literal.
struct ps_expr * ps_expr_lit_new_u64(u64 value, struct ps_token *token)
Creates a new literal expression for an unsigned integer (of at most 64 bits).
struct ps_node * ps_node_return_new(struct ps_expr *value)
Creates a new return statement that returns the expression value.
struct ps_expr * ps_expr_lit_new_bool(bool value, struct ps_token *token)
Creates a new literal expression for a boolean.
struct ps_node * ps_node_extern_new(struct ps_token *name, struct ps_type_tuple *sig)
struct ps_node * ps_node_let_new(struct ps_token *name, bool is_mutable, struct ps_type *type, struct ps_expr *value)
Creates a new let statement initializing the variable name to the expression value.
struct ps_node * ps_node_expr_stm_new(struct ps_expr *expr)
Creates a new expression statement for expr.
struct ps_expr * ps_expr_lit_new_i64(i64 value, struct ps_token *token)
Creates a new literal expression for a signed integer (of at most 64 bits).
struct ps_expr * ps_expr_call_new(struct ps_token *callee, struct ps_expr_arr *args)
Creates a new call expression.
struct ps_expr * ps_expr_lit_new_str(STR value, struct ps_token *token)
Creates a new literal expression for a string.
struct ps_node * ps_node_fn_new(struct ps_token *name, struct ps_type *ret_type, struct ps_type_field_arr *params, enum ps_fn_qualifiers qualifiers, struct ps_node_block *body)
Creates a new function with the given name name, parameters params, and function body body.
struct ps_node * ps_node_block_stm_new(struct ps_node_block *block)
Creates a new block statement.
struct ps_node * ps_node_if_new(struct ps_expr *cond, struct ps_node_block *body, struct ps_node_block *else_body)
Creates a new if statement on condition cond.
struct ps_expr * ps_expr_binary_new(struct ps_expr *lhs, struct ps_token *op, struct ps_expr *rhs)
Creates a new binary expression.
struct ps_node * ps_node_while_new(struct ps_expr *cond, struct ps_node_block *body)
Creates a new while loop.
struct ps_expr * ps_expr_lit_new_interp_str(struct ps_interp_str *value)
Creates a new literal expression for an interpolated string.
#define ps_expr_arr_new()
struct ps_expr * ps_expr_id_new(struct ps_token *name)
Creates a new id expression.
struct ps_node * ps_node_import_new(struct ps_name *name)
Creates a new import statement.
#define ps_node_arr_free(arr)
#define ps_interp_str_new()
ps_fn_qualifiers
Function qualifier flags.
@ PS_FN_INLINE
Inlined everywhere.
@ PS_FN_PUBLIC
Visible outside the module.
@ PS_FN_PRIVATE
Hidden outside the module.
#define ps_node_arr_new()
#define ps_node_block_new()
#define ps_push(__arrptr, __new_elem)
usize ps_error_count(void)
The number of errors that have been reported in the error reporting system.
Error reporting and displaying utilities.
struct ps_loc PS_LOC_NONE(void)
Represents the absence token location.
bool ps_token_type_is_op(enum ps_token_type type)
Whether type represents an operator token.
const struct ps_operator * ps_token_type_get_op(enum ps_token_type type)
Returns: the operator information associated with the given operator token.
Operator precedence and associativity info.
i32 ps_operator_precedence_t
struct ps_expr * ps_parse_expr_lit(struct ps_tstream *ts)
Parses an expression literal.
struct ps_node * ps_parse_extern(struct ps_tstream *ts)
Parses an eexternal declaration.
struct ps_node * ps_parse_if(struct ps_tstream *ts)
Parses an if-else statement.
struct ps_type_tuple * ps_parse_type_tuple(struct ps_tstream *ts)
Parses a tuple type.
#define PS_GROUP_MISMATCH_REFER(tkn)
struct ps_node * ps_parse_enum(struct ps_tstream *ts)
Parses an enumeration declaration.
struct ps_node * ps_parse_for(struct ps_tstream *ts)
Parses a for loop.
struct ps_expr * ps_parse_expr_call(struct ps_tstream *ts, struct ps_token *callee)
Parses a call expression, which involves a token (TODO: an expression) followed by a set of parenthes...
struct ps_expr * ps_parse_expr_primary(struct ps_tstream *ts)
A primary expression is a literal or call expression.
struct ps_expr * ps_parse_expr(struct ps_tstream *ts)
Parses a general expression.
struct ps_type * ps_parse_type(struct ps_tstream *ts)
Parses a type such as Rectangle or (Point, Point) from the token stream.
struct ps_expr * ps_parse_interp_str(struct ps_tstream *ts)
struct ps_node * ps_parse_while(struct ps_tstream *ts)
Parses a while loop.
struct ps_node * ps_parse_return(struct ps_tstream *ts)
Parses a return statement.
struct ps_node_block * ps_parse_block(struct ps_tstream *ts)
Parses a block like:
struct ps_node * ps_parse_let(struct ps_tstream *ts)
struct ps_node * ps_parse_import(struct ps_tstream *ts)
Parses an import statement.
struct ps_type * ps_parse_type_primary(struct ps_tstream *ts)
Parses a primary type such as a tuple or unresolved (struct, enum).
struct ps_node * ps_parse_fn(struct ps_tstream *ts)
Parses a function definition.
struct ps_node * ps_parse_node(struct ps_tstream *ts)
Parses and returns the next node in ts.
struct ps_node * ps_parse_struct(struct ps_tstream *ts)
Parses a structure declaration.
struct ps_name * ps_parse_name(struct ps_tstream *ts, struct ps_token *first)
Parses a name such as foo::bar::baz.
#define try_get_float(from, bind_to, do_)
struct ps_node_arr * ps_parse(struct ps_token_arr *tokens, const struct ps_file_ctx *file_ctx)
Constructs a series of nodes from the given tokens.
struct ps_expr * ps_parse_expr_helper(struct ps_tstream *ts, struct ps_expr *lhs, ps_operator_precedence_t min_prec)
Handles predence and associativity in parsing expressions.
struct ps_node * ps_parse_expr_stm(struct ps_tstream *ts)
An expression statement consists of an expression followed by a newline.
Parsing routines for nodes and expressions.
#define PS_PARSER_MAX_ERRORS
The parser will stop in its tracks after it encounters this many errors.
Represents an error or source-referencing display message.
Expression nodes are represented with tagged unions.
Information captured in a file necessary for effective info/error reporting.
AST nodes are represented with tagged unions.
struct ps_node_block * block
enum ps_node::ps_node_type type
bool is_binary
Enables processing this operator as a binary operator.
ps_operator_precedence_t unary_prec
The operator's unary precedence.
bool is_left_associative
This defines operator assocativity as follows:
ps_operator_precedence_t binary_prec
The operator's binary precedence.
bool is_unary
Enables processing this operator as an unary operator.
Processes tokens in a stream.
const struct ps_token_arr * tokens
The tokens in the stream.
const struct ps_file_ctx * file_ctx
The file context for the stream.
struct ps_type_tuple * tuple
ps_token_type
The type of a token.
void ps_tstream_eof_error(struct ps_tstream *ts, int code, STR ctx, STR fix)
Reports an end-of-file error with the given context ctx, using the last token in ts for location.
void ps_tstream_init(struct ps_tstream *ts, const struct ps_token_arr *tokens, const struct ps_file_ctx *file_ctx)
Points tstream to the first token in tokens and reads from it there on.
bool ps_tstream_is_eof(struct ps_tstream *ts)
Whether tstream has no more tokens.
struct ps_token * ps_tstream_peek(struct ps_tstream *ts, usize n, enum ps_token_type type)
If the nth next token in ts is of the given type, returns it.
#define match(type, ctx)
Tries to match the next token with the given token type, opening a block for if no match succeeded.
#define bindmatch_any(val, types, ctx)
#define bindmatch(val, type, ctx)
Tries to match the next token with the given token type and assign the token to the given variable,...
struct ps_type * ps_type_from_name(struct ps_token *name)
Returns the type associated with the given name (e.g.
struct ps_type * ps_type_from_tuple(struct ps_type_tuple *tuple)
Constructs and returns a type for the given tuple type tuple.
struct ps_type * ps_type_prim_new(enum ps_type_type prim_type)
Constructs a new primitive type specified by prim_type.
#define ps_type_field_arr_new()
#define ps_type_tuple_new()