lommereimar: add lommereimar
This commit adds the required files for the LommeReimar project. It is very good and nice. also incomplete.
This commit is contained in:
parent
29abedb032
commit
f4b2d113f7
149
lommereimar/calculator.c
Normal file
149
lommereimar/calculator.c
Normal file
@ -0,0 +1,149 @@
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "calculator.h"
|
||||
|
||||
FileIter fileiter(const char* filename)
|
||||
{
|
||||
return (FileIter) {
|
||||
.file = fopen(filename, "r"),
|
||||
.done = false,
|
||||
};
|
||||
}
|
||||
|
||||
char fileiter_next(FileIter* file)
|
||||
{
|
||||
if (file->done)
|
||||
return '\0';
|
||||
int c = fgetc(file->file);
|
||||
if (c == EOF) {
|
||||
file->done = true;
|
||||
return '\0';
|
||||
} else {
|
||||
return (char)c;
|
||||
}
|
||||
}
|
||||
|
||||
Lexer lexer(FileIter input_file)
|
||||
{
|
||||
return (Lexer) {
|
||||
.input_file = input_file,
|
||||
.current = fileiter_next(&input_file),
|
||||
.pos = (Position) {
|
||||
.line = 1,
|
||||
.col = 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
void lexer_step(Lexer* lexer)
|
||||
{
|
||||
lexer->current = fileiter_next(&lexer->input_file);
|
||||
if (lexer->current) {
|
||||
lexer->pos.line++;
|
||||
lexer->pos.col = 1;
|
||||
} else {
|
||||
lexer->pos.col++;
|
||||
}
|
||||
}
|
||||
|
||||
Token lexer_single_token(Lexer* lexer, TokenType token_type)
|
||||
{
|
||||
Position pos = lexer->pos;
|
||||
lexer_step(lexer);
|
||||
return (Token) {
|
||||
.type = TokenTypePlus,
|
||||
.pos = pos,
|
||||
.value = NULL,
|
||||
};
|
||||
}
|
||||
|
||||
Token lexer_next(Lexer* lexer)
|
||||
{
|
||||
if (isspace(lexer->current)) {
|
||||
while (isspace(lexer->current))
|
||||
lexer_step(lexer);
|
||||
return lexer_next(lexer);
|
||||
} else if (isdigit(lexer->current)) {
|
||||
Position pos = lexer->pos;
|
||||
size_t i = 0;
|
||||
char value[1234] = { 0 };
|
||||
while (isdigit(lexer->current)) {
|
||||
value[i] = lexer->current;
|
||||
lexer_step(lexer);
|
||||
}
|
||||
char* allocated_value = malloc(sizeof(char) * strlen(value) + 1);
|
||||
strcpy(allocated_value, value);
|
||||
return (Token) {
|
||||
.type = TokenTypeInt,
|
||||
.pos = pos,
|
||||
.value = allocated_value,
|
||||
};
|
||||
} else {
|
||||
switch (lexer->current) {
|
||||
case '+':
|
||||
return lexer_single_token(lexer, TokenTypePlus);
|
||||
case '-':
|
||||
return lexer_single_token(lexer, TokenTypeMinus);
|
||||
case '*':
|
||||
return lexer_single_token(lexer, TokenTypeAsterisk);
|
||||
case '/':
|
||||
return lexer_single_token(lexer, TokenTypeSlash);
|
||||
case '^':
|
||||
return lexer_single_token(lexer, TokenTypeHat);
|
||||
default:
|
||||
return lexer_single_token(lexer, TokenTypeInvalidChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expr* allocate_expr(Expr data)
|
||||
{
|
||||
Expr* expr = malloc(sizeof(Expr));
|
||||
*expr = data;
|
||||
return expr;
|
||||
}
|
||||
|
||||
Parser parser(Lexer lexer)
|
||||
{
|
||||
return (Parser) {
|
||||
.lexer = lexer,
|
||||
.current = lexer_next(&lexer),
|
||||
};
|
||||
}
|
||||
|
||||
void parser_step(Parser* parser)
|
||||
{
|
||||
parser->current = lexer_next(&parser->lexer);
|
||||
}
|
||||
|
||||
Expr* parser_parse_expr(Parser* parser) { return parser_parse_term(parser); }
|
||||
|
||||
Expr* parser_parse_term(Parser* parser)
|
||||
{
|
||||
// Grammar
|
||||
// term -> factor (("+"|"-") factor):*
|
||||
Position pos = parser->current.pos;
|
||||
Expr* left = parser_parse_factor(parser);
|
||||
for (;;) {
|
||||
if (parser->current.type == TokenTypePlus) {
|
||||
parser_step(parser);
|
||||
Expr* right = parser_parse_factor(parser);
|
||||
left = allocate_expr((Expr) {
|
||||
.type = ExprTypeBinary,
|
||||
.pos = pos,
|
||||
.binary = (ExprBinary) {
|
||||
.type = ExprBinaryTypeAdd,
|
||||
.left = left,
|
||||
.right = right,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() { return EXIT_SUCCESS; }
|
115
lommereimar/calculator.h
Normal file
115
lommereimar/calculator.h
Normal file
@ -0,0 +1,115 @@
|
||||
#ifndef CALCULATOR_H
|
||||
#define CALCULATOR_H
|
||||
|
||||
typedef struct {
|
||||
FILE* file;
|
||||
bool done;
|
||||
} FileIter;
|
||||
|
||||
FileIter fileiter(const char* filename);
|
||||
|
||||
char fileiter_next(FileIter* file);
|
||||
|
||||
typedef struct {
|
||||
int line;
|
||||
int col;
|
||||
} Position;
|
||||
|
||||
typedef enum {
|
||||
TokenTypeEof,
|
||||
TokenTypeInvalidChar,
|
||||
TokenTypeInt,
|
||||
TokenTypePlus,
|
||||
TokenTypeMinus,
|
||||
TokenTypeAsterisk,
|
||||
TokenTypeSlash,
|
||||
TokenTypeHat,
|
||||
TokenTypeLParen,
|
||||
TokenTypeRParen,
|
||||
} TokenType;
|
||||
|
||||
typedef struct {
|
||||
// optional
|
||||
char* value;
|
||||
TokenType type;
|
||||
Position pos;
|
||||
} Token;
|
||||
|
||||
typedef struct {
|
||||
FileIter input_file;
|
||||
char current;
|
||||
Position pos;
|
||||
} Lexer;
|
||||
|
||||
Lexer lexer(FileIter input_file);
|
||||
|
||||
void lexer_step(Lexer* lexer);
|
||||
|
||||
Token lexer_single_token(Lexer* lexer, TokenType token_type);
|
||||
|
||||
Token lexer_next(Lexer* lexer);
|
||||
|
||||
typedef enum {
|
||||
ExprTypeEof,
|
||||
ExprTypeError,
|
||||
ExprTypeInt,
|
||||
ExprTypeFloat,
|
||||
ExprTypeUnary,
|
||||
ExprTypeBinary,
|
||||
} ExprType;
|
||||
|
||||
typedef struct Expr Expr;
|
||||
|
||||
typedef enum {
|
||||
ExprBinaryTypeAdd,
|
||||
ExprBinaryTypeSubtract,
|
||||
ExprBinaryTypeMultiply,
|
||||
ExprBinaryTypeDivide,
|
||||
ExprBinaryTypeExponent,
|
||||
} ExprBinaryType;
|
||||
|
||||
typedef struct {
|
||||
ExprBinaryType type;
|
||||
Expr* left;
|
||||
Expr* right;
|
||||
} ExprBinary;
|
||||
|
||||
typedef enum {
|
||||
ExprUnaryTypeNegate,
|
||||
} ExprUnaryType;
|
||||
|
||||
typedef struct {
|
||||
ExprUnaryType type;
|
||||
Expr* subject;
|
||||
} ExprUnary;
|
||||
|
||||
struct Expr {
|
||||
ExprType type;
|
||||
Position pos;
|
||||
union {
|
||||
char* error_value;
|
||||
int int_value;
|
||||
float float_value;
|
||||
ExprUnary unary;
|
||||
ExprBinary binary;
|
||||
};
|
||||
};
|
||||
|
||||
Expr* allocate_expr(Expr data);
|
||||
|
||||
typedef struct {
|
||||
Lexer lexer;
|
||||
Token current;
|
||||
} Parser;
|
||||
|
||||
Parser parser(Lexer lexer);
|
||||
|
||||
void parser_step(Parser* parser);
|
||||
|
||||
Expr* parser_parse_expr(Parser* parser);
|
||||
|
||||
Expr* parser_parse_term(Parser* parser);
|
||||
|
||||
Expr* parser_parse_factor(Parser* parser);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user