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

View File

@ -1,11 +1,15 @@
%{
extern int yywrap() { return 1; }
%}
%option noyywrap
%%
[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 STRING;
\"[a-zA-Z][a-zA-Z0-9]*\" return STRING_LITERAL;
"+" return PLUS;
"-" return MINUS;
"*" return MULTIPLY;
@ -30,6 +34,7 @@ extern int yywrap() { return 1; }
"{" return LEFT_BRACE;
"}" return RIGHT_BRACE;
"//" return COMMENT;
"\n" return NEWLINE;
" " ;
"\n" ;
[ \t] ;
%%

107
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 ID
%token INT
%token UINT
%token FLOAT
%token DOUBLE
%token STRING
%token BOOL
%token ID
%token STRING_LITERAL
%token PLUS
%token MINUS
%token MULTIPLY
@ -27,25 +46,27 @@
%token COMMENT
%token NEWLINE
%parse-param { FILE* fp }
%left PLUS MINUS
%left BANG
%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);
}
PrimaryExpression : Identifier
| NUMBER
{
$$ = MakeNumberNode(yytext);
@ -75,17 +96,71 @@ Expression : PrimaryExpression
| UnaryExpression
| 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"
/* yacc error handler */
void yyerror(char *s)
int main(int argc, char *argv[])
{
fprintf (stderr, "%s\n", s);
}
if (argc < 2)
{
printf("Please provide a file.\n");
return 1;
}
int main(void)
{
return yyparse();
FILE *fp = fopen(argv[1], "r");
yyin = fp;
yyparse(fp);
fclose(fp);
return 0;
}