more parser progress

generics
cosmonaut 2021-04-16 14:40:28 -07:00
parent d8df1c019a
commit 465daaa931
3 changed files with 197 additions and 40 deletions

115
ast.h
View File

@ -1,19 +1,20 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
typedef enum typedef enum
{ {
Assignment, Assignment,
BinaryExpression, BinaryExpression,
Boolean,
Comment, Comment,
Declaration,
Expression, Expression,
ForLoop, ForLoop,
Identifier, Identifier,
Number, Number,
Return, Return,
String, StringLiteral,
UnaryExpression UnaryExpression
} SyntaxKind; } SyntaxKind;
@ -28,18 +29,22 @@ typedef enum
Subtract Subtract
} BinaryOperator; } BinaryOperator;
typedef enum
{
Bool,
Int,
UInt,
Float,
Double,
String
} PrimitiveType;
typedef union typedef union
{ {
UnaryOperator unaryOperator; UnaryOperator unaryOperator;
BinaryOperator binaryOperator; BinaryOperator binaryOperator;
} Operator; } Operator;
typedef union
{
const char *string;
uint64_t number;
} Value;
typedef struct Node typedef struct Node
{ {
SyntaxKind syntaxKind; SyntaxKind syntaxKind;
@ -50,18 +55,37 @@ typedef struct Node
UnaryOperator unaryOperator; UnaryOperator unaryOperator;
BinaryOperator binaryOperator; BinaryOperator binaryOperator;
} operator; } operator;
Value value; union
{
char *string;
uint64_t number;
} value;
PrimitiveType type;
} Node; } Node;
char* strdup (const char* s)
{
size_t slen = strlen(s);
char* result = malloc(slen + 1);
if(result == NULL)
{
return NULL;
}
memcpy(result, s, slen+1);
return result;
}
const char* SyntaxKindString(SyntaxKind syntaxKind) const char* SyntaxKindString(SyntaxKind syntaxKind)
{ {
switch(syntaxKind) switch(syntaxKind)
{ {
case Assignment: return "Assignment"; case Assignment: return "Assignment";
case BinaryExpression: return "BinaryExpression"; case BinaryExpression: return "BinaryExpression";
case Declaration: return "Declaration";
case Identifier: return "Identifier"; case Identifier: return "Identifier";
case Number: return "Number"; case Number: return "Number";
case String: return "String"; case StringLiteral: return "StringLiteral";
case UnaryExpression: return "UnaryExpression"; case UnaryExpression: return "UnaryExpression";
default: return "Unknown"; default: return "Unknown";
} }
@ -72,7 +96,7 @@ Node* MakeIdentifierNode(
) { ) {
Node* node = (Node*) malloc(sizeof(Node)); Node* node = (Node*) malloc(sizeof(Node));
node->syntaxKind = Identifier; node->syntaxKind = Identifier;
node->value.string = id; node->value.string = strdup(id);
node->childCount = 0; node->childCount = 0;
return node; return node;
} }
@ -92,8 +116,8 @@ Node* MakeStringNode(
const char *string const char *string
) { ) {
Node* node = (Node*) malloc(sizeof(Node)); Node* node = (Node*) malloc(sizeof(Node));
node->syntaxKind = String; node->syntaxKind = StringLiteral;
node->value.string = string; node->value.string = strdup(string);
node->childCount = 0; node->childCount = 0;
return node; return node;
} }
@ -126,6 +150,43 @@ Node* MakeBinaryNode(
return node; return node;
} }
Node* MakeDeclarationNode(
PrimitiveType type,
const char *id
) {
Node* node = (Node*) malloc(sizeof(Node));
node->syntaxKind = Declaration;
node->type = type;
node->value.string = strdup(id);
node->childCount = 0;
return node;
}
Node* MakeAssignmentNode(
Node *left,
Node *right
) {
Node* node = (Node*) malloc(sizeof(Node));
node->syntaxKind = Assignment;
node->childCount = 2;
node->children = malloc(sizeof(Node*) * 2);
node->children[0] = left;
node->children[1] = right;
return node;
}
static const char* PrimitiveTypeToString(PrimitiveType type)
{
switch (type)
{
case Int: return "Int";
case UInt: return "UInt";
case Bool: return "Bool";
}
return "Unknown";
}
static void PrintBinaryOperator(BinaryOperator expression) static void PrintBinaryOperator(BinaryOperator expression)
{ {
switch (expression) switch (expression)
@ -142,27 +203,43 @@ static void PrintBinaryOperator(BinaryOperator expression)
printf("\n"); printf("\n");
} }
static void PrintNode(Node *node) static void PrintNode(Node *node, int tabCount)
{ {
printf("%s\n", SyntaxKindString(node->syntaxKind)); uint32_t i;
for (i = 0; i < tabCount; i += 1)
{
printf(" ");
}
printf("%s: ", SyntaxKindString(node->syntaxKind));
switch (node->syntaxKind) switch (node->syntaxKind)
{ {
case BinaryExpression: case BinaryExpression:
PrintBinaryOperator(node->operator.binaryOperator); PrintBinaryOperator(node->operator.binaryOperator);
break; break;
case Declaration:
printf("%s %s", PrimitiveTypeToString(node->type), node->value.string);
break;
case Identifier:
printf("%s", node->value.string);
break;
case Number: case Number:
printf("%lu\n", node->value.number); printf("%lu", node->value.number);
break; break;
} }
printf("\n");
} }
void PrintTree(Node *node) void PrintTree(Node *node, uint32_t tabCount)
{ {
uint32_t i; uint32_t i;
PrintNode(node); PrintNode(node, tabCount);
for (i = 0; i < node->childCount; i += 1) for (i = 0; i < node->childCount; i += 1)
{ {
PrintTree(node->children[i]); PrintTree(node->children[i], tabCount + 1);
} }
} }

