Compare commits
9 Commits
4514d94be9
...
905acacd07
Author | SHA1 | Date | |
---|---|---|---|
905acacd07 | |||
8763fa35dd | |||
feae5d560a | |||
ec268f6047 | |||
6fff5e5cc8 | |||
7b19e553f2 | |||
64ef797727 | |||
85e17ede84 | |||
8e5b39a6e4 |
@ -1,12 +1,13 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
IndentCaseLabels: true
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
IndentWidth: 4
|
||||
PointerAlignment: Left
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ tags
|
||||
.cache
|
||||
build/*
|
||||
compile_commands.json
|
||||
vgcore.*
|
||||
|
2
Makefile
2
Makefile
@ -14,7 +14,7 @@ TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj
|
||||
CC = clang
|
||||
LINK = clang
|
||||
CFLAGS = -Wall -DDBG -ggdb
|
||||
LDFLAGS =
|
||||
LDFLAGS = -lm
|
||||
|
||||
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
|
||||
OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC_FILES))
|
||||
|
17
README.md
17
README.md
@ -1,4 +1,4 @@
|
||||
# SCL: Simple Calculator Language
|
||||
# SCL: Simple CAS Language
|
||||
|
||||
## Syntax
|
||||
|
||||
@ -12,16 +12,24 @@ As one would expect, you can evaluate simple infix expressions:
|
||||
You can also define your own functions:
|
||||
|
||||
```scl
|
||||
> f(x) 2x
|
||||
> f(x) = 2x
|
||||
> f(2)
|
||||
= 4
|
||||
```
|
||||
|
||||
Symbolic algebra is done in the following manner:
|
||||
|
||||
```scl
|
||||
> f(x) = e^x
|
||||
> diff(f, x:sym, 2)
|
||||
= e^x
|
||||
```
|
||||
|
||||
SCL will dynamically decide on types, but you can state them explicitly as
|
||||
well:
|
||||
|
||||
```scl
|
||||
> f(x:int) 2x
|
||||
> f(x:int) = 2x
|
||||
> f(2.2)
|
||||
! f(x:int): x must be of type int.
|
||||
```
|
||||
@ -32,6 +40,5 @@ Variables can be defined, with several attributes:
|
||||
> a = 1 // Interpret type automatically.
|
||||
> b:int = 1 // Must be int.
|
||||
> c:const:int = 1 // Constant: value can never change.
|
||||
> d:lazy = (1 + 1) // Interpreter will wait as long as possible before
|
||||
// evaluating.
|
||||
> x:sym // Treated symbolicaly.
|
||||
```
|
||||
|
72
src/ast.c
72
src/ast.c
@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "include/ast.h"
|
||||
#include "include/dstr.h"
|
||||
#include "include/util.h"
|
||||
|
||||
extern AST* root;
|
||||
@ -23,36 +24,59 @@ void ast_destroy(AST* ast) {
|
||||
if (!ast) return;
|
||||
|
||||
switch (ast->type) {
|
||||
case AST_TYPE_NUM: ast_type_num_destroy(ast->data); break;
|
||||
case AST_TYPE_CALL: ast_type_call_destroy(ast->data); break;
|
||||
default: log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
|
||||
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
|
||||
case AST_TYPE_CALL: ast_call_data_destroy(ast->data); break;
|
||||
default:
|
||||
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void ast_print(AST* ast) {
|
||||
log_dbgf("Tree type: %s", asttype_names[ast->type]);
|
||||
fflush(stdout);
|
||||
void ast_print(AST* ast) { ast_print_i(ast, 0); }
|
||||
|
||||
void ast_print_i(AST* ast, int i) {
|
||||
INDENT_BEGIN(i);
|
||||
|
||||
INDENT_TITLE("AST", ast);
|
||||
INDENT_FIELD("type", "%s", asttype_names[ast->type]);
|
||||
INDENT_FIELD_EXT_NONL_START("data");
|
||||
switch (ast->type) {
|
||||
case AST_TYPE_NUM:
|
||||
printf("%s %lf\n", INDENT_spacing->buf, *(ASTNumData*)ast->data);
|
||||
break;
|
||||
case AST_TYPE_CALL: ast_call_print(ast->data, i + 2); break;
|
||||
default: exit(1);
|
||||
}
|
||||
INDENT_FIELD_NONL_END;
|
||||
INDENT_END;
|
||||
}
|
||||
|
||||
|
||||
ASTNumData* ast_type_num_init(int val) {
|
||||
ASTNumData* ast_num_data_init(double val) {
|
||||
talloc(ASTNumData, num);
|
||||
|
||||
num->val = val;
|
||||
log_dbgf("val: %lf", val);
|
||||
|
||||
*num = val;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
void ast_type_num_destroy(ASTNumData* num) {
|
||||
if (!num)
|
||||
return
|
||||
|
||||
free(num);
|
||||
void ast_num_data_destroy(ASTNumData* num) {
|
||||
if (!num) return free(num);
|
||||
}
|
||||
|
||||
ASTCallData* ast_type_call_init(char* to, size_t argc, AST** argv) {
|
||||
void ast_num_print(ASTNumData* data, int i) {
|
||||
INDENT_BEGIN(i);
|
||||
|
||||
INDENT_FIELD("data", "%lf", *data);
|
||||
|
||||
INDENT_END;
|
||||
}
|
||||
|
||||
ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv) {
|
||||
talloc(ASTCallData, call);
|
||||
|
||||
log_dbgf("to: %s", to);
|
||||
|
||||
call->to = to;
|
||||
call->argc = argc;
|
||||
call->argv = argv;
|
||||
@ -60,11 +84,19 @@ ASTCallData* ast_type_call_init(char* to, size_t argc, AST** argv) {
|
||||
return call;
|
||||
}
|
||||
|
||||
void ast_type_call_destroy(ASTCallData* call) {
|
||||
if (!call)
|
||||
return
|
||||
|
||||
free(call->to);
|
||||
void ast_call_data_destroy(ASTCallData* call) {
|
||||
if (!call) return free(call->to);
|
||||
for (size_t i = 0; i < call->argc; i++) free(call->argv[i]);
|
||||
free(call);
|
||||
}
|
||||
|
||||
void ast_call_print(ASTCallData* data, int i) {
|
||||
INDENT_BEGIN(i);
|
||||
|
||||
INDENT_TITLE("ASTCallData", data);
|
||||
INDENT_FIELD("to", "%s", data->to);
|
||||
INDENT_FIELD("argc", "%ld", data->argc);
|
||||
INDENT_FIELD_LIST("argv", data->argv, data->argc, ast_print_i);
|
||||
|
||||
INDENT_END;
|
||||
}
|
||||
|
12
src/dstr.c
12
src/dstr.c
@ -25,8 +25,10 @@ void dstr_append(Dstr* dest, char* src, size_t ln) {
|
||||
// Double the buffer size when overflown.
|
||||
dest->bufsz *= 2;
|
||||
dest->buf = realloc(dest->buf, dest->bufsz);
|
||||
log_dbgf("dstr @ %p doubled from %ld to %ld", dest, dest->bufsz / 2,
|
||||
dest->bufsz);
|
||||
log_dbgf(
|
||||
"dstr @ %p doubled from %ld to %ld", dest, dest->bufsz / 2,
|
||||
dest->bufsz
|
||||
);
|
||||
}
|
||||
|
||||
// Overwrites the \0 at the end of the string, keeps the null from the given
|
||||
@ -40,8 +42,10 @@ void dstr_appendch(Dstr* dest, char ch) {
|
||||
// Double the buffer size when overflown.
|
||||
dest->bufsz *= 2;
|
||||
dest->buf = realloc(dest->buf, dest->bufsz);
|
||||
log_dbgf("dstr @ %p doubled from %ld to %ld", dest, dest->bufsz / 2,
|
||||
dest->bufsz);
|
||||
log_dbgf(
|
||||
"dstr @ %p doubled from %ld to %ld", dest, dest->bufsz / 2,
|
||||
dest->bufsz
|
||||
);
|
||||
}
|
||||
|
||||
// Overwrites the preexisting null terminator, and adds one of its own.
|
||||
|
23
src/exec.c
23
src/exec.c
@ -7,26 +7,33 @@
|
||||
|
||||
extern AST* root;
|
||||
|
||||
void exec_expr() {
|
||||
ast_print(root);
|
||||
ASTNumData exec_expr(AST* ast) {
|
||||
// ast_print(ast);
|
||||
log_dbg("Started execution.");
|
||||
switch (root->type) {
|
||||
case AST_TYPE_CALL: exec_call(); break;
|
||||
switch (ast->type) {
|
||||
case AST_TYPE_CALL: return exec_call(ast);
|
||||
case AST_TYPE_NUM: return *(ASTNumData*)ast->data;
|
||||
default: printf("what\n");
|
||||
}
|
||||
}
|
||||
|
||||
void exec_call() {
|
||||
ASTNumData exec_call(AST* ast) {
|
||||
log_dbg("Started call execution.");
|
||||
fflush(stdout);
|
||||
ASTCallData* calldata = (ASTCallData*)root->data;
|
||||
ASTCallData* calldata = (ASTCallData*)ast->data;
|
||||
if (!strcmp(calldata->to, "+") && calldata->argc == 2) {
|
||||
|
||||
/*
|
||||
ASTNumData* n1 = (ASTNumData*)calldata->argv[0]->data;
|
||||
ASTNumData* n2 = (ASTNumData*)calldata->argv[1]->data;
|
||||
*/
|
||||
|
||||
exec_return(n1->val + n2->val);
|
||||
ASTNumData n1 = exec_expr(calldata->argv[0]);
|
||||
ASTNumData n2 = exec_expr(calldata->argv[1]);
|
||||
|
||||
return n1 + n2;
|
||||
}
|
||||
return -1000;
|
||||
}
|
||||
|
||||
void exec_return(int n) { printf("= %d\n", n); }
|
||||
void exec_print(double n) { printf("= %lf\n", n); }
|
||||
|
@ -14,14 +14,14 @@
|
||||
}
|
||||
|
||||
%union {
|
||||
int intval;
|
||||
double fval;
|
||||
char* strval;
|
||||
AST* ast;
|
||||
}
|
||||
|
||||
%define parse.error verbose
|
||||
|
||||
%token<intval> NUM
|
||||
%token<fval> NUM
|
||||
%token<strval> CALL
|
||||
%token PLUS
|
||||
%token NL
|
||||
@ -35,13 +35,12 @@ input:
|
||||
;
|
||||
|
||||
exp:
|
||||
NUM { $$ = ast_init(AST_TYPE_NUM, ast_type_num_init($1)); }
|
||||
NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); }
|
||||
| NUM PLUS NUM {
|
||||
AST* argv[2] = {
|
||||
ast_init(AST_TYPE_NUM, ast_type_num_init($1)),
|
||||
ast_init(AST_TYPE_NUM, ast_type_num_init($3))
|
||||
};
|
||||
$$ = ast_init(AST_TYPE_CALL, ast_type_call_init("+", 2, argv));
|
||||
};
|
||||
AST** argv = calloc(2, sizeof(AST*));
|
||||
argv[0] = ast_init(AST_TYPE_NUM, ast_num_data_init($1));
|
||||
argv[1] = ast_init(AST_TYPE_NUM, ast_num_data_init($3));
|
||||
$$ = ast_init(AST_TYPE_CALL, ast_call_data_init("+", 2, argv));
|
||||
}
|
||||
|
||||
%%
|
||||
|
@ -17,13 +17,13 @@ typedef struct {
|
||||
AST* ast_init(ASTType type, void* data);
|
||||
void ast_destroy(AST* ast);
|
||||
void ast_print(AST* ast);
|
||||
void ast_print_i(AST* ast, int i);
|
||||
|
||||
typedef struct {
|
||||
int val;
|
||||
} ASTNumData;
|
||||
typedef double ASTNumData;
|
||||
|
||||
ASTNumData* ast_type_num_init(int val);
|
||||
void ast_type_num_destroy(ASTNumData* num);
|
||||
ASTNumData* ast_num_data_init(double val);
|
||||
void ast_num_data_destroy(ASTNumData* num);
|
||||
void ast_num_print(ASTNumData*, int i);
|
||||
|
||||
typedef struct {
|
||||
char* to; // What the call's to.
|
||||
@ -31,7 +31,8 @@ typedef struct {
|
||||
AST** argv; // Argument vector.
|
||||
} ASTCallData;
|
||||
|
||||
ASTCallData* ast_type_call_init(char* to, size_t argc, AST** argv);
|
||||
void ast_type_call_destroy(ASTCallData* call);
|
||||
ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv);
|
||||
void ast_call_data_destroy(ASTCallData* call);
|
||||
void ast_call_print(ASTCallData*, int i);
|
||||
|
||||
#endif
|
||||
|
@ -1,8 +1,10 @@
|
||||
#ifndef EXEC_H
|
||||
#define EXEC_H
|
||||
|
||||
void exec_expr();
|
||||
void exec_call();
|
||||
void exec_return(int n);
|
||||
#include "ast.h"
|
||||
|
||||
ASTNumData exec_expr(AST* ast);
|
||||
ASTNumData exec_call(AST* ast);
|
||||
void exec_print(double n);
|
||||
|
||||
#endif
|
||||
|
@ -4,19 +4,25 @@
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include("../../build/grammars/grammar.tab.h")
|
||||
#include "../../build/grammars/grammar.tab.h"
|
||||
#else
|
||||
#warn "Build resources not present!"
|
||||
#endif
|
||||
#if __has_include("../../build/grammars/grammar.tab.h")
|
||||
#include "../../build/grammars/grammar.tab.h"
|
||||
#else
|
||||
#warn "Not sure whether build-time resources are present."
|
||||
#include "../../build/grammars/grammar.tab.h"
|
||||
#warn "Build resources not present!"
|
||||
#endif
|
||||
#else
|
||||
#warn "Not sure whether build-time resources are present."
|
||||
#include "../../build/grammars/grammar.tab.h"
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
extern char* inp;
|
||||
|
||||
// Accumulate an integer.
|
||||
int acc_int(int c);
|
||||
|
||||
// Accumulate a floating-point number.
|
||||
double acc_float(int c);
|
||||
|
||||
// Called by `yyparse()` (in bison-generated files.)
|
||||
int yylex();
|
||||
void yyerror(char const* s);
|
||||
|
@ -1,39 +0,0 @@
|
||||
#ifndef TOKEN_H
|
||||
#define TOKEN_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef enum {
|
||||
TOKEN_TYPE_CALL,
|
||||
TOKEN_TYPE_NUMBER,
|
||||
TOKEN_TYPE_MAX = TOKEN_TYPE_NUMBER,
|
||||
} TokenType;
|
||||
|
||||
// Token.
|
||||
typedef struct {
|
||||
TokenType type; // The type of the Token.
|
||||
size_t valn; // The length of val.
|
||||
char* val; // The text of the Token.
|
||||
size_t len; // Length of the text of the Token.
|
||||
} Token;
|
||||
|
||||
Token* token_init(TokenType type, char* val, size_t valn);
|
||||
void token_destroy(Token* token);
|
||||
|
||||
// Prints out a representation of the Token.
|
||||
void token_print(Token* token);
|
||||
|
||||
// Prints out a representation of the Token, with the specified indent level.
|
||||
void token_print_i(Token* token, int ilevel);
|
||||
|
||||
// Prints out a representation of the TokenType.
|
||||
void tokentype_print(TokenType t);
|
||||
|
||||
// Prints out a representation of the TokenType, with the specified indent
|
||||
// level.
|
||||
void tokentype_print_i(TokenType t, int ilevel);
|
||||
|
||||
// Prints a token's type. That's it.
|
||||
void tokentype_print_raw(TokenType t);
|
||||
|
||||
#endif
|
@ -50,7 +50,7 @@
|
||||
|
||||
// Print & indent the title of a section.
|
||||
#define INDENT_TITLE(THING, WHERE) \
|
||||
printf("%s" COL_BCYA THING " @ %p\n" COL_RESET, INDENT_spacing->buf, WHERE);
|
||||
printf("%s" COL_BCYA THING COL_RESET " @" COL_MAG " %p\n" COL_RESET, INDENT_spacing->buf, WHERE);
|
||||
|
||||
// Print & indent a thing.
|
||||
#define INDENT_FIELD(FIELD, VAL, ...) \
|
||||
@ -64,8 +64,8 @@
|
||||
INDENT_spacing->buf, INDENT_spacing->buf, __VA_ARGS__);
|
||||
|
||||
// Print & indent a thing without any newline.
|
||||
#define INDENT_FIELD_NONL_START(FIELD) \
|
||||
printf("%s " COL_BWHI FIELD ": " COL_RESET COL_WHI, INDENT_spacing->buf);
|
||||
#define INDENT_FIELD_EXT_NONL_START(FIELD) \
|
||||
printf("%s " COL_BWHI FIELD ":\n" COL_RESET COL_WHI, INDENT_spacing->buf);
|
||||
#define INDENT_FIELD_NONL_END printf( "\n" COL_RESET);
|
||||
|
||||
// Print an array A of N things, by calling the function F.
|
||||
|
52
src/lexer.c
52
src/lexer.c
@ -1,9 +1,52 @@
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "include/lexer.h"
|
||||
|
||||
int acc_int(int c) {
|
||||
int value = c - '0';
|
||||
while (isdigit(*inp)) {
|
||||
value = value * 10 + (*inp - '0'); // Accumulate value.
|
||||
inp++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
double acc_float(int c) {
|
||||
int dplaces = 0;
|
||||
double value = (double)(c - '0');
|
||||
|
||||
// Grab everything prior to '.'.
|
||||
while (isdigit(*inp)) {
|
||||
value = value * 10 + (*inp - '0'); // Accumulate value.
|
||||
inp++;
|
||||
}
|
||||
|
||||
if (*inp == '.') {
|
||||
inp++;
|
||||
|
||||
while (isdigit(*inp)) {
|
||||
// TODO:
|
||||
// Accumulate as int, divide once at end.
|
||||
// value = value + (((double)(*inp - '0'))/pow(10.0l,
|
||||
// (double)(inp-oinp))); // Accumulate value.
|
||||
value = value * 10 + (*inp - '0'); // Accumulate value.
|
||||
dplaces++;
|
||||
inp++;
|
||||
}
|
||||
value = value / pow(10, dplaces);
|
||||
}
|
||||
|
||||
// > 1.20000
|
||||
// = 1.0 + 2/10
|
||||
|
||||
// > 1.23
|
||||
// = 1.2 + 3/100
|
||||
return value;
|
||||
}
|
||||
|
||||
int yylex() {
|
||||
if (*inp == '\0') return YYEOF;
|
||||
|
||||
@ -15,12 +58,7 @@ int yylex() {
|
||||
|
||||
// Check for NUM.
|
||||
if (isdigit(c)) {
|
||||
int value = c - '0';
|
||||
while (isdigit(*inp)) {
|
||||
value = value * 10 + (*inp - '0'); // Accumulate value.
|
||||
inp++;
|
||||
}
|
||||
yylval.intval = value; // Set the token value.
|
||||
yylval.fval = acc_float(c); // Set the token value.
|
||||
return NUM;
|
||||
}
|
||||
|
||||
@ -34,4 +72,4 @@ int yylex() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
void yyerror(char const* s) { fprintf(stderr, "Syntax error:\n%s\n", s); }
|
||||
void yyerror(char const* s) { fprintf(stderr, "Parse error: %s\n", s); }
|
||||
|
13
src/main.c
13
src/main.c
@ -2,9 +2,9 @@
|
||||
|
||||
#include "include/ast.h"
|
||||
#include "include/dstr.h"
|
||||
#include "include/exec.h"
|
||||
#include "include/lexer.h"
|
||||
#include "include/util.h"
|
||||
#include "include/exec.h"
|
||||
|
||||
#include "../build/grammars/grammar.tab.h"
|
||||
|
||||
@ -31,7 +31,6 @@ int main(int argc, char** argv) {
|
||||
switch (c) {
|
||||
case EOF: dstr_destroy(ln); goto lnskip;
|
||||
case '\n': goto lnend;
|
||||
|
||||
default: dstr_appendch(ln, c); log_dbgf("cchar: %c", c);
|
||||
}
|
||||
} while (1);
|
||||
@ -41,14 +40,12 @@ int main(int argc, char** argv) {
|
||||
log_dbgf("cline: %s", ln->buf);
|
||||
|
||||
if (ln->ln > 0) {
|
||||
// I hope it's null-terminated.
|
||||
inp = ln->buf;
|
||||
if (yyparse() == 0)
|
||||
printf("Parsed successfully!\n");
|
||||
else
|
||||
printf("Parse error.\n");
|
||||
if (yyparse() == 0) printf("Parsed successfully!\n");
|
||||
else printf("Parse error.\n");
|
||||
|
||||
exec_expr();
|
||||
exec_print(exec_expr(root));
|
||||
ast_print(root);
|
||||
}
|
||||
|
||||
dstr_destroy(ln);
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "include/util.h"
|
||||
#include "include/stack.h"
|
||||
#include "include/util.h"
|
||||
|
||||
Stack* stack_init() {
|
||||
talloc(Stack, stack);
|
||||
|
62
src/token.c
62
src/token.c
@ -1,62 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "include/token.h"
|
||||
#include "include/dstr.h"
|
||||
#include "include/util.h"
|
||||
|
||||
static char* tokentype_names[] = {
|
||||
[TOKEN_TYPE_CALL] = "CALL",
|
||||
[TOKEN_TYPE_NUMBER] = "NUMBER",
|
||||
};
|
||||
|
||||
Token* token_init(TokenType type, char* val, size_t valn) {
|
||||
Token* t = malloc(sizeof(Token));
|
||||
|
||||
t->type = type;
|
||||
t->valn = valn;
|
||||
t->val = val;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void token_destroy(Token* t) {
|
||||
free(t->val);
|
||||
free(t);
|
||||
}
|
||||
|
||||
void token_print(Token* token) { token_print_i(token, 0); }
|
||||
|
||||
void token_print_i(Token *token, int ilvl) {
|
||||
INDENT_BEGIN(ilvl);
|
||||
|
||||
INDENT_TITLE("Token", token);
|
||||
INDENT_FIELD_NONL_START("type")
|
||||
tokentype_print_raw(token->type);
|
||||
INDENT_FIELD_NONL_END
|
||||
INDENT_FIELD("valn", "%ld", token->valn);
|
||||
INDENT_FIELD_NL("val", "\"%s\"", token->val);
|
||||
}
|
||||
|
||||
void tokentype_print_raw(TokenType t) {
|
||||
if (t > TOKEN_TYPE_MAX) {
|
||||
printf("Unknown (%d)", t);
|
||||
log_dbgf("%d is not a valid TokenType (max: %d)", t, TOKEN_TYPE_MAX);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s", tokentype_names[t]);
|
||||
}
|
||||
|
||||
void tokentype_print(TokenType t) { tokentype_print_i(t, 0); }
|
||||
|
||||
void tokentype_print_i(TokenType t, int i) {
|
||||
INDENT_BEGIN(i);
|
||||
|
||||
if (t > TOKEN_TYPE_MAX) {
|
||||
INDENT_FIELD("val", "Unknown (%d)", t);
|
||||
log_dbgf("%d is not a valid TokenType (max: %d)", t, TOKEN_TYPE_MAX);
|
||||
return;
|
||||
}
|
||||
|
||||
INDENT_FIELD("val", "%s", tokentype_names[t]);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user