make file added
This commit is contained in:
128
src/sylt/lexer.c
128
src/sylt/lexer.c
@@ -1,7 +1,9 @@
|
||||
#include "lexer.h"
|
||||
#include "exception.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio,h>
|
||||
#include <stdio.h>
|
||||
|
||||
Lexer initLexer(char *source) {
|
||||
Lexer newLexer = {
|
||||
@@ -11,6 +13,7 @@ Lexer initLexer(char *source) {
|
||||
.lineNumber = 1,
|
||||
.currentChar = '\0'
|
||||
};
|
||||
readChar(&newLexer);
|
||||
return newLexer;
|
||||
}
|
||||
|
||||
@@ -25,63 +28,134 @@ void readChar(Lexer *lexer) {
|
||||
}
|
||||
|
||||
void skipWhitespace(Lexer *lexer) {
|
||||
switch (lexer->currentChar)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
if (lexer->currentChar == '\n')
|
||||
lexer->lineNumber++;
|
||||
bool whitespace = true;
|
||||
|
||||
readChar(lexer);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
while (whitespace)
|
||||
{
|
||||
switch (lexer->currentChar)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
if (lexer->currentChar == '\n')
|
||||
lexer->lineNumber++;
|
||||
|
||||
readChar(lexer);
|
||||
break;
|
||||
|
||||
default:
|
||||
whitespace = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Token readNumber(Lexer *lexer) {
|
||||
int startPos = lexer->position;
|
||||
int dotCount = 0;
|
||||
int strLength = 0;
|
||||
|
||||
size_t outputCap = 8;
|
||||
char *output = malloc(outputCap);
|
||||
|
||||
if (!output) {
|
||||
exceptionMessage(EXCEPTION_MEMORY_ALLOCATION_FAILURE, "Lexer failed to allocate memory.", lexer->lineNumber, lexer->position);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (isdigit(lexer->currentChar) || lexer->currentChar == '.')
|
||||
{
|
||||
if (lexer->currentChar == '.') {
|
||||
dotCount++;
|
||||
|
||||
if (dotCount > 1) {
|
||||
exceptionMessage(EXCEPTION_MALFORMED_NUMBER, "Too many dots in decimal.", lexer->lineNumber, lexer->position);
|
||||
|
||||
char buffer[strLength+1];
|
||||
strncpy(buffer, lexer->source + startPos, strLength+1);
|
||||
buffer[strLength+1] = 0;
|
||||
|
||||
return NEW_TOKEN(lexer, TOKEN_ILLEGAL, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// allocate more memory if we reach the end of our buffer
|
||||
if (strLength + 1 >= outputCap) {
|
||||
char *temp = realloc(output, outputCap*=2);
|
||||
|
||||
if (!temp) {
|
||||
exceptionMessage(EXCEPTION_MEMORY_ALLOCATION_FAILURE, "Lexer failed to allocate memory.", lexer->lineNumber, lexer->position);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
output = temp;
|
||||
}
|
||||
|
||||
output[strLength] = lexer->source[lexer->position];
|
||||
strLength++;
|
||||
readChar(lexer);
|
||||
|
||||
if (lexer->currentChar == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
output[strLength] = 0;
|
||||
|
||||
if (dotCount == 0)
|
||||
return NEW_TOKEN(lexer, TOKEN_INT, output);
|
||||
else
|
||||
return NEW_TOKEN(lexer, TOKEN_FLOAT, output);
|
||||
}
|
||||
|
||||
Token nextToken(Lexer *lexer) {
|
||||
//Token tok;
|
||||
Token tok;
|
||||
skipWhitespace(lexer);
|
||||
|
||||
switch (lexer->currentChar)
|
||||
{
|
||||
case '+':
|
||||
return NEW_TOKEN(lexer, PLUS, "+");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_PLUS, "+");
|
||||
break;
|
||||
case '-':
|
||||
return NEW_TOKEN(lexer, MINUS, "-");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_MINUS, "-");
|
||||
break;
|
||||
case '*':
|
||||
return NEW_TOKEN(lexer, ASTERISK, "*");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_ASTERISK, "*");
|
||||
break;
|
||||
case '/':
|
||||
return NEW_TOKEN(lexer, SLASH, "/");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_SLASH, "/");
|
||||
break;
|
||||
case '%':
|
||||
return NEW_TOKEN(lexer, MODULUS, "%");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_MODULUS, "%");
|
||||
break;
|
||||
case '^':
|
||||
return NEW_TOKEN(lexer, POW, "^");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_POW, "^");
|
||||
break;
|
||||
case '(':
|
||||
return NEW_TOKEN(lexer, LPAREN, "(");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_LPAREN, "(");
|
||||
break;
|
||||
case ')':
|
||||
return NEW_TOKEN(lexer, RPAREN, ")");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_RPAREN, ")");
|
||||
break;
|
||||
case '\0':
|
||||
return NEW_TOKEN(lexer, EOF, "");
|
||||
|
||||
case '\0': // EOF
|
||||
tok = NEW_TOKEN(lexer, TOKEN_EOF, "EOF");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isdigit())
|
||||
if (isdigit(lexer->currentChar)) {
|
||||
tok = readNumber(lexer);
|
||||
} else {
|
||||
tok = NEW_TOKEN(lexer, TOKEN_ILLEGAL, &lexer->currentChar);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//return tok;
|
||||
readChar(lexer);
|
||||
return tok;
|
||||
}
|
||||
Reference in New Issue
Block a user