View File

@ -1,11 +1,15 @@
%{ %option noyywrap
extern int yywrap() { return 1; }
%}
%% %%
[0-9]+ return NUMBER; [0-9]+ return NUMBER;
"int" return INT;
"uint" return UINT;
"float" return FLOAT;
"double" return DOUBLE;
"string" return STRING;
"bool" return BOOL;
[a-zA-Z][a-zA-Z0-9]* return ID; [a-zA-Z][a-zA-Z0-9]* return ID;
\"[a-zA-Z][a-zA-Z0-9]*\" return STRING; \"[a-zA-Z][a-zA-Z0-9]*\" return STRING_LITERAL;
"+" return PLUS; "+" return PLUS;
"-" return MINUS; "-" return MINUS;
"*" return MULTIPLY; "*" return MULTIPLY;
@ -30,6 +34,7 @@ extern int yywrap() { return 1; }
"{" return LEFT_BRACE; "{" return LEFT_BRACE;
"}" return RIGHT_BRACE; "}" return RIGHT_BRACE;
"//" return COMMENT; "//" return COMMENT;
"\n" return NEWLINE; " " ;
"\n" ;
[ \t] ; [ \t] ;
%% %%

105
wraith.y
View File

@ -1,6 +1,25 @@
%{
#include <stdio.h>
#include "ast.h"
#define YYSTYPE struct Node*
void yyerror(FILE *fp, char *s)
{
fprintf (stderr, "%s\n", s);
}
Node **statements;
uint32_t statementCount;
uint32_t i;
%}
%token NUMBER %token NUMBER
%token ID %token INT
%token UINT
%token FLOAT
%token DOUBLE
%token STRING %token STRING
%token BOOL
%token ID
%token STRING_LITERAL
%token PLUS %token PLUS
%token MINUS %token MINUS
%token MULTIPLY %token MULTIPLY
@ -27,25 +46,27 @@
%token COMMENT %token COMMENT
%token NEWLINE %token NEWLINE
%parse-param { FILE* fp }
%left PLUS MINUS %left PLUS MINUS
%left BANG %left BANG
%left LEFT_PAREN RIGHT_PAREN %left LEFT_PAREN RIGHT_PAREN
%{
#include "ast.h"
#define YYSTYPE struct Node*
%}
%% %%
Main : Expression NEWLINE Program : Statements
{ {
PrintTree($1); for (i = 0; i < statementCount; i += 1)
{
PrintTree(statements[i], 0);
}
} }
PrimaryExpression : ID Identifier : ID
{ {
$$ = MakeIdentifierNode(yytext); $$ = MakeIdentifierNode(yytext);
} }
PrimaryExpression : Identifier
| NUMBER | NUMBER
{ {
$$ = MakeNumberNode(yytext); $$ = MakeNumberNode(yytext);
@ -75,17 +96,71 @@ Expression : PrimaryExpression
| UnaryExpression | UnaryExpression
| BinaryExpression | BinaryExpression
; ;
VariableDeclaration : INT ID
{
$$ = MakeDeclarationNode(Int, yytext);
}
| UINT ID
{
$$ = MakeDeclarationNode(UInt, yytext);
}
| FLOAT ID
{
$$ = MakeDeclarationNode(Float, yytext);
}
| DOUBLE ID
{
$$ = MakeDeclarationNode(Double, yytext);
}
| STRING ID
{
$$ = MakeDeclarationNode(String, yytext);
}
| BOOL ID
{
$$ = MakeDeclarationNode(Bool, yytext);
}
AssignmentStatement : VariableDeclaration EQUAL Expression
{
$$ = MakeAssignmentNode($1, $3);
}
| Identifier EQUAL Expression
{
$$ = MakeAssignmentNode($1, $3);
}
Statement : AssignmentStatement
;
CompleteStatement : Statement SEMICOLON;
Statements : Statements CompleteStatement
{
statements = realloc(statements, statementCount + 1);
statements[statementCount] = $2;
statementCount += 1;
}
|
{
$$ = NULL;
}
%% %%
#include "lex.yy.c" #include "lex.yy.c"
/* yacc error handler */ int main(int argc, char *argv[])
void yyerror(char *s)
{ {
fprintf (stderr, "%s\n", s); if (argc < 2)
{
printf("Please provide a file.\n");
return 1;
} }
int main(void) FILE *fp = fopen(argv[1], "r");
{ yyin = fp;
return yyparse(); yyparse(fp);
fclose(fp);
return 0;
} }