Skip to content

Instantly share code, notes, and snippets.

@lanoxx
Last active May 3, 2019 18:23
Show Gist options
  • Select an option

  • Save lanoxx/fa7f9bf8c47a97661aa6f4e189d2276d to your computer and use it in GitHub Desktop.

Select an option

Save lanoxx/fa7f9bf8c47a97661aa6f4e189d2276d to your computer and use it in GitHub Desktop.
/* Mini Calculator */
/* calc.lex */
%{
#include "heading.h"
#include "tok.h"
int yyerror(char *s);
#undef YY_INPUT
#define YY_INPUT(buffer,result,maxsize) \
{ \
int remaining = strlen(global_lexer_input); \
int length = remaining > maxsize ? maxsize : remaining; \
strncpy (buffer, global_lexer_input, length); \
global_lexer_input += length; \
printf("Lex Input Length: %d\n", length); \
result = length; \
return 0; \
}
%}
negation NOT|not
and and
exists_next EX
exists_globally EG
exists E
until U
atom [a-z]
opening_parenthesis \(
closing_parenthesis \)
%%
{exists_next} { char*token = malloc(strlen(yytext)+1); strcpy(token,yytext); yylval.atom_name = token; printf("EXISTS_NEXT\n"); return EXISTS_NEXT; }
{exists_globally} { char*token = malloc(strlen(yytext)+1); strcpy(token,yytext); yylval.atom_name = token; printf("EXISTS_GLOBALLY\n"); return EXISTS_GLOBALLY; }
{exists} { char*token = malloc(strlen(yytext)+1); strcpy(token,yytext); yylval.atom_name = token; printf("EXISTS\n"); return EXISTS; }
{until} { char*token = malloc(strlen(yytext)+1); strcpy(token,yytext); yylval.atom_name = token; printf("UNTIL\n"); return UNTIL; }
{negation} { char*token = malloc(strlen(yytext)+1); strcpy(token,yytext); yylval.atom_name = token; printf("NEGATION\n"); return NOT; }
{and} { char*token = malloc(strlen(yytext)+1); strcpy(token,yytext); yylval.atom_name = token; printf("AND\n"); return AND; }
{atom} { char*token = malloc(strlen(yytext)+1); strcpy(token,yytext); yylval.atom_name = token; printf("ATOM\n"); return ATOMIC_PROPOSITION; }
{opening_parenthesis} { printf("OPEN\n"); return '('; }
{closing_parenthesis} { printf("CLOSE\n"); return ')'; }
[ \t]* { printf("WHITESPACE\n"); }
[\n] { yylineno++; }
. { printf("%s", "LEXER "); yyerror("XXX"); exit(1); }
/* Mini Calculator */
/* calc.y */
%{
#include "heading.h"
int yyerror(char *s);
int yylex(void);
%}
%define parse.error verbose
%define parse.lac full
%union{
char* op_val;
char* atom_name;
struct formula *formula;
}
%start input
%token <atom_name> ATOMIC_PROPOSITION
%token <formula> EXISTS_NEXT
%token <formula> EXISTS_GLOBALLY
%token <formula> EXISTS
%token <formula> UNTIL
%token <formula> NOT
%type <formula> stmt
%type <formula> atom
%left <formula> AND
%nonassoc '('
%nonassoc ')'
%%
input: %empty
| stmt { root_formula = $1; YYACCEPT; }
;
stmt: atom {
$$ = $1;
}
| NOT atom {
printf("statement is negated statement\n");
Formula *stmt_formula = malloc(sizeof(Formula));
stmt_formula->type = CTL_TYPE_NEGATION;
stmt_formula->left = $2;
stmt_formula->name = "negation";
$$ = stmt_formula;
}
| EXISTS_NEXT '(' stmt ')' {
printf("statement is EX\n");
Formula *stmt_formula = malloc(sizeof(Formula));
stmt_formula->type = CTL_TYPE_EXIST_NEXT;
stmt_formula->left = $3;
stmt_formula->name = "EX";
$$ = stmt_formula;
}
| EXISTS_GLOBALLY '(' stmt ')' {
printf("statement is EG\n");
Formula *stmt_formula = malloc(sizeof(Formula));
stmt_formula->type = CTL_TYPE_EXISTS_GLOBALLY;
stmt_formula->left = $3;
stmt_formula->name = "EG";
$$ = stmt_formula;
}
| EXISTS stmt UNTIL stmt {
printf("statement is E U\n");
Formula *stmt_formula = malloc(sizeof(Formula));
stmt_formula->type = CTL_TYPE_EXIST_UNTIL;
stmt_formula->left = $2;
stmt_formula->right = $4;
stmt_formula->name = "EU";
$$ = stmt_formula;
}
| stmt AND stmt {
printf("statement is conjunction\n");
Formula *stmt_formula = malloc(sizeof(Formula));
stmt_formula->type = CTL_TYPE_CONJUNCTION;
stmt_formula->left = $1;
stmt_formula->right = $3;
stmt_formula->name = "and";
$$ = stmt_formula;
}
;
atom: ATOMIC_PROPOSITION {
printf("parsed atom\n");
Formula *stmt_formula = malloc(sizeof(Formula));
stmt_formula->type = CTL_TYPE_ATOMIC_PROPOSITION;
stmt_formula->name = $1;
$$ = stmt_formula;
}
%%
int yyerror(char *s)
{
extern int yylineno; // defined and maintained in lex.c
extern char *yytext; // defined and maintained in lex.c
printf ("ERROR: %s at symbol \"%s", s, yytext);
printf ("\" on line %d", yylineno);
exit(1);
}
/* heading.h */
#define _POSIX_C_SOURCE 200809L
#define YY_NO_UNPUT
#include<stdio.h>
#include<stdlib.h>
extern char *global_lexer_input;
extern char *global_current_lexer_input;
enum FormulaType
{
CTL_TYPE_NONE,
CTL_TYPE_BOOLEAN_LITERAL,
CTL_TYPE_ATOMIC_PROPOSITION,
CTL_TYPE_NEGATION,
CTL_TYPE_CONJUNCTION,
CTL_TYPE_EXIST_NEXT,
CTL_TYPE_EXIST_UNTIL,
CTL_TYPE_EXISTS_GLOBALLY,
CTL_TYPE_LAST
};
typedef struct formula {
struct formula *left;
struct formula *right;
enum FormulaType type;
union {
char *name;
long value;
};
} Formula;
Formula *root_formula;
/* main.cc */
#include <stdlib.h>
#include <string.h>
#include "heading.h"
// prototype of bison-generated parser function
int yyparse();
//#define INPUT "EX(EG(E a U b))"
//#define INPUT "EX(EG(a AND b))"
#define INPUT "a and b "
char *global_lexer_input;
void print_formula (Formula *formula);
int main(int argc, char **argv)
{
global_lexer_input = malloc (strlen(INPUT) + 1);
strncpy (global_lexer_input, INPUT, strlen(INPUT)+1);
root_formula = malloc(sizeof(root_formula));
yyparse();
print_formula (root_formula);
return 0;
}
void print_formula (Formula *formula)
{
if (!formula) return;
Formula *current = formula;
switch (current->type)
{
case CTL_TYPE_BOOLEAN_LITERAL:
printf ("Result: %s\n", current->value ? "true" : "false");
break;
case CTL_TYPE_ATOMIC_PROPOSITION:
printf("Result: %s\n", current->name);
break;
default:
printf("Result: %s\n", current->name);
break;
}
print_formula (current->left);
print_formula (current->right);
}
@lanoxx
Copy link
Author

lanoxx commented May 3, 2019

The error was in https://gist.github.com/lanoxx/fa7f9bf8c47a97661aa6f4e189d2276d#file-calc-lex:

Line 18: return 0; that was preventing the EOF token from being emitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment