added a working thread-safe lemon example
This commit is contained in:
parent
97465b12e2
commit
6d5f42daf7
|
@ -0,0 +1,5 @@
|
|||
flex_scanner.h
|
||||
flex_scanner.c
|
||||
lemon_parser.h
|
||||
lemon_parser.c
|
||||
lemon_test
|
|
@ -0,0 +1,9 @@
|
|||
rm -f lemon_test lemon_parser.c flex_scanner.c
|
||||
echo "Lemon"
|
||||
lemon lemon_parser.y
|
||||
echo "Flex"
|
||||
# flex lexer.l
|
||||
flex --outfile=flex_scanner.c --header-file=flex_scanner.h flex_scanner.l
|
||||
echo "Compile"
|
||||
g++ main.cpp lemon_parser.c flex_scanner.c -o lemon_test -std=c++11 -pthread
|
||||
./lemon_test
|
|
@ -0,0 +1,17 @@
|
|||
%{
|
||||
#include "lemon_parser.h"
|
||||
#include <stdlib.h>
|
||||
%}
|
||||
|
||||
|
||||
%option reentrant
|
||||
%option noyywrap
|
||||
|
||||
|
||||
%%
|
||||
[0-9]+|[0-9]+.[0-9]+ return NUMBER;
|
||||
[+] return PLUS;
|
||||
[\n] return NL;
|
||||
[ \t] ; /* skip whitespace */
|
||||
. {printf("Unknown character '%c'\n", yytext[0]); return 0;}
|
||||
%%
|
|
@ -0,0 +1,23 @@
|
|||
%include {
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
}
|
||||
%syntax_error { printf("Lemon syntax error\n"); }
|
||||
|
||||
%token_type {const char*}
|
||||
%type expr {float}
|
||||
|
||||
%left PLUS MINUS .
|
||||
|
||||
%extra_argument { float* result }
|
||||
|
||||
start ::= prog.
|
||||
|
||||
prog ::= prog print NL .
|
||||
prog ::= prog print .
|
||||
prog ::= .
|
||||
|
||||
print ::= expr(a) . { *result = a; }
|
||||
|
||||
expr(a) ::= NUMBER(b) . { a = atof(b); }
|
||||
expr(a) ::= expr(b) PLUS expr(c) . { a = b + c; }
|
|
@ -0,0 +1,65 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <thread>
|
||||
#include "flex_scanner.h"
|
||||
#include "lemon_parser.h"
|
||||
|
||||
// Based on https://github.com/theory/flex-lemon-example
|
||||
// and http://stackoverflow.com/questions/24833465/bison-yacc-vs-lemon-vs-standard-input
|
||||
typedef float ResultType;
|
||||
|
||||
void *ParseAlloc(void *(*mallocProc)(size_t));
|
||||
void ParseFree(void *p, void (*freeProc)(void*));
|
||||
void Parse(void *yyp, int yymajor, const char* text, ResultType*);
|
||||
|
||||
int yylex(void);
|
||||
int yylval;
|
||||
|
||||
|
||||
float parseString(const char* string) {
|
||||
yyscan_t scanner;
|
||||
yylex_init(&scanner);
|
||||
|
||||
// Scan the provided string
|
||||
YY_BUFFER_STATE state = yy_scan_string(string, scanner);
|
||||
|
||||
void* lemonParser = ParseAlloc(malloc);
|
||||
int tokenCode;
|
||||
ResultType result;
|
||||
do {
|
||||
tokenCode = yylex(scanner);
|
||||
Parse(lemonParser, tokenCode, yyget_text(scanner), &result);
|
||||
// printf("Token %d\n", tokenCode);
|
||||
} while (tokenCode > 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void multithreadTest(int numOfParses, int id) {
|
||||
for (int n = 0; n < numOfParses; ++n) {
|
||||
int a = rand() % 1000 + 1;
|
||||
int b = rand() % 1000 + 1;
|
||||
int c = a + b;
|
||||
char string[32];
|
||||
sprintf(string, "%d + %d", a, b);
|
||||
|
||||
int result = parseString(string);
|
||||
if (result != c) printf("Error[%d]! %s != %d\n", id, string, result);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const int numThreads = 10;
|
||||
int numRuns = 5000;
|
||||
|
||||
std::thread threads[numThreads];
|
||||
for (int n = 0; n < numThreads; ++n) {
|
||||
threads[n] = std::thread(multithreadTest, numRuns, n);
|
||||
}
|
||||
|
||||
for (int n = 0; n < numThreads; ++n) {
|
||||
threads[n].join();
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue