Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow bison parsers to be generated as libraries #3259

Merged
merged 20 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from 16 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
24 changes: 24 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
BasedOnStyle: WebKit
BreakBeforeBraces: Attach
AccessModifierOffset: -2
AlignAfterOpenBracket: AlwaysBreak
AlignOperands: true
Cpp11BracedListStyle: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
ColumnLimit: 80
IndentWidth: 2
Language: Cpp
NamespaceIndentation: None
AlwaysBreakTemplateDeclarations: true
FixNamespaceComments: true
SpaceBeforeCpp11BracedList: false
DerivePointerAlignment: false
PointerAlignment: Right
AllowShortCaseLabelsOnASingleLine: true
ReflowComments: false
...
204 changes: 158 additions & 46 deletions k-distribution/include/kframework/cparser/main.c
Original file line number Diff line number Diff line change
@@ -1,37 +1,102 @@
#include "node.h"
#include "parser.tab.h"
#include "scanner.h"

#include <assert.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "node.h"
#include "parser.tab.h"
#include "scanner.h"

struct string_buffer {
FILE *fp;
char *buf;
size_t capacity;
size_t idx;
};
Baltoli marked this conversation as resolved.
Show resolved Hide resolved

struct string_buffer string_buffer_new_memory(size_t initial) {
assert(initial > 0 && "Invalid initial capacity");

char *buf = malloc(sizeof(*buf) * initial);
buf[0] = '\0';

struct string_buffer ret
= {.fp = NULL, .buf = buf, .capacity = initial, .idx = 0};
return ret;
}

struct string_buffer string_buffer_new_file(FILE *fp) {
struct string_buffer ret = {.fp = fp, .buf = NULL, .capacity = 0, .idx = 0};
return ret;
}

void string_buffer_grow(struct string_buffer *sb) {
if (sb->fp) {
return;
}

size_t old_cap = sb->capacity;
size_t new_cap = old_cap * 2;

sb->buf = realloc(sb->buf, new_cap);
sb->buf[old_cap] = 0;
sb->capacity = new_cap;
}

int buf_printf(struct string_buffer *sb, char const *format, ...) {
va_list args;

if (sb->fp) {
va_start(args, format);
int result = vfprintf(sb->fp, format, args);
va_end(args);
return result;
} else {
va_start(args, format);
int required = vsnprintf(NULL, 0, format, args) + 1;
va_end(args);

while ((sb->capacity - sb->idx) < required) {
string_buffer_grow(sb);
}

va_start(args, format);
Baltoli marked this conversation as resolved.
Show resolved Hide resolved
vsnprintf(sb->buf + sb->idx, required, format, args);
va_end(args);

sb->idx += required - 1;
return required;
}
}

static void append(char *buf, size_t *bufidx, char *str, size_t len) {
memcpy(buf+*bufidx, str, len);
memcpy(buf + *bufidx, str, len);
*bufidx = *bufidx + len;
}

char *enquote(char *str) {
size_t len = strlen(str);
size_t bufidx = 1;
char *res = malloc(len*4+3);
char *res = malloc(len * 4 + 3);
res[0] = '"';
for(int idx = 0; idx < len; idx++) {
for (int idx = 0; idx < len; idx++) {
char c = str[idx];
switch (c) {
case '"': append(res, &bufidx, "\\\"", 2); break;
case '\\': append(res, &bufidx, "\\\\", 2); break;
case '\n': append(res, &bufidx, "\\n", 2); break;
case '\t': append(res, &bufidx, "\\t", 2); break;
case '\r': append(res, &bufidx, "\\r", 2); break;
default:
if (c >= 32 && c < 127) {
append(res, &bufidx, &c, 1);
} else {
char buf[5];
sprintf(buf, "\\x%02hhx", (unsigned char)c);
append(res, &bufidx, buf, 4);
}
case '"': append(res, &bufidx, "\\\"", 2); break;
case '\\': append(res, &bufidx, "\\\\", 2); break;
case '\n': append(res, &bufidx, "\\n", 2); break;
case '\t': append(res, &bufidx, "\\t", 2); break;
case '\r': append(res, &bufidx, "\\r", 2); break;
default:
if (c >= 32 && c < 127) {
append(res, &bufidx, &c, 1);
} else {
char buf[5];
sprintf(buf, "\\x%02hhx", (unsigned char)c);
append(res, &bufidx, buf, 4);
}
}
}
append(res, &bufidx, "\"", 2);
Expand Down Expand Up @@ -65,7 +130,8 @@ char *injSymbol(char *lesser, char *greater) {
char *prefix = "inj{";
char *infix = ", ";
char *suffix = "}";
size_t len = strlen(prefix) + strlen(suffix) + strlen(lesser) + strlen(greater) + strlen(infix) + 1;
size_t len = strlen(prefix) + strlen(suffix) + strlen(lesser)
+ strlen(greater) + strlen(infix) + 1;
char *symbol = malloc(len);
strcpy(symbol, prefix);
strcat(symbol, lesser);
Expand Down Expand Up @@ -101,56 +167,102 @@ YYSTYPE mergeAmb(YYSTYPE x0, YYSTYPE x1) {
return result;
}

void print(node *current) {
void print(struct string_buffer *sb, node *current) {
if (current->hasLocation) {
printf("Lbl'Hash'location{");
printf("%s", current->sort);
printf("}(");
buf_printf(sb, "Lbl'Hash'location{");
buf_printf(sb, "%s", current->sort);
buf_printf(sb, "}(");
}
printf("%s", current->symbol);
buf_printf(sb, "%s", current->symbol);
if (!current->str) {
printf("(");
buf_printf(sb, "(");
for (int i = 0; i < current->nchildren; i++) {
node *child = current->children[i];
print(child);
if (i != current->nchildren - 1) printf(",");
print(sb, child);
if (i != current->nchildren - 1)
buf_printf(sb, ",");
}
printf(")");
buf_printf(sb, ")");
}
if (current->hasLocation) {
printf(", \\dv{SortString{}}(%s), \\dv{SortInt{}}(\"%d\"), \\dv{SortInt{}}(\"%d\"), \\dv{SortInt{}}(\"%d\"), \\dv{SortInt{}}(\"%d\"))", enquote(current->location.filename), current->location.first_line, current->location.first_column, current->location.last_line, current->location.last_column);
buf_printf(
sb,
", \\dv{SortString{}}(%s), \\dv{SortInt{}}(\"%d\"), "
"\\dv{SortInt{}}(\"%d\"), \\dv{SortInt{}}(\"%d\"), "
"\\dv{SortInt{}}(\"%d\"))",
enquote(current->location.filename), current->location.first_line,
current->location.first_column, current->location.last_line,
current->location.last_column);
}
}

extern node *result;
extern char *filename;

int main(int argc, char **argv) {
static void parse_internal(
struct string_buffer *sb, char *program_name, char *input_file,
char *location_file) {
yyscan_t scanner;
yylex_init(&scanner);
if (argc < 2 || argc > 3) {
fprintf(stderr, "usage: %s <file> [<filename>]\n", argv[0]);
exit(1);
}
if (argc == 3) {
filename=argv[2];
} else {
filename=argv[1];
}
FILE *f = fopen(argv[1], "r");
yylex_init(&scanner);

filename = location_file;

FILE *f = fopen(input_file, "r");
if (!f) {
int len = strlen(argv[0]) + strlen(argv[1]) + 19;
int len = strlen(program_name) + strlen(input_file) + 19;
char *buf = malloc(len);
snprintf(buf, len, "%s: cannot access '%s'", argv[0], argv[1]);
snprintf(buf, len, "%s: cannot access '%s'", program_name, input_file);
perror(buf);
exit(1);
}

yyset_in(f, scanner);

int status = yyparse(scanner);
if (status) {
exit(status);
}
print(result);
printf("\n");

print(sb, result);
yylex_destroy(scanner);
}

#define CONCAT(X, Y) X##Y
#define NAME(sort) CONCAT(parse_, sort)
#define PARSER_FUNCTION NAME(K_BISON_PARSER_SORT)

#define XSTR(S) #S
#define STR(S) XSTR(S)

char *PARSER_FUNCTION(char *input_file, char *location_file) {
struct string_buffer sb = string_buffer_new_memory(1024);

if (!location_file) {
location_file = input_file;
}

parse_internal(&sb, STR(PARSER_FUNCTION), input_file, location_file);
return sb.buf;
}

#ifdef K_BISON_PARSER_MAIN

int main(int argc, char **argv) {
if (argc < 2 || argc > 3) {
fprintf(stderr, "usage: %s <file> [<filename>]\n", argv[0]);
exit(1);
}

char *location_file;
if (argc == 3) {
location_file = argv[2];
} else {
location_file = argv[1];
}

struct string_buffer sb = string_buffer_new_file(stdout);
parse_internal(&sb, argv[0], argv[1], location_file);
printf("\n");
}

#endif
9 changes: 5 additions & 4 deletions k-distribution/include/kframework/cparser/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
#define NODE_H

typedef struct YYLTYPE YYLTYPE;
struct YYLTYPE
{
struct YYLTYPE {
char *filename;
int first_line;
int first_column;
Expand All @@ -13,17 +12,19 @@ struct YYLTYPE

#define YYLTYPE struct YYLTYPE

#include <stdbool.h>
#include "parser.tab.h"

#include <stdbool.h>
#include <stddef.h>

typedef struct node {
char *symbol;
char *sort;
bool str;
size_t nchildren;
bool hasLocation;
YYLTYPE location;
struct node * children[];
struct node *children[];
} node;

typedef union value_type {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
Baltoli marked this conversation as resolved.
Show resolved Hide resolved
26 changes: 26 additions & 0 deletions k-distribution/tests/regression-new/bison-parser-library/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
DEF=test
EXT=test
TESTDIR=.
KOMPILE_FLAGS=--syntax-module TEST --gen-glr-bison-parser --bison-parser-library --llvm-kompile-type c --llvm-kompile-output libfoo

UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
CC=clang
else
CC=gcc
endif

check: test.kore
diff test.kore test.out

test: kompile
$(CC) test.c -Ltest-kompiled -lfoo -lparser_KItem_TEST -o test

test.kore: test test.in
LD_LIBRARY_PATH=test-kompiled ./test test.in > test.kore

include ../../../include/kframework/ktest.mak

clean:
rm -rf ./test-kompiled .depend-tmp .depend .kompile-* .krun-* .kprove-* .kbmc-* kore-exec.tar.gz
rm -rf test.kore test
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <stdio.h>

char *parse_KItem(char *, char *);

int main(int argc, char **argv) { printf("%s\n", parse_KItem(argv[1], NULL)); }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright (c) K Team. All Rights Reserved.
module TEST
syntax Foo [locations]
syntax Foo ::= foo() | bar()
endmodule
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
inj{SortFoo{}, SortKItem{}}(Lbl'Hash'location{SortFoo{}}(Lblfoo'LParRParUnds'TEST'Unds'Foo{}(), \dv{SortString{}}("test.in"), \dv{SortInt{}}("1"), \dv{SortInt{}}("0"), \dv{SortInt{}}("1"), \dv{SortInt{}}("4")))
4 changes: 1 addition & 3 deletions kernel/src/main/java/org/kframework/kast/KastFrontEnd.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@
import java.util.Set;
import java.util.stream.Collectors;

import static org.kframework.kore.KORE.*;

public class KastFrontEnd extends FrontEnd {

public static List<com.google.inject.Module> getModules() {
Expand Down Expand Up @@ -205,7 +203,7 @@ public int run() {

KRead kread = new KRead(kem, files.get(), options.input, options.global);
if (options.genParser || options.genGlrParser) {
kread.createBisonParser(parsingMod, sort, options.bisonOutputFile(), options.genGlrParser, options.bisonFile, options.bisonStackMaxDepth);
kread.createBisonParser(parsingMod, sort, options.bisonOutputFile(), options.genGlrParser, options.bisonFile, options.bisonStackMaxDepth, false);
try {
Files.copy(options.bisonOutputFile().toPath(), files.get().resolveKompiled("parser_" + sort.name() + "_" + options.module).toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {}
Expand Down
Loading