move AST rendering code to separate file
This commit is contained in:
459
src/parser.cpp
459
src/parser.cpp
@@ -14,465 +14,6 @@
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
static const char *bin_op_str(BinOpType bin_op) {
|
||||
switch (bin_op) {
|
||||
case BinOpTypeInvalid: return "(invalid)";
|
||||
case BinOpTypeBoolOr: return "||";
|
||||
case BinOpTypeBoolAnd: return "&&";
|
||||
case BinOpTypeCmpEq: return "==";
|
||||
case BinOpTypeCmpNotEq: return "!=";
|
||||
case BinOpTypeCmpLessThan: return "<";
|
||||
case BinOpTypeCmpGreaterThan: return ">";
|
||||
case BinOpTypeCmpLessOrEq: return "<=";
|
||||
case BinOpTypeCmpGreaterOrEq: return ">=";
|
||||
case BinOpTypeBinOr: return "|";
|
||||
case BinOpTypeBinXor: return "^";
|
||||
case BinOpTypeBinAnd: return "&";
|
||||
case BinOpTypeBitShiftLeft: return "<<";
|
||||
case BinOpTypeBitShiftRight: return ">>";
|
||||
case BinOpTypeAdd: return "+";
|
||||
case BinOpTypeSub: return "-";
|
||||
case BinOpTypeMult: return "*";
|
||||
case BinOpTypeDiv: return "/";
|
||||
case BinOpTypeMod: return "%";
|
||||
case BinOpTypeAssign: return "=";
|
||||
case BinOpTypeAssignTimes: return "*=";
|
||||
case BinOpTypeAssignDiv: return "/=";
|
||||
case BinOpTypeAssignMod: return "%=";
|
||||
case BinOpTypeAssignPlus: return "+=";
|
||||
case BinOpTypeAssignMinus: return "-=";
|
||||
case BinOpTypeAssignBitShiftLeft: return "<<=";
|
||||
case BinOpTypeAssignBitShiftRight: return ">>=";
|
||||
case BinOpTypeAssignBitAnd: return "&=";
|
||||
case BinOpTypeAssignBitXor: return "^=";
|
||||
case BinOpTypeAssignBitOr: return "|=";
|
||||
case BinOpTypeAssignBoolAnd: return "&&=";
|
||||
case BinOpTypeAssignBoolOr: return "||=";
|
||||
case BinOpTypeUnwrapMaybe: return "??";
|
||||
case BinOpTypeStrCat: return "++";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static const char *prefix_op_str(PrefixOp prefix_op) {
|
||||
switch (prefix_op) {
|
||||
case PrefixOpInvalid: return "(invalid)";
|
||||
case PrefixOpNegation: return "-";
|
||||
case PrefixOpBoolNot: return "!";
|
||||
case PrefixOpBinNot: return "~";
|
||||
case PrefixOpAddressOf: return "&";
|
||||
case PrefixOpConstAddressOf: return "&const";
|
||||
case PrefixOpDereference: return "*";
|
||||
case PrefixOpMaybe: return "?";
|
||||
case PrefixOpError: return "%";
|
||||
case PrefixOpUnwrapError: return "%%";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static const char *return_prefix_str(ReturnKind kind) {
|
||||
switch (kind) {
|
||||
case ReturnKindError: return "%";
|
||||
case ReturnKindMaybe: return "?";
|
||||
case ReturnKindUnconditional: return "";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
const char *node_type_str(NodeType node_type) {
|
||||
switch (node_type) {
|
||||
case NodeTypeRoot:
|
||||
return "Root";
|
||||
case NodeTypeRootExportDecl:
|
||||
return "RootExportDecl";
|
||||
case NodeTypeFnDef:
|
||||
return "FnDef";
|
||||
case NodeTypeFnDecl:
|
||||
return "FnDecl";
|
||||
case NodeTypeFnProto:
|
||||
return "FnProto";
|
||||
case NodeTypeParamDecl:
|
||||
return "ParamDecl";
|
||||
case NodeTypeBlock:
|
||||
return "Block";
|
||||
case NodeTypeBinOpExpr:
|
||||
return "BinOpExpr";
|
||||
case NodeTypeUnwrapErrorExpr:
|
||||
return "UnwrapErrorExpr";
|
||||
case NodeTypeFnCallExpr:
|
||||
return "FnCallExpr";
|
||||
case NodeTypeArrayAccessExpr:
|
||||
return "ArrayAccessExpr";
|
||||
case NodeTypeSliceExpr:
|
||||
return "SliceExpr";
|
||||
case NodeTypeDirective:
|
||||
return "Directive";
|
||||
case NodeTypeReturnExpr:
|
||||
return "ReturnExpr";
|
||||
case NodeTypeVariableDeclaration:
|
||||
return "VariableDeclaration";
|
||||
case NodeTypeErrorValueDecl:
|
||||
return "ErrorValueDecl";
|
||||
case NodeTypeNumberLiteral:
|
||||
return "NumberLiteral";
|
||||
case NodeTypeStringLiteral:
|
||||
return "StringLiteral";
|
||||
case NodeTypeCharLiteral:
|
||||
return "CharLiteral";
|
||||
case NodeTypeSymbol:
|
||||
return "Symbol";
|
||||
case NodeTypePrefixOpExpr:
|
||||
return "PrefixOpExpr";
|
||||
case NodeTypeImport:
|
||||
return "Import";
|
||||
case NodeTypeCImport:
|
||||
return "CImport";
|
||||
case NodeTypeBoolLiteral:
|
||||
return "BoolLiteral";
|
||||
case NodeTypeNullLiteral:
|
||||
return "NullLiteral";
|
||||
case NodeTypeUndefinedLiteral:
|
||||
return "UndefinedLiteral";
|
||||
case NodeTypeIfBoolExpr:
|
||||
return "IfBoolExpr";
|
||||
case NodeTypeIfVarExpr:
|
||||
return "IfVarExpr";
|
||||
case NodeTypeWhileExpr:
|
||||
return "WhileExpr";
|
||||
case NodeTypeForExpr:
|
||||
return "ForExpr";
|
||||
case NodeTypeSwitchExpr:
|
||||
return "SwitchExpr";
|
||||
case NodeTypeSwitchProng:
|
||||
return "SwitchProng";
|
||||
case NodeTypeSwitchRange:
|
||||
return "SwitchRange";
|
||||
case NodeTypeLabel:
|
||||
return "Label";
|
||||
case NodeTypeGoto:
|
||||
return "Goto";
|
||||
case NodeTypeBreak:
|
||||
return "Break";
|
||||
case NodeTypeContinue:
|
||||
return "Continue";
|
||||
case NodeTypeAsmExpr:
|
||||
return "AsmExpr";
|
||||
case NodeTypeFieldAccessExpr:
|
||||
return "FieldAccessExpr";
|
||||
case NodeTypeStructDecl:
|
||||
return "StructDecl";
|
||||
case NodeTypeStructField:
|
||||
return "StructField";
|
||||
case NodeTypeStructValueField:
|
||||
return "StructValueField";
|
||||
case NodeTypeContainerInitExpr:
|
||||
return "ContainerInitExpr";
|
||||
case NodeTypeArrayType:
|
||||
return "ArrayType";
|
||||
case NodeTypeErrorType:
|
||||
return "ErrorType";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
void ast_print(AstNode *node, int indent) {
|
||||
for (int i = 0; i < indent; i += 1) {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
assert(node->type == NodeTypeRoot || *node->parent_field == node);
|
||||
|
||||
switch (node->type) {
|
||||
case NodeTypeRoot:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
|
||||
AstNode *child = node->data.root.top_level_decls.at(i);
|
||||
ast_print(child, indent + 2);
|
||||
}
|
||||
break;
|
||||
case NodeTypeRootExportDecl:
|
||||
fprintf(stderr, "%s %s '%s'\n", node_type_str(node->type),
|
||||
buf_ptr(&node->data.root_export_decl.type),
|
||||
buf_ptr(&node->data.root_export_decl.name));
|
||||
break;
|
||||
case NodeTypeFnDef:
|
||||
{
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
AstNode *child = node->data.fn_def.fn_proto;
|
||||
ast_print(child, indent + 2);
|
||||
ast_print(node->data.fn_def.body, indent + 2);
|
||||
break;
|
||||
}
|
||||
case NodeTypeFnProto:
|
||||
{
|
||||
Buf *name_buf = &node->data.fn_proto.name;
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
|
||||
|
||||
for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
|
||||
AstNode *child = node->data.fn_proto.params.at(i);
|
||||
ast_print(child, indent + 2);
|
||||
}
|
||||
|
||||
ast_print(node->data.fn_proto.return_type, indent + 2);
|
||||
|
||||
break;
|
||||
}
|
||||
case NodeTypeBlock:
|
||||
{
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
for (int i = 0; i < node->data.block.statements.length; i += 1) {
|
||||
AstNode *child = node->data.block.statements.at(i);
|
||||
ast_print(child, indent + 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeParamDecl:
|
||||
{
|
||||
Buf *name_buf = &node->data.param_decl.name;
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
|
||||
|
||||
ast_print(node->data.param_decl.type, indent + 2);
|
||||
|
||||
break;
|
||||
}
|
||||
case NodeTypeReturnExpr:
|
||||
{
|
||||
const char *prefix_str = return_prefix_str(node->data.return_expr.kind);
|
||||
fprintf(stderr, "%s%s\n", prefix_str, node_type_str(node->type));
|
||||
if (node->data.return_expr.expr)
|
||||
ast_print(node->data.return_expr.expr, indent + 2);
|
||||
break;
|
||||
}
|
||||
case NodeTypeVariableDeclaration:
|
||||
{
|
||||
Buf *name_buf = &node->data.variable_declaration.symbol;
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
|
||||
if (node->data.variable_declaration.type)
|
||||
ast_print(node->data.variable_declaration.type, indent + 2);
|
||||
if (node->data.variable_declaration.expr)
|
||||
ast_print(node->data.variable_declaration.expr, indent + 2);
|
||||
break;
|
||||
}
|
||||
case NodeTypeErrorValueDecl:
|
||||
{
|
||||
Buf *name_buf = &node->data.error_value_decl.name;
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
|
||||
break;
|
||||
}
|
||||
case NodeTypeFnDecl:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.fn_decl.fn_proto, indent + 2);
|
||||
break;
|
||||
case NodeTypeBinOpExpr:
|
||||
fprintf(stderr, "%s %s\n", node_type_str(node->type),
|
||||
bin_op_str(node->data.bin_op_expr.bin_op));
|
||||
ast_print(node->data.bin_op_expr.op1, indent + 2);
|
||||
ast_print(node->data.bin_op_expr.op2, indent + 2);
|
||||
break;
|
||||
case NodeTypeUnwrapErrorExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.unwrap_err_expr.op1, indent + 2);
|
||||
if (node->data.unwrap_err_expr.symbol) {
|
||||
ast_print(node->data.unwrap_err_expr.symbol, indent + 2);
|
||||
}
|
||||
ast_print(node->data.unwrap_err_expr.op2, indent + 2);
|
||||
break;
|
||||
case NodeTypeFnCallExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.fn_call_expr.fn_ref_expr, indent + 2);
|
||||
for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
|
||||
AstNode *child = node->data.fn_call_expr.params.at(i);
|
||||
ast_print(child, indent + 2);
|
||||
}
|
||||
break;
|
||||
case NodeTypeArrayAccessExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.array_access_expr.array_ref_expr, indent + 2);
|
||||
ast_print(node->data.array_access_expr.subscript, indent + 2);
|
||||
break;
|
||||
case NodeTypeSliceExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.slice_expr.array_ref_expr, indent + 2);
|
||||
ast_print(node->data.slice_expr.start, indent + 2);
|
||||
if (node->data.slice_expr.end) {
|
||||
ast_print(node->data.slice_expr.end, indent + 2);
|
||||
}
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
case NodeTypePrefixOpExpr:
|
||||
fprintf(stderr, "%s %s\n", node_type_str(node->type),
|
||||
prefix_op_str(node->data.prefix_op_expr.prefix_op));
|
||||
ast_print(node->data.prefix_op_expr.primary_expr, indent + 2);
|
||||
break;
|
||||
case NodeTypeNumberLiteral:
|
||||
{
|
||||
NumLit kind = node->data.number_literal.kind;
|
||||
const char *name = node_type_str(node->type);
|
||||
if (kind == NumLitUInt) {
|
||||
fprintf(stderr, "%s uint %" PRIu64 "\n", name, node->data.number_literal.data.x_uint);
|
||||
} else {
|
||||
fprintf(stderr, "%s float %f\n", name, node->data.number_literal.data.x_float);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeStringLiteral:
|
||||
{
|
||||
const char *c = node->data.string_literal.c ? "c" : "";
|
||||
fprintf(stderr, "StringLiteral %s'%s'\n", c,
|
||||
buf_ptr(&node->data.string_literal.buf));
|
||||
break;
|
||||
}
|
||||
case NodeTypeCharLiteral:
|
||||
{
|
||||
fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);
|
||||
break;
|
||||
}
|
||||
case NodeTypeSymbol:
|
||||
fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
|
||||
break;
|
||||
case NodeTypeImport:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path));
|
||||
break;
|
||||
case NodeTypeCImport:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.c_import.block, indent + 2);
|
||||
break;
|
||||
case NodeTypeBoolLiteral:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
|
||||
node->data.bool_literal.value ? "true" : "false");
|
||||
break;
|
||||
case NodeTypeNullLiteral:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
case NodeTypeIfBoolExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
if (node->data.if_bool_expr.condition)
|
||||
ast_print(node->data.if_bool_expr.condition, indent + 2);
|
||||
ast_print(node->data.if_bool_expr.then_block, indent + 2);
|
||||
if (node->data.if_bool_expr.else_node)
|
||||
ast_print(node->data.if_bool_expr.else_node, indent + 2);
|
||||
break;
|
||||
case NodeTypeIfVarExpr:
|
||||
{
|
||||
Buf *name_buf = &node->data.if_var_expr.var_decl.symbol;
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
|
||||
if (node->data.if_var_expr.var_decl.type)
|
||||
ast_print(node->data.if_var_expr.var_decl.type, indent + 2);
|
||||
if (node->data.if_var_expr.var_decl.expr)
|
||||
ast_print(node->data.if_var_expr.var_decl.expr, indent + 2);
|
||||
ast_print(node->data.if_var_expr.then_block, indent + 2);
|
||||
if (node->data.if_var_expr.else_node)
|
||||
ast_print(node->data.if_var_expr.else_node, indent + 2);
|
||||
break;
|
||||
}
|
||||
case NodeTypeWhileExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.while_expr.condition, indent + 2);
|
||||
ast_print(node->data.while_expr.body, indent + 2);
|
||||
break;
|
||||
case NodeTypeForExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.for_expr.elem_node, indent + 2);
|
||||
ast_print(node->data.for_expr.array_expr, indent + 2);
|
||||
if (node->data.for_expr.index_node) {
|
||||
ast_print(node->data.for_expr.index_node, indent + 2);
|
||||
}
|
||||
ast_print(node->data.for_expr.body, indent + 2);
|
||||
break;
|
||||
case NodeTypeSwitchExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.switch_expr.expr, indent + 2);
|
||||
for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
|
||||
AstNode *child_node = node->data.switch_expr.prongs.at(i);
|
||||
ast_print(child_node, indent + 2);
|
||||
}
|
||||
break;
|
||||
case NodeTypeSwitchProng:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
|
||||
AstNode *child_node = node->data.switch_prong.items.at(i);
|
||||
ast_print(child_node, indent + 2);
|
||||
}
|
||||
if (node->data.switch_prong.var_symbol) {
|
||||
ast_print(node->data.switch_prong.var_symbol, indent + 2);
|
||||
}
|
||||
ast_print(node->data.switch_prong.expr, indent + 2);
|
||||
break;
|
||||
case NodeTypeSwitchRange:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.switch_range.start, indent + 2);
|
||||
ast_print(node->data.switch_range.end, indent + 2);
|
||||
break;
|
||||
case NodeTypeLabel:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
|
||||
break;
|
||||
case NodeTypeGoto:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name));
|
||||
break;
|
||||
case NodeTypeBreak:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
case NodeTypeContinue:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
case NodeTypeUndefinedLiteral:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
case NodeTypeAsmExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
case NodeTypeFieldAccessExpr:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
|
||||
buf_ptr(&node->data.field_access_expr.field_name));
|
||||
ast_print(node->data.field_access_expr.struct_expr, indent + 2);
|
||||
break;
|
||||
case NodeTypeStructDecl:
|
||||
fprintf(stderr, "%s '%s'\n",
|
||||
node_type_str(node->type), buf_ptr(&node->data.struct_decl.name));
|
||||
for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
|
||||
AstNode *child = node->data.struct_decl.fields.at(i);
|
||||
ast_print(child, indent + 2);
|
||||
}
|
||||
for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
|
||||
AstNode *child = node->data.struct_decl.fns.at(i);
|
||||
ast_print(child, indent + 2);
|
||||
}
|
||||
break;
|
||||
case NodeTypeStructField:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name));
|
||||
if (node->data.struct_field.type) {
|
||||
ast_print(node->data.struct_field.type, indent + 2);
|
||||
}
|
||||
break;
|
||||
case NodeTypeStructValueField:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name));
|
||||
ast_print(node->data.struct_val_field.expr, indent + 2);
|
||||
break;
|
||||
case NodeTypeContainerInitExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
ast_print(node->data.container_init_expr.type, indent + 2);
|
||||
for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
|
||||
AstNode *child = node->data.container_init_expr.entries.at(i);
|
||||
ast_print(child, indent + 2);
|
||||
}
|
||||
break;
|
||||
case NodeTypeArrayType:
|
||||
{
|
||||
const char *const_str = node->data.array_type.is_const ? "const" : "var";
|
||||
fprintf(stderr, "%s %s\n", node_type_str(node->type), const_str);
|
||||
if (node->data.array_type.size) {
|
||||
ast_print(node->data.array_type.size, indent + 2);
|
||||
}
|
||||
ast_print(node->data.array_type.child_type, indent + 2);
|
||||
break;
|
||||
}
|
||||
case NodeTypeErrorType:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ParseContext {
|
||||
Buf *buf;
|
||||
AstNode *root;
|
||||
|
||||
Reference in New Issue
Block a user