|
Packit Service |
360c39 |
%code requires {
|
|
Packit Service |
360c39 |
/* Required to break a circular dependency introduced with bison 2.6 */
|
|
Packit Service |
360c39 |
typedef void* yyscan_t;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
%code top {
|
|
Packit Service |
360c39 |
#include <errno.h>
|
|
Packit Service |
360c39 |
#include "lang.h"
|
|
Packit Service |
360c39 |
#include "lexer.h"
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
static int yyerror(struct lgfs2_lang_state *state, yyscan_t lexer, const char *errorstr)
|
|
Packit Service |
360c39 |
{
|
|
Packit Service |
360c39 |
fprintf(stderr, "%d:%d: %s\n", state->ls_linenum, state->ls_colnum, errorstr);
|
|
Packit Service |
360c39 |
return 1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
%defines
|
|
Packit Service |
360c39 |
%debug
|
|
Packit Service |
360c39 |
%define api.pure
|
|
Packit Service |
360c39 |
%parse-param { struct lgfs2_lang_state *state }
|
|
Packit Service |
360c39 |
%parse-param { yyscan_t lexer }
|
|
Packit Service |
360c39 |
%lex-param { yyscan_t lexer }
|
|
Packit Service |
360c39 |
%start script
|
|
Packit Service |
360c39 |
%token TOK_COLON
|
|
Packit Service |
360c39 |
%token TOK_COMMA
|
|
Packit Service |
360c39 |
%token TOK_ID
|
|
Packit Service |
360c39 |
%token TOK_LBRACE
|
|
Packit Service |
360c39 |
%token TOK_LBRACKET
|
|
Packit Service |
360c39 |
%token TOK_NUMBER
|
|
Packit Service |
360c39 |
%token TOK_OFFSET
|
|
Packit Service |
360c39 |
%token TOK_RBRACE
|
|
Packit Service |
360c39 |
%token TOK_RBRACKET
|
|
Packit Service |
360c39 |
%token TOK_SEMI
|
|
Packit Service |
360c39 |
%token TOK_SET
|
|
Packit Service |
360c39 |
%token TOK_GET
|
|
Packit Service |
360c39 |
%token TOK_STATE
|
|
Packit Service |
360c39 |
%token TOK_STRING
|
|
Packit Service |
360c39 |
%token TOK_PATH
|
|
Packit Service |
360c39 |
%%
|
|
Packit Service |
360c39 |
script: statements {
|
|
Packit Service |
360c39 |
state->ls_ast_root = $1;
|
|
Packit Service |
360c39 |
state->ls_interp_curr = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
| statements TOK_SEMI {
|
|
Packit Service |
360c39 |
state->ls_ast_root = $1;
|
|
Packit Service |
360c39 |
state->ls_interp_curr = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
statements: statements TOK_SEMI statement {
|
|
Packit Service |
360c39 |
state->ls_ast_tail->ast_left = $3;
|
|
Packit Service |
360c39 |
state->ls_ast_tail = $3;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
| statement {
|
|
Packit Service |
360c39 |
if (state->ls_ast_tail == NULL)
|
|
Packit Service |
360c39 |
state->ls_ast_tail = $1;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
statement: set_stmt { $$ = $1;}
|
|
Packit Service |
360c39 |
| get_stmt { $$ = $1; }
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
set_stmt: TOK_SET blockspec structspec {
|
|
Packit Service |
360c39 |
$1->ast_right = $2;
|
|
Packit Service |
360c39 |
$2->ast_right = $3;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
| TOK_SET blockspec typespec structspec {
|
|
Packit Service |
360c39 |
$1->ast_right = $2;
|
|
Packit Service |
360c39 |
$2->ast_right = $3;
|
|
Packit Service |
360c39 |
$3->ast_right = $4;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
get_stmt: TOK_GET blockspec {
|
|
Packit Service |
360c39 |
$1->ast_right = $2; $$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
| TOK_GET blockspec TOK_STATE {
|
|
Packit Service |
360c39 |
$1->ast_right = $2;
|
|
Packit Service |
360c39 |
$2->ast_right = $3;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
blockspec: offset { $$ = $1; }
|
|
Packit Service |
360c39 |
| address { $$ = $1; }
|
|
Packit Service |
360c39 |
| path { $$ = $1; }
|
|
Packit Service |
360c39 |
| block_literal { $$ = $1; }
|
|
Packit Service |
360c39 |
| subscript { $$ = $1; }
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
offset: blockspec TOK_OFFSET {
|
|
Packit Service |
360c39 |
$2->ast_left = $1;
|
|
Packit Service |
360c39 |
$$ = $2;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
typespec: identifier {
|
|
Packit Service |
360c39 |
$1->ast_type = AST_EX_TYPESPEC;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
block_literal: identifier { $$ = $1; }
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
subscript: block_literal TOK_LBRACKET index TOK_RBRACKET {
|
|
Packit Service |
360c39 |
$4->ast_left = $1;
|
|
Packit Service |
360c39 |
$1->ast_left = $3;
|
|
Packit Service |
360c39 |
$$ = $4;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
index: number { $$ = $1; }
|
|
Packit Service |
360c39 |
| identifier { $$ = $1; }
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
address: number {
|
|
Packit Service |
360c39 |
$1->ast_type = AST_EX_ADDRESS;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
structspec: TOK_LBRACE fieldspecs TOK_RBRACE { $$ = $2; }
|
|
Packit Service |
360c39 |
| TOK_LBRACE TOK_RBRACE { $$ = NULL; }
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
fieldspecs: fieldspecs TOK_COMMA fieldspec {
|
|
Packit Service |
360c39 |
$1->ast_left = $3;
|
|
Packit Service |
360c39 |
$$ = $1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
| fieldspec { $$ = $1; }
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
fieldspec: identifier TOK_COLON fieldvalue {
|
|
Packit Service |
360c39 |
$2->ast_right = $1;
|
|
Packit Service |
360c39 |
$1->ast_right = $3;
|
|
Packit Service |
360c39 |
$$ = $2;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
fieldvalue: number { $$ = $1; }
|
|
Packit Service |
360c39 |
| string { $$ = $1; }
|
|
Packit Service |
360c39 |
;
|
|
Packit Service |
360c39 |
number: TOK_NUMBER { $$ = $1; }
|
|
Packit Service |
360c39 |
string: TOK_STRING { $$ = $1; }
|
|
Packit Service |
360c39 |
identifier: TOK_ID { $$ = $1; }
|
|
Packit Service |
360c39 |
path: TOK_PATH { $$ = $1; }
|
|
Packit Service |
360c39 |
%%
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
/**
|
|
Packit Service |
360c39 |
* Allocate and initialize a new parse state structure. The caller must free the
|
|
Packit Service |
360c39 |
* memory returned by this function.
|
|
Packit Service |
360c39 |
*/
|
|
Packit Service |
360c39 |
struct lgfs2_lang_state *lgfs2_lang_init(void)
|
|
Packit Service |
360c39 |
{
|
|
Packit Service |
360c39 |
struct lgfs2_lang_state *state;
|
|
Packit Service |
360c39 |
state = calloc(1, sizeof(struct lgfs2_lang_state));
|
|
Packit Service |
360c39 |
if (state == NULL) {
|
|
Packit Service |
360c39 |
return NULL;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
state->ls_linenum = 1;
|
|
Packit Service |
360c39 |
return state;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
void lgfs2_lang_free(struct lgfs2_lang_state **state)
|
|
Packit Service |
360c39 |
{
|
|
Packit Service |
360c39 |
ast_destroy(&(*state)->ls_ast_root);
|
|
Packit Service |
360c39 |
free(*state);
|
|
Packit Service |
360c39 |
*state = NULL;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
int lgfs2_lang_parsef(struct lgfs2_lang_state *state, FILE *src)
|
|
Packit Service |
360c39 |
{
|
|
Packit Service |
360c39 |
int ret = 0;
|
|
Packit Service |
360c39 |
yyscan_t lexer;
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
ret = yylex_init_extra(state, &lexer);
|
|
Packit Service |
360c39 |
if (ret != 0) {
|
|
Packit Service |
360c39 |
fprintf(stderr, "Failed to initialize lexer.\n");
|
|
Packit Service |
360c39 |
return ret;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
yyset_in(src, lexer);
|
|
Packit Service |
360c39 |
ret = yyparse(state, lexer);
|
|
Packit Service |
360c39 |
yylex_destroy(lexer);
|
|
Packit Service |
360c39 |
return ret;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
int lgfs2_lang_parses(struct lgfs2_lang_state *state, const char *cstr)
|
|
Packit Service |
360c39 |
{
|
|
Packit Service |
360c39 |
int ret;
|
|
Packit Service |
360c39 |
FILE *src;
|
|
Packit Service |
360c39 |
char *str = strdup(cstr);
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
if (str == NULL) {
|
|
Packit Service |
360c39 |
perror("Failed to duplicate source string");
|
|
Packit Service |
360c39 |
return 1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
src = fmemopen(str, strlen(str), "r");
|
|
Packit Service |
360c39 |
if (src == NULL) {
|
|
Packit Service |
360c39 |
perror("Failed to open string as source file");
|
|
Packit Service |
360c39 |
free(str);
|
|
Packit Service |
360c39 |
return 1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
ret = lgfs2_lang_parsef(state, src);
|
|
Packit Service |
360c39 |
fclose(src);
|
|
Packit Service |
360c39 |
free(str);
|
|
Packit Service |
360c39 |
if (ret != 0 || state->ls_errnum != 0) {
|
|
Packit Service |
360c39 |
return 1;
|
|
Packit Service |
360c39 |
}
|
|
Packit Service |
360c39 |
return 0;
|
|
Packit Service |
360c39 |
}
|