Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lib/lrama/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ def merge_stdlib(grammar)
).parse

grammar.prepend_parameterized_rules(stdlib_grammar.parameterized_rules)

if stdlib_grammar.aux.prologue
if grammar.aux.prologue
grammar.aux.prologue = stdlib_grammar.aux.prologue + "\n" + grammar.aux.prologue
else
grammar.aux.prologue = stdlib_grammar.aux.prologue
grammar.aux.prologue_first_lineno = stdlib_grammar.aux.prologue_first_lineno
end
end

stdlib_grammar.percent_codes.each do |percent_code|
grammar.percent_codes.unshift(percent_code)
end
end

def prepare_grammar(grammar)
Expand Down
108 changes: 97 additions & 11 deletions lib/lrama/grammar/stdlib.y
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,92 @@

**********************************************************************/

%code requires {
#ifndef LRAMA_STDLIB_LIST_H
#define LRAMA_STDLIB_LIST_H

#include <stdlib.h>
#include <stddef.h>

typedef struct lrama_list_node {
void *val;
struct lrama_list_node *next;
} lrama_list_node_t;

/* Create a new list node with a single value */
__attribute__((unused))
static lrama_list_node_t* lrama_list_new(void *val) {
lrama_list_node_t *node = (lrama_list_node_t*)malloc(sizeof(lrama_list_node_t));
if (node == NULL) {
return NULL;
}
node->val = val;
node->next = NULL;
return node;
}

/* Append a value to the end of the list */
__attribute__((unused))
static lrama_list_node_t* lrama_list_append(lrama_list_node_t *list, void *val) {
lrama_list_node_t *new_node = lrama_list_new(val);
if (new_node == NULL) {
return list;
}

if (list == NULL) {
return new_node;
}

lrama_list_node_t *current = list;
while (current->next != NULL) {
current = current->next;
}
current->next = new_node;
return list;
}

/* Free all nodes in the list (does not free the values themselves) */
__attribute__((unused))
static void lrama_list_free(lrama_list_node_t *list) {
lrama_list_node_t *current = list;
while (current != NULL) {
lrama_list_node_t *next = current->next;
free(current);
current = next;
}
}

/* Count the number of elements in the list */
__attribute__((unused))
static size_t lrama_list_length(const lrama_list_node_t *list) {
size_t count = 0;
const lrama_list_node_t *current = list;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}

/* Get the nth element (0-indexed), returns NULL if out of bounds */
__attribute__((unused))
static void* lrama_list_get(const lrama_list_node_t *list, size_t index) {
const lrama_list_node_t *current = list;
size_t i = 0;
while (current != NULL) {
if (i == index) {
return current->val;
}
i++;
current = current->next;
}
return NULL;
}

#endif /* LRAMA_STDLIB_LIST_H */

}

%%

// -------------------------------------------------------------------
Expand Down Expand Up @@ -94,7 +180,7 @@
*/
%rule list(X)
: /* empty */
| list(X) X
| list(X) X { $$ = lrama_list_append($1, (void*)$2); }
;

/*
Expand All @@ -107,8 +193,8 @@
* nonempty_list_X: nonempty_list_X X
*/
%rule nonempty_list(X)
: X
| nonempty_list(X) X
: X { $$ = lrama_list_new((void*)$1); }
| nonempty_list(X) X { $$ = lrama_list_append($1, (void*)$2); }
;

/*
Expand All @@ -121,8 +207,8 @@
* separated_nonempty_list_separator_X: separated_nonempty_list_separator_X separator X
*/
%rule separated_nonempty_list(separator, X)
: X
| separated_nonempty_list(separator, X) separator X
: X { $$ = lrama_list_new((void*)$1); }
| separated_nonempty_list(separator, X) separator X { $$ = lrama_list_append($1, (void*)$3); }
;

/*
Expand All @@ -131,12 +217,12 @@
* =>
*
* program: separated_list_separator_X
* separated_list_separator_X: option_separated_nonempty_list_separator_X
* option_separated_nonempty_list_separator_X: %empty
* option_separated_nonempty_list_separator_X: separated_nonempty_list_separator_X
* separated_nonempty_list_separator_X: X
* separated_nonempty_list_separator_X: separator separated_nonempty_list_separator_X X
* separated_list_separator_X: %empty
* separated_list_separator_X: X
* separated_list_separator_X: separated_list_separator_X separator X
*/
%rule separated_list(separator, X)
: option(separated_nonempty_list(separator, X))
: /* empty */
| X { $$ = lrama_list_new((void*)$1); }
| separated_list(separator, X) separator X { $$ = lrama_list_append($1, (void*)$3); }
;
16 changes: 12 additions & 4 deletions spec/fixtures/integration/parameterized.y
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define YYDEBUG 1

#include <stdio.h>
#include <stdint.h>

#include "parameterized.h"
#include "parameterized-lexer.h"
Expand All @@ -16,25 +17,32 @@ static int yyerror(YYLTYPE *loc, const char *str);
%union {
int num;
char* str;
void* ptr;
lrama_list_node_t* list;
}

%token <num> ODD EVEN

%type <num> stmt
%type <ptr> stmt_wrapped
%type <str> opt_nl
%type <list> stmts

%locations

%%

program: stmts
program: stmts { lrama_list_free($1);}
;

stmts: stmt+
stmts: stmt_wrapped+ <list> { $$ = $1; }
;

stmt: ODD opt_nl { printf("odd: %d\n", $1); }
| EVEN opt_semicolon { printf("even: %d\n", $1); }
stmt_wrapped: stmt { $$ = (void*)(intptr_t)$1; }
;

stmt: ODD opt_nl { printf("odd: %d\n", $1); $$ = $1; }
| EVEN opt_semicolon { printf("even: %d\n", $1); $$ = $1; }
;

opt_nl: '\n'?[nl] <str> { $$ = $nl; }
Expand Down
16 changes: 12 additions & 4 deletions spec/fixtures/integration/user_defined_parameterized.y
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define YYDEBUG 1

#include <stdio.h>
#include <stdint.h>

#include "user_defined_parameterized.h"
#include "user_defined_parameterized-lexer.h"
Expand All @@ -15,11 +16,15 @@ static int yyerror(YYLTYPE *loc, const char *str);

%union {
int num;
void* ptr;
lrama_list_node_t* list;
}

%token <num> ODD EVEN

%type <num> stmt
%type <ptr> stmt_wrapped
%type <list> stmts

%rule pair(X, Y): X Y
{
Expand All @@ -34,14 +39,17 @@ static int yyerror(YYLTYPE *loc, const char *str);

%%

program: stmts
program: stmts { lrama_list_free($1);}
;

stmts: separated_list(';', stmt)
stmts: separated_list(';', stmt_wrapped) <list> { $$ = $1; }
;

stmt: pair(ODD, EVEN) <num> { printf("pair odd even: %d\n", $1); }
| pair(EVEN, ODD)[result] <num> { printf("pair even odd: %d\n", $result); }
stmt_wrapped: stmt { $$ = (void*)(intptr_t)$1; }
;

stmt: pair(ODD, EVEN) <num> { printf("pair odd even: %d\n", $1); $$ = $1; }
| pair(EVEN, ODD)[result] <num> { printf("pair even odd: %d\n", $result); $$ = $result; }
;

%%
Expand Down
Loading
Loading