Blame gfs2/libgfs2/parser.y

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