Author: mesyeti <mesyeti@mesyeti.uk>
basic: new call syntax
basic/Makefile | 5 - basic/source/compiler.c | 5 - basic/source/compiler.h | 2 basic/source/frontend/c89.c | 7 -- basic/source/lexer.c | 89 ++++++++++++++++++---------------- basic/source/lexer.h | 5 + basic/source/parser.c | 72 ++++++++++++--------------- basic/source/parser.h | 19 ++++--- basic/source/semanticAnalysis.c | 70 +++++++++++++------------- basic/test.bas | 9 -- basic/test2.bas | 1
diff --git a/basic/Makefile b/basic/Makefile index aaa0971a94f97fc700755b58b2d98a4def96ddee..5b435b6bc5dc69fc055a668e2e953e4edd546546 100644 --- a/basic/Makefile +++ b/basic/Makefile @@ -28,9 +28,6 @@ all: $(OUT) @: -run: $(OUT) - '$(dir $<)$(notdir $<)' $(RUNFLAGS) - $(OUT): $(OBJECTS) $(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ @@ -49,4 +46,4 @@ distclean: clean rm $(OUT) -.PHONY: all run clean distclean +.PHONY: all clean distclean diff --git a/basic/source/compiler.c b/basic/source/compiler.c index 14f961a18c1d900f442908e119a41f5e2b0761ee..df9f561f0e56efa6adbd4548a02c6b99380b2c33 100644 --- a/basic/source/compiler.c +++ b/basic/source/compiler.c @@ -27,10 +27,6 @@ void Frontend_CompileFuncCall(FuncCallNode* node) { frontend.compileFuncCall(node); } -void Frontend_CompileAssign(AssignNode* node) { - frontend.compileAssign(node); -} - void Frontend_CompileExtern(ExternNode* node) { frontend.compileExtern(node); } @@ -47,7 +43,6 @@ case NODE_FUNC_DEF: break; case NODE_DIM: break; case NODE_EXTERN: break; case NODE_FUNC_CALL: Frontend_CompileFuncCall(&node->funcCall); break; - case NODE_ASSIGN: Frontend_CompileAssign(&node->assign); break; default: { PrintError(node->i.err, "Unexpected '%s'", Parser_TypeStr(node->i.type)); } diff --git a/basic/source/compiler.h b/basic/source/compiler.h index 6d00872338df8c25bdd2f28c73284b786324b51a..5279ef5f9a599baf99af6686f11eeced12cad581 100644 --- a/basic/source/compiler.h +++ b/basic/source/compiler.h @@ -9,7 +9,6 @@ void (*beginMain)(void); void (*compileFuncDef)(FuncDefNode* node); void (*compileDim)(DimNode* node); void (*compileFuncCall)(FuncCallNode* node); - void (*compileAssign)(AssignNode* node); void (*compileExtern)(ExternNode* node); } Frontend; @@ -19,7 +18,6 @@ void Frontend_BeginMain(void); void Frontend_CompileFuncDef(FuncDefNode* node); void Frontend_CompileDim(DimNode* node); void Frontend_CompileFuncCall(FuncCallNode* node); -void Frontend_CompileAssign(AssignNode* node); void Frontend_CompileExtern(ExternNode* node); typedef struct { diff --git a/basic/source/frontend/c89.c b/basic/source/frontend/c89.c index 870cfea38a9d6c858c427349ec368ee25b560d6a..fff6d42e6d6368671c1bc0f6ef0a64e2bc263c36 100644 --- a/basic/source/frontend/c89.c +++ b/basic/source/frontend/c89.c @@ -145,12 +145,6 @@ CompileFuncCallExpr(node); fprintf(out, ";\n"); } -static void CompileAssign(AssignNode* node) { - fprintf(out, "nitron_%s = ", node->variable); - CompileExprNode(node->rValue); - fprintf(out, ";\n"); -} - static void CompileExtern(ExternNode* node) { CompileDec(node->dec); fprintf(out, ";\n"); @@ -218,7 +212,6 @@ .beginMain = &BeginMain, .compileFuncDef = &CompileFuncDef, .compileDim = &CompileDim, .compileFuncCall = &CompileFuncCall, - .compileAssign = &CompileAssign, .compileExtern = &CompileExtern }; } diff --git a/basic/source/lexer.c b/basic/source/lexer.c index 06ae344d28b518f6745713a23d6a05af98a2075c..7051a3837f322ea88249cc246bdb5eca1d5216bf 100644 --- a/basic/source/lexer.c +++ b/basic/source/lexer.c @@ -70,6 +70,11 @@ #define TOKEN(TYPE, CONTENTS) ((Token) \ {(TYPE), (ErrorInfo) {lexer->fileName, lexer->line}, (CONTENTS)}) +typedef struct { + const char* name; + TokenType token; +} Keyword; + int Lexer_Next(Lexer* lexer, Token* token) { char ch; @@ -97,10 +102,26 @@ case '-': *token = TOKEN(TOKEN_SUBTRACT, NULL); return LEXER_TOKEN; case '*': *token = TOKEN(TOKEN_MULTIPLY, NULL); return LEXER_TOKEN; case '/': *token = TOKEN(TOKEN_DIVIDE, NULL); return LEXER_TOKEN; case '%': *token = TOKEN(TOKEN_MOD, NULL); return LEXER_TOKEN; - case '=': *token = TOKEN(TOKEN_EQUAL, NULL); return LEXER_TOKEN; - case '<': *token = TOKEN(TOKEN_LESS, NULL); return LEXER_TOKEN; - case '>': *token = TOKEN(TOKEN_GREATER, NULL); return LEXER_TOKEN; - case '\n': *token = TOKEN(TOKEN_LINE, NULL); return LEXER_TOKEN; + case '=': { + char next; + GET_CHAR(next); + + if (next == '=') { + *token = TOKEN(TOKEN_EQUAL, NULL); + } + else { + *token = TOKEN(TOKEN_ASSIGN, NULL); + + if (next == '\n') { + -- lexer->line; + } + fseek(lexer->file, -1, SEEK_CUR); + } + return LEXER_TOKEN; + } + case '<': *token = TOKEN(TOKEN_LESS, NULL); return LEXER_TOKEN; + case '>': *token = TOKEN(TOKEN_GREATER, NULL); return LEXER_TOKEN; + case '\n': *token = TOKEN(TOKEN_LINE, NULL); return LEXER_TOKEN; case '\'': { while (true) { GET_CHAR(ch); @@ -132,45 +153,27 @@ if (IsNumeric(string.contents)) { *token = TOKEN(TOKEN_INT, string.contents); return LEXER_TOKEN; } - if (!strcmp(string.contents, "extern")) { - *token = TOKEN(TOKEN_EXTERN, NULL); - String_Free(&string); - return LEXER_TOKEN; - } - if (!strcmp(string.contents, "func") || !strcmp(string.contents, "function")) { - *token = TOKEN(TOKEN_FUNC, NULL); - String_Free(&string); - return LEXER_TOKEN; - } - if (!strcmp(string.contents, "sub")) { - *token = TOKEN(TOKEN_SUB, NULL); - String_Free(&string); - return LEXER_TOKEN; - } - if (!strcmp(string.contents, "dim")) { - *token = TOKEN(TOKEN_DIM, NULL); - String_Free(&string); - return LEXER_TOKEN; - } - if (!strcmp(string.contents, "as")) { - *token = TOKEN(TOKEN_AS, NULL); - String_Free(&string); - return LEXER_TOKEN; - } - if (!strcmp(string.contents, "quit")) { - *token = TOKEN(TOKEN_QUIT, NULL); - String_Free(&string); - return LEXER_TOKEN; - } - if (!strcmp(string.contents, "ptr")) { - *token = TOKEN(TOKEN_PTR, NULL); - String_Free(&string); - return LEXER_TOKEN; - } - if (!strcmp(string.contents, "end")) { - *token = TOKEN(TOKEN_END, NULL); - String_Free(&string); - return LEXER_TOKEN; + + static const Keyword keywords[] = { + {"extern", TOKEN_EXTERN}, + {"func", TOKEN_FUNC}, + {"function", TOKEN_FUNC}, + {"sub", TOKEN_SUB}, + {"dim", TOKEN_DIM}, + {"as", TOKEN_AS}, + {"quit", TOKEN_QUIT}, + {"ptr", TOKEN_PTR}, + {"end", TOKEN_END}, + {"if", TOKEN_IF}, + {"then", TOKEN_THEN} + }; + + for (size_t i = 0; i < sizeof(keywords) / sizeof(Keyword); ++ i) { + if (!strcmp(string.contents, keywords[i].name)) { + *token = TOKEN(keywords[i].token, NULL); + String_Free(&string); + return LEXER_TOKEN; + } } *token = TOKEN(TOKEN_IDENTIFIER, string.contents); diff --git a/basic/source/lexer.h b/basic/source/lexer.h index 0f3e15fa515f4e38f3882d1480fa461bb3e6a706..795de53b9dc0571dac3cd3f59e4f283bdd9ea303 100644 --- a/basic/source/lexer.h +++ b/basic/source/lexer.h @@ -17,6 +17,8 @@ TOKEN_AS, TOKEN_QUIT, TOKEN_PTR, TOKEN_END, + TOKEN_IF, + TOKEN_THEN, // misc TOKEN_IDENTIFIER, @@ -37,7 +39,8 @@ TOKEN_DIVIDE, TOKEN_MOD, TOKEN_EQUAL, TOKEN_LESS, - TOKEN_GREATER + TOKEN_GREATER, + TOKEN_ASSIGN } TokenType; enum { diff --git a/basic/source/parser.c b/basic/source/parser.c index 1212e859a6a468c68afb69a25fd51f243e79d937..9c576721f1b51ac606356abc0b571345566bb051 100644 --- a/basic/source/parser.c +++ b/basic/source/parser.c @@ -55,6 +55,7 @@ #define INFO(TYPE) ((NodeInfo) {TYPE, p->tokens[p->i].err}) static Node ParseBinary(Parser* p); static Node ParseNode(Parser* p); +static Node ParseFuncCall(Parser* p); static void Advance(Parser* p) { ++ p->i; @@ -84,6 +85,11 @@ Advance(p); switch (token->type) { case TOKEN_IDENTIFIER: { + if (p->tokens[p->i].type == TOKEN_LPAREN) { + -- p->i; + return ParseFuncCall(p); + } + ret.ident = (IdentifierNode) {INFO(NODE_IDENTIFIER), NewString(token->contents)}; return ret; } @@ -378,10 +384,13 @@ ret.i = INFO(NODE_FUNC_CALL); ret.func = NewString(p->tokens[p->i].contents); Advance(p); + Expect(p, TOKEN_LPAREN); + + Advance(p); Node* params = NULL; size_t paramsNum = 0; - while (p->tokens[p->i].type != TOKEN_LINE) { + while (p->tokens[p->i].type != TOKEN_RPAREN) { Node param = ParseBinary(p); ++ paramsNum; @@ -389,7 +398,7 @@ params = SafeRealloc(params, paramsNum * sizeof(Node)); params[paramsNum - 1] = param; if ( - (p->tokens[p->i].type != TOKEN_LINE) && + (p->tokens[p->i].type != TOKEN_RPAREN) && (p->tokens[p->i].type != TOKEN_COMMA) ) { PrintError( @@ -402,6 +411,8 @@ Advance(p); } } + Advance(p); + ret.params = params; ret.paramsNum = paramsNum; @@ -410,25 +421,6 @@ node.funcCall = ret; return node; } -static Node ParseAssign(Parser* p) { - AssignNode ret; - ret.i = INFO(NODE_ASSIGN); - ret.variable = NewString(p->tokens[p->i].contents); - - Advance(p); - Expect(p, TOKEN_EQUAL); - Advance(p); - - ret.rValue = SafeMalloc(sizeof(Node)); - *ret.rValue = ParseBinary(p); - - Expect(p, TOKEN_LINE); - - Node node; - node.assign = ret; - return node; -} - static Node ParseExtern(Parser* p) { Advance(p); @@ -441,22 +433,37 @@ node.external = ret; return node; } +// static Node ParseIf(Parser* p) { +// Advance(p); +// +// IfNode ret; +// ret.i = INFO(NODE_IF); +// +// +// } + static Node ParseNode(Parser* p) { switch (p->tokens[p->i].type) { case TOKEN_FUNC: case TOKEN_SUB: return ParseFuncDef(p); case TOKEN_DIM: return ParseDim(p); case TOKEN_EXTERN: return ParseExtern(p); + // case TOKEN_IF: return ParseIf(p); case TOKEN_IDENTIFIER: { if (p->i == p->tokenNum - 1) { PrintError(p->tokens[p->i].err, "Unexpected EOF"); } - if (p->tokens[p->i + 1].type == TOKEN_EQUAL) { - return ParseAssign(p); + Node ret = ParseBinary(p); + + if ( + ((ret.i.type == NODE_BINARY_OP) && (ret.bin.op != TOKEN_ASSIGN)) || + ((ret.i.type != NODE_BINARY_OP) && (ret.i.type != NODE_FUNC_CALL)) + ) { + PrintError(p->tokens[p->i].err, "Unexpected %s", Parser_TypeStr(ret.i.type)); } - return ParseFuncCall(p); + return ret; } default: { PrintError( @@ -551,7 +558,7 @@ puts(""); break; } case NODE_FUNC_CALL: { - printf("%s ", node->funcCall.func); + printf("%s(", node->funcCall.func); for (size_t i = 0; i < node->funcCall.paramsNum; ++ i) { Parser_PrintNode(&node->funcCall.params[i]); @@ -560,13 +567,7 @@ if (i < node->funcCall.paramsNum - 1) { printf(", "); } } - puts(""); - break; - } - case NODE_ASSIGN: { - printf("%s = ", node->assign.variable); - Parser_PrintNode(node->assign.rValue); - puts(""); + puts(")"); break; } case NODE_EXTERN: { @@ -659,12 +660,6 @@ } free(node->funcCall.params); break; } - case NODE_ASSIGN: { - free(node->assign.variable); - Parser_FreeNode(node->assign.rValue); - free(node->assign.rValue); - break; - } default: return; } } @@ -681,7 +676,6 @@ case NODE_PTR: return "ptr"; case NODE_FUNC_DEF: return "function definition"; case NODE_DIM: return "dim"; case NODE_FUNC_CALL: return "function call"; - case NODE_ASSIGN: return "assignment"; default: return "???"; } } diff --git a/basic/source/parser.h b/basic/source/parser.h index 2a3183738fdda807fa4471325c70c89e02a7ce9b..83a7a494083d44d595164b4e308c2719daba5907 100644 --- a/basic/source/parser.h +++ b/basic/source/parser.h @@ -16,8 +16,8 @@ NODE_PTR, NODE_FUNC_DEF, NODE_DIM, NODE_FUNC_CALL, - NODE_ASSIGN, - NODE_EXTERN + NODE_EXTERN, + NODE_IF } NodeType; typedef struct { @@ -94,14 +94,17 @@ } FuncCallNode; typedef struct { NodeInfo i; - char* variable; - Node* rValue; -} AssignNode; + FuncDec dec; +} ExternNode; typedef struct { NodeInfo i; - FuncDec dec; -} ExternNode; + Node* condition; + Node* body; + size_t bodyLen; + Node* elseBody; + size_t elseLen; +} IfNode; union Node { NodeInfo i; @@ -114,8 +117,8 @@ PtrNode ptr; FuncDefNode funcDef; DimNode dim; FuncCallNode funcCall; - AssignNode assign; ExternNode external; + IfNode ifStat; }; typedef struct { diff --git a/basic/source/semanticAnalysis.c b/basic/source/semanticAnalysis.c index 309607c7ec259e7dec820f4647bbb7b9dd6550b4..40e18b6904bd1592a096fb4c8b67d602fc4acc7c 100644 --- a/basic/source/semanticAnalysis.c +++ b/basic/source/semanticAnalysis.c @@ -333,41 +333,41 @@ var.name = NewString(node->dim.name); State_AddVar(var); return GET_PRIM("unit", 0); } - case NODE_ASSIGN: { - Var* var = State_GetVar(node->assign.variable); - - if (!var) { - PrintError( - node->i.err, "Variable '%s' doesn't exist", - node->assign.variable - ); - } - - UsedType left = var->type; - UsedType right = SemanticAnalysis_EvalType(node->assign.rValue); - - Type* leftType = State_GetTypeFromUsed(left); - Type* rightType = State_GetTypeFromUsed(right); - - bool compatible = true; - - if ((left.ptr != right.ptr) || (leftType->type != rightType->type)) { - compatible = false; - } - else if (leftType->type == TYPE_PRIM) { - if (leftType->primType != rightType->primType) compatible = false; - else if (leftType->size < rightType->size) compatible = false; - } - - if (!compatible) { - PrintError( - node->i.err, "Type '%s' cannot be assigned to '%s' variable", - State_GetTypeFromUsed(left)->name, State_GetTypeFromUsed(right)->name - ); - } - - return GET_PRIM("unit", 0); - } +// case NODE_ASSIGN: { +// Var* var = State_GetVar(node->assign.variable); +// +// if (!var) { +// PrintError( +// node->i.err, "Variable '%s' doesn't exist", +// node->assign.variable +// ); +// } +// +// UsedType left = var->type; +// UsedType right = SemanticAnalysis_EvalType(node->assign.rValue); +// +// Type* leftType = State_GetTypeFromUsed(left); +// Type* rightType = State_GetTypeFromUsed(right); +// +// bool compatible = true; +// +// if ((left.ptr != right.ptr) || (leftType->type != rightType->type)) { +// compatible = false; +// } +// else if (leftType->type == TYPE_PRIM) { +// if (leftType->primType != rightType->primType) compatible = false; +// else if (leftType->size < rightType->size) compatible = false; +// } +// +// if (!compatible) { +// PrintError( +// node->i.err, "Type '%s' cannot be assigned to '%s' variable", +// State_GetTypeFromUsed(left)->name, State_GetTypeFromUsed(right)->name +// ); +// } +// +// return GET_PRIM("unit", 0); +// } case NODE_EXTERN: { if (inFunc) { PrintError(node->i.err, "Nested function definitions are not allowed"); diff --git a/basic/test.bas b/basic/test.bas index 4d55461d8e4b380d153580b33028dd90be5a5e96..d480fae239708df93bba9372fba66f3e86bd24d7 100644 --- a/basic/test.bas +++ b/basic/test.bas @@ -1,14 +1,9 @@ 'NITRON extern func puts(str as ptr(char)) int -extern func printf(str as ptr(char), val as int) int sub SayHello() - puts "Hello!" + puts("Hello!") end -dim a as int -a = 4 * 16 - -printf "My number is %d\n", a -SayHello +SayHello() diff --git a/basic/test2.bas b/basic/test2.bas new file mode 100644 index 0000000000000000000000000000000000000000..4c7113ece9ee44c670e0a45d674efc1c6b7fc0cd --- /dev/null +++ b/basic/test2.bas @@ -0,0 +1 @@ +print a / 2 / 3