Subversion Repositories PlanixRsrch.SVN

Compare Revisions

Ignore whitespace Rev 254 → Rev 255

/tags/mgen/0.0.2/test.c
0,0 → 1,184
#include <stdio.h>
#include <string.h>
 
#include <mutests.h>
 
#include "mgen.h"
 
 
 
static char *
gen_test_file(char *str)
{
FILE *f;
char *filename;
filename = tmpnam(NULL);
f=fopen(filename,"wt");
(void)fprintf(f,str);
(void)fclose(f);
return filename;
}
 
 
 
int test_mgen_read_rule_set1(char *bnf, char *prg, char * start, int wrc)
{
char * filename;
MGEN_FILE * mf;
struct mgen_rule_set * rules;
int rc;
 
filename = gen_test_file(bnf);
mf = mgen_open(filename,"");
rules = mgen_read_rule_set(mf);
 
mu_assert(rules!=NULL,"create rules");
remove(filename);
 
filename = gen_test_file(prg);
mf = mgen_open(filename,"");
rc = mgen_parse(mf,rules, start);
mu_assert(rc == wrc, "mgen_parse bnf: %s, prg: %s",bnf,prg);
 
remove (filename);
return 1;
}
 
int test_mgen_read_rule_set()
{
test_mgen_read_rule_set1(
"<Program> ::= a b c",
"abc",
"Program",
1);
test_mgen_read_rule_set1(
"<Program> ::= a b c",
"abx",
"Program",
0);
test_mgen_read_rule_set1(
"<Program> ::= <Word> a b c\n\
<Word> ::= <Letter> <Wordrest>\n\
<Wordrest> ::= <Letter> | \n\
<Letter> ::= x | y | z",
 
"xyabc",
"Program",
1);
 
 
}
 
int test_mgen_ring_seek1(char *str,int bufsize,int blocksize)
{
char * filename;
MGEN_FILE * mf;
int i,c,rc;
 
filename = gen_test_file(str);
 
mf = mgen_open(filename,"");
mu_assert(mf!=NULL, "seek: can't open file %s",filename);
 
mgen_ring_set_block_size(&mf->ring,(size_t)blocksize);
mgen_ring_set_buffer_size(&mf->ring,(size_t)bufsize);
 
for(i=0; i<(int)strlen(str); i++){
c = mgen_getc(mf);
mu_assert( c == str[i], "seek: test 1");
}
 
for(i=0; i<(int)strlen(str); i++){
rc = mgen_ring_seek(&mf->ring,(size_t)i);
if ( (int)strlen(str)-i > bufsize )
mu_assert(!rc,"seek: test 44");
else{
mu_assert(rc,"seek: test 45");
c = mgen_getc(mf);
mu_assert (c == str[i], "seek: test 77");
}
}
 
(void)remove(filename);
return 1;
}
 
int test_mgen_ring_seek()
{
int rc=0;
rc |= test_mgen_ring_seek1("012345678",5,3);
rc |= test_mgen_ring_seek1("0123456789123",100,3);
rc |= test_mgen_ring_seek1("xxaass0123456789123",5,1);
rc |= test_mgen_ring_seek1("12345678",8,2);
rc |= test_mgen_ring_seek1("12345678",8,8);
rc |= test_mgen_ring_seek1("12345678",9,8);
return rc;
}
 
 
 
int test_mgen_getc()
{
MGEN_FILE * mf;
char * str;
char *filename;
int i,rc;
int maxbuf,diff,blocksize;
 
str = "Hello World"; /* 11 characters */
diff = 3;
blocksize = 2;
maxbuf = (int)strlen(str)-diff;
 
filename = gen_test_file(str);
 
mf = mgen_open(filename,"");
mu_assert(mf!=NULL, "can't open file %s",filename);
 
mgen_ring_set_block_size(&mf->ring,(size_t)blocksize);
mgen_ring_set_buffer_size(&mf->ring,(size_t)maxbuf);
 
for (i=0; (size_t)i<strlen(str); i++){
int c;
c = mgen_getc(mf);
mu_assert(c == str[i],"test 1");
mu_assert((size_t)i+1 == mf->ring.abspos,"test 2");
}
 
/* mu_assert(mf->ring.pos == (size_t)maxbuf % (size_t)diff-1, "test 3");*/
 
/* unget characters into the whole buffer */
for (i=0; i<maxbuf; i++){
rc = mgen_ungetc('0'+i,mf);
mu_assert(rc == '0'+i,"test 4");
}
/* unget one more character should result in EOF */
rc = mgen_ungetc('x',mf);
mu_assert( rc == EOF, "test 5");
for (i=0; i<maxbuf; i++){
rc = mgen_getc(mf);
mu_assert(rc == '0'+maxbuf-1-i, "test 6");
}
 
rc = mgen_getc(mf);
mu_assert(rc == EOF,"test 7");
 
(void)fclose(mf->infile);
(void)remove(filename);
 
return 1;
}
 
int main()
{
mutests tf = {
test_mgen_getc,
test_mgen_ring_seek,
test_mgen_read_rule_set,
NULL
};
return mutests_run(tf);
}
 
/tags/mgen/0.0.2/LICENSE
0,0 → 1,26
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/tags/mgen/0.0.2/Makefile
0,0 → 1,40
 
 
OBJS= mgen_getc.o \
mgen_run.o \
mgen_open.o \
mgen_ungetc.o \
mgen_skip_spaces.o \
mgen_perror.o \
mgen_read_rule_set.o \
mgen_create_rule_set.o \
mgen_print_symlist.o \
mgen_print_rhs_list.o \
mgen_parse.o \
mgen_ring.o
 
PRGOBJS=\
bnf.o
 
TSTOBJS=\
test.o
 
PRG=bnf
TSTPRG=test
 
.c.o:
$(CC) -c $(CFLAGS) $<
 
$(PRG): $(OBJS) $(PRGOBJS)
$(CC) $(LDFLAGS) -o $(PRG) $(PRGOBJS) $(OBJS) -lmavl
 
$(TSTPRG): $(OBJS) $(TSTOBJS)
$(CC) $(LDFLAGS) -o $(TSTPRG) $(TSTOBJS) $(OBJS) -lmavl -lmutests
 
 
 
 
clean:
rm -f *.o
rm -f $(PRG)
rm -f *.core
/tags/mgen/0.0.2/README
0,0 → 1,0
A simple *true* BNF-Parser in pure ANSI C 89
/tags/mgen/0.0.2/algol60.bnf
0,0 → 1,5
<program> ::= <block> | <compound statement>
<block> ::= <unlabelled block> | <label>: <block>
<unlabelled block> ::= <block head> ; <compound tail>
<block head> ::= begin <declaration> | <block head> ; <declaration>
<compound statement> ::= <unlabelled compound> | <label>: <compound statement>
/tags/mgen/0.0.2/algol60.raw
0,0 → 1,7
:
<program> ::= <block> | <compound statement><block> ::= <unlabelled block> | <label>: <block>
<unlabelled block> ::= <block head> ;
<compound tail><block head> ::= begin <declaration> | <block head> ; <declaration>
<compound statement> ::= <unlabelled compound> | <label>: <compound statement><unlabelled compound> ::= begin <compound tail><compound tail> ::= <statement> end | <statement> ; <compound tail><declaration> ::= <type declaration> | <array declaration> | <switch declaration> | <procedure declaration><type declaration> ::= <local or own type> <type list><local or own type> ::= <type> | own <type><type> ::= real | integer | boolean<type list> ::= <simple variable> | <simple variable> , <type list><array declaration> ::= array <array list> | <local or own type> array <array list><array list> ::= <array segment> | <array list> , <array segment><array segment> ::= <array identifier> [ <bound pair list> ] | <array identifier> , <array segment><array identifier> ::= <identifier><bound pair list> ::= <bound pair> | <bound pair list> , <bound pair><bound pair> ::= <lower bound> : <upper bound><upper bound> ::= <arithmetic expression><lower bound> ::= <arithmetic expression><switch declaration> ::= switch <switch identifier> := <switch list><switch identifier> ::= <identifier><switch list> ::= <designational expression> | <switch list> , <designational expression><procedure declaration> ::= procedure <procedure heading> <procedure body> | <type> procedure <procedure heading> <procedure body><procedure heading> ::= <procedure identifier> <formal parameter part> ; <value part> <specification part><procedure identifier> ::= <identifier><formal parameter part> ::= <empty> | ( <formal parameter list> )<formal parameter list> ::= <formal parameter> | <formal parameter list> <parameter delimiter> <formal parameter><formal parameter> ::= <identifier> <value part> ::= value <identifier list> ; | <empty><specification part> ::= <empty> | <specifier> <identifier list> ; | <specification part> <specifier> <identifier list><specifier> ::= string | <type> | array | <type> array | label | switch | procedure | <type> procedure<identifier list> ::= <identifier> | <identifier list> , <identifier><procedure body> ::= <statement> | <code><statement> ::= <unconditional statement> | <conditional statement> | <for statement><unconditional statement> ::= <basic statement> | <compound statement> | <block><basic statement> ::= <unlabelled basic statement> | <label>: <basic statement><label> ::= <identifier> | <unsigned integer><unlabelled basic statement> ::= <assignment statement> | <go to statement> | <dummy statement> | <procedure statement><assignment statement> ::= <left part list> <arithmetic expression> | <left part list> <Boolean expression><left part list> ::= <left part> | <left part list> <left part><left part> ::= <variable> := | <procedure identifier> :=<go to statement> ::= goto <designational expression><designational expression> ::= <simple designational expression> |<if clause> <simple designational expression> else <designational expression><simple designational expression> ::= <label> | <switch designator> | (<designational expression>)<switch designator> ::= <switch identifier> [<subscript expression>]<dummy statement> ::= <empty><procedure statement> ::= <procedure identifier> <actual parameter part><actual parameter part> ::= <empty> | ( <actual parameter list> )<actual parameter list> ::= <actual parameter> | <actual parameter list> <parameter delimiter> <actual parameter><parameter delimiter> ::= , | ) <letter string> : (<actual parameter> ::= <string> | <expression> | <array identifier> | <switch identifier> | <procedure identifier><conditional statement> ::= <if statement> | <if statement> else <statement> | <if clause> <for statement> | <label>: <conditional statement><if statement> ::= <if clause> <unconditional statement><if clause> ::= if <Boolean expression> then<for statement> ::= <for clause> <statement> | <label>: <for statement><for clause> ::= for <variable> := <for list> do<for list> ::= <for list element> | <for list> , <for list element><for list element> ::= <arithmetic expression> |<arithmetic expression> step <arithmetic expression> until <arithmetic expression> |<arithmetic expression> while <Boolean expression><expression> ::= <arithmetic expression> | <Boolean expression> | <designational expression><arithmetic expression> ::= <simple arithmetic expression> | <if clause> <simple arithmetic expression> else <arithmetic expression><simple arithmetic expression> ::= <term> | <adding operator> <term> | <simple arithmetic expression> <adding operator> <term><adding operator> ::= + | –<term> ::= <factor> | <term> <multiplying operator> <factor><multiplying operator> ::= × | / | ÷<factor> ::= <primary> | <factor> | <factor> ↑ <primary><primary> ::= <unsigned number> | <variable> | <function designator> | ( <arithmetic expression> )<unsigned number> ::= <decimal number> | <exponential part> | <decimal number> <exponential part>
<decimal number> ::= <unsigned integer> | <decimal fraction> | <unsigned integer> <decimal fraction><unsigned integer> ::= <digit> | <unsigned integer> <digit><decimal fraction> ::= . <unsigned integer><exponential part> ::= 10 <integer><integer> ::= <unsigned integer> | + <unsigned integer> | – <unsigned integer><Boolean expression> ::= <simple Boolean> | <if clause> <simple Boolean> else <Boolean expression><simple Boolean> ::= <implication> | <simple Boolean> ≣ <implication><implication> ::= <Boolean term> | <implication> ⊃ <Boolean term><Boolean term> ::= <Boolean factor> | <Boolean term> ⋁ <Boolean factor><Boolean factor> ::= <Boolean secondary> | <Boolean factor> ⋀ <Boolean secondary><Boolean secondary> ::= <Boolean primary> | ¬ <Boolean primary><Boolean primary> ::= <logical value> | <variable> | <function designator> | <relation> | ( <Boolean expression> )<relation> ::= <simple arithmetic expression> <relational operator> <simple arithmetic expression><relational operator> ::= < | ≤ | = | ≠ | > | ≥<function designator> ::= <procedure identifier> <actual parameter part><variable> ::= <simple variable> | <subscripted variable><simple variable> ::= <variable identifier><variable identifier> ::= <identifier><subscripted variable> ::= <array identifier> [ <subscript list> ]<subscript list> ::= <subscript expression> | <subscript list> , <subscript expression><subscript expression> ::= <arithmetic expression><string> ::= "<open string>"<open string> ::= <proper string> "<open string>" | <open string><open string><proper string> ::= <any sequence of symbols not containing " > | <empty><letter string> ::= <letter> | <letter string> <letter><identifier> ::= letter> | <identifier> <letter> | <identifier> <digit><basic symbol> ::= <letter> | <digit> | <logical value> | <delimiter><letter> ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |A |B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <logical value> ::= true | false<delimiter> ::= <operator> | <separator> | <bracket> | <declarator> | <specificator><operator> ::= <arithmetic operator> | <relational operator> | <logical operator> | <sequential operator><arithmetic operator> ::= + | – | × | / | ÷ | ↑<relational operator> ::= < | ≤ | = | ≠ | > | ≥<logical operator> ::= ≣ | ⊃ | ⋁ | ⋀ | ¬<sequential operator> ::= goto | if | then | else | for | do<separator> ::= , | . | 10 | : | ; | := | _ | step | until | while | comment<bracket> ::= ( | ) | [ | ] | ` | ' | begin | end<declarator> ::= own | boolean | integer | real | array | switch | procedure<specificator> ::= string | label | value
 
/tags/mgen/0.0.2/algol60.txt
0,0 → 1,110
 
<program> ::= <block> | <compound statement>
<block> ::= <unlabelled block> | <label>: <block>
<unlabelled block> ::= <block head> ;
<compound tail>
<block head> ::= begin <declaration> | <block head> ; <declaration>
<compound statement> ::= <unlabelled compound> | <label>: <compound statement>
<unlabelled compound> ::= begin <compound tail>
<compound tail> ::= <statement> end | <statement> ;
<compound tail>
<declaration> ::=
<type declaration> | <array declaration> | <switch declaration> | <procedure declaration>
 
<type declaration> ::= <local or own type>
<type list>
<local or own type> ::= <type> | own
<type>
<type> ::= real | integer | boolean
<type list> ::= <simple variable> | <simple variable> , <type list>
<array declaration> ::= array <array list> | <local or own type> array <array list>
<array list> ::= <array segment> | <array list> , <array segment>
<array segment> ::= <array identifier> [ <bound pair list> ] | <array identifier> , <array segment>
<array identifier> ::= <identifier>
<bound pair list> ::= <bound pair> | <bound pair list> , <bound pair>
<bound pair> ::= <lower bound> : <upper bound>
<upper bound> ::= <arithmetic expression>
<lower bound> ::= <arithmetic expression>
<switch declaration> ::= switch <switch identifier> := <switch list>
<switch identifier> ::= <identifier>
<switch list> ::= <designational expression> | <switch list> , <designational expression>
<procedure declaration> ::= procedure <procedure heading> <procedure body> | <type> procedure <procedure heading> <procedure body>
<procedure heading> ::= <procedure identifier> <formal parameter part> ; <value part> <specification part>
<procedure identifier> ::= <identifier>
<formal parameter part> ::= <empty> | ( <formal parameter list> )
<formal parameter list> ::= <formal parameter> | <formal parameter list> <parameter delimiter> <formal parameter>
<formal parameter> ::= <identifier> <value part> ::= value <identifier list> ; | <empty>
<specification part> ::= <empty> | <specifier> <identifier list> ; | <specification part> <specifier> <identifier list>
<specifier> ::= string | <type> | array | <type> array | label | switch | procedure | <type> procedure<identifier list> ::= <identifier> | <identifier list> , <identifier>
<procedure body> ::= <statement> | <code>
<statement> ::= <unconditional statement> | <conditional statement> | <for statement>
<unconditional statement> ::= <basic statement> | <compound statement> | <block>
<basic statement> ::= <unlabelled basic statement> | <label>: <basic statement>
<label> ::= <identifier> | <unsigned integer>
<unlabelled basic statement> ::= <assignment statement> | <go to statement> | <dummy statement> | <procedure statement>
<assignment statement> ::= <left part list> <arithmetic expression> | <left part list> <Boolean expression>
<left part list> ::= <left part> | <left part list> <left part>
<left part> ::= <variable> := | <procedure identifier> :=<go to statement> ::= goto <designational expression>
<designational expression> ::= <simple designational expression> |<if clause> <simple designational expression> else <designational expression>
<simple designational expression> ::= <label> | <switch designator> | (<designational expression>)
<switch designator> ::= <switch identifier> [<subscript expression>]
<dummy statement> ::= <empty>
<procedure statement> ::= <procedure identifier> <actual parameter part>
<actual parameter part> ::= <empty> | ( <actual parameter list> )
<actual parameter list> ::= <actual parameter> | <actual parameter list> <parameter delimiter> <actual parameter>
 
<parameter delimiter> ::= , | ) <letter string> : (
<actual parameter> ::= <string> | <expression> | <array identifier> | <switch identifier> | <procedure identifier>
 
<conditional statement> ::= <if statement> | <if statement> else <statement> |
<if clause> <for statement> | <label>: <conditional statement>
 
<if statement> ::= <if clause> <unconditional statement>
<if clause> ::= if <Boolean expression> then<for statement> ::= <for clause> <statement> | <label>: <for statement>
<for clause> ::= for <variable> := <for list> do<for list> ::= <for list element> | <for list> , <for list element>
<for list element> ::= <arithmetic expression> |<arithmetic expression> step <arithmetic expression> until <arithmetic expression> |<arithmetic expression> while <Boolean expression>
<expression> ::= <arithmetic expression> | <Boolean expression> | <designational expression>
<arithmetic expression> ::= <simple arithmetic expression> | <if clause> <simple arithmetic expression> else <arithmetic expression>
<simple arithmetic expression> ::= <term> | <adding operator> <term> | <simple arithmetic expression> <adding operator> <term>
<adding operator> ::= + | –<term> ::= <factor> | <term> <multiplying operator> <factor>
<multiplying operator> ::= × | / | ÷<factor> ::= <primary> | <factor> | <factor> ↑ <primary>
<primary> ::= <unsigned number> | <variable> | <function designator> | ( <arithmetic expression> )<unsigned number> ::= <decimal number> | <exponential part> | <decimal number> <exponential part>
<decimal number> ::= <unsigned integer> | <decimal fraction> | <unsigned integer> <decimal fraction>
<unsigned integer> ::= <digit> | <unsigned integer> <digit>
<decimal fraction> ::= . <unsigned integer>
<exponential part> ::= 10 <integer>
<integer> ::= <unsigned integer> | + <unsigned integer> | – <unsigned integer>
<Boolean expression> ::= <simple Boolean> | <if clause> <simple Boolean> else <Boolean expression>
<simple Boolean> ::= <implication> | <simple Boolean> ≣ <implication>
<implication> ::= <Boolean term> | <implication> ⊃ <Boolean term>
<Boolean term> ::= <Boolean factor> | <Boolean term> ⋁ <Boolean factor>
<Boolean factor> ::= <Boolean secondary> | <Boolean factor> ⋀ <Boolean secondary>
<Boolean secondary> ::= <Boolean primary> | ¬ <Boolean primary>
<Boolean primary> ::= <logical value> | <variable> | <function designator> | <relation> | ( <Boolean expression> )<relation> ::= <simple arithmetic expression> <relational operator> <simple arithmetic expression>
<relational operator> ::= < | ≤ | = | ≠ | > | ≥<function designator> ::= <procedure identifier> <actual parameter part>
<variable> ::= <simple variable> | <subscripted variable>
<simple variable> ::= <variable identifier>
<variable identifier> ::= <identifier>
<subscripted variable> ::= <array identifier> [ <subscript list> ]<subscript list> ::= <subscript expression> | <subscript list> , <subscript expression>
<subscript expression> ::= <arithmetic expression>
<string> ::= "<open string>"
<open string> ::= <proper string> "<open string>" | <open string>
<open string>
<proper string> ::= <any sequence of symbols not containing " > | <empty>
<letter string> ::= <letter> | <letter string> <letter>
<identifier> ::= letter> | <identifier> <letter> | <identifier> <digit>
<basic symbol> ::= <letter> | <digit> | <logical value> | <delimiter>
<letter> ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |A |B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<logical value> ::= true | false
<delimiter> ::= <operator> | <separator> | <bracket> | <declarator> | <specificator>
<operator> ::= <arithmetic operator> | <relational operator> | <logical operator> | <sequential operator>
<arithmetic operator> ::= + | – | × | / | ÷ | ↑
<relational operator> ::= < | ≤ | = | ≠ | > | ≥
<logical operator> ::= ≣ | ⊃ | ⋁ | ⋀ | ¬
<sequential operator> ::= goto | if | then | else | for | do
<separator> ::= , | . | 10 | : | ; | := | _ | step | until | while | comment
<bracket> ::= ( | ) | [ | ] | ` | ' | begin | end
<declarator> ::= own | boolean | integer | real | array | switch | procedure
<specificator> ::= string | label | value
 
/tags/mgen/0.0.2/bnf.c
0,0 → 1,844
/*
* Copyright 2019, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
 
#include <libmavl/mavl.h>
 
#define MAX_NONTERMINAL 1024
#define MAX_TERMINAL 1024
 
#include "mgen.h"
 
const char * prgname;
 
/*#define printf (void)printf*/
 
struct prs {
FILE * infile;
int line;
int col;
int prev_col;
char * filename;
struct mavl *rules;
struct mgen_rule * current_rule;
struct rhs_elem * current_rhs_elem;
struct mgen_sym ** current_sym;
};
 
 
 
struct mgen_parser {
struct mavl * rules;
struct mgen_stream * mf;
struct mgen_sym * stack[1000];
int stackptr;
};
 
 
void prgerr(char *text)
{
(void)fprintf(stderr, "%s: error: %s: %s\n",
prgname,text,strerror(errno));
}
 
int get_char(struct prs * prs)
{
int c;
c=fgetc(prs->infile);
switch(c) {
case '\n':
prs->line++;
prs->prev_col = prs->col;
prs->col=0;
break;
case '\t':
prs->col+=8;
break;
default:
prs->col++;
}
return c;
}
 
 
void
unget_char(int c, struct prs * prs){
(void)ungetc(c,prs->infile);
switch(c) {
case '\n':
prs->line--;
prs->col=prs->prev_col;
break;
case '\t':
prs->col-=8;
break;
default:
prs->col--;
}
}
 
struct mgen_sym * append_sym(struct mgen_sym ** next, int type, char *name)
{
struct mgen_sym * sym;
sym = malloc( sizeof( struct mgen_sym));
if (!sym){
prgerr("can't allocate memory");
return NULL;
}
sym->name = malloc( strlen(name)+1);
if (!sym->name){
prgerr("can't allocate memory");
return NULL;
}
(void)strcpy (sym->name,name);
sym->type=type;
sym->next=NULL;
 
*next = sym;
return sym;
}
 
struct rhs_elem *
append_rhs_elem(struct rhs_elem ** next)
{
while (*next!=NULL){
next = &((*next)->next);
}
*next = malloc(sizeof(struct rhs_elem));
if (!*next){
prgerr("can't allocate memory");
return NULL;
}
(*next)->sym_list=NULL;
(*next)->next=NULL;
return *next;
}
 
int
skip_spaces(struct prs * prs )
{
int c;
while (1) {
c=get_char(prs);
if ( mgen_isspace(c) ) {
continue;
}
break;
};
return c;
}
 
void
err(struct prs * prs, char *str)
{
if (prs->filename)
(void) fprintf(stderr, "\"%s\", line %d, col %d: error: %s\n",
prs->filename,
prs->line,
prs->col,
str
);
else
(void) fprintf(stderr,
"line %d, col %d: error: %s\n ",
prs->line,
prs->col,
str);
}
 
int
get_non_terminal(struct prs * prs, char * result)
{
int c;
int i;
 
c=EOF; /* this eliminates a compiler warning
about c may be used unassigned */
 
for (i=0; i<MAX_NONTERMINAL; i++){
c = get_char(prs);
if (c=='>')
break;
if (c=='\n' || c==EOF){
err (prs,"missing '>' at end of non-terminal");
return EOF;
}
result[i]=(char)c;
}
 
if (i==MAX_NONTERMINAL && c!='>'){
err(prs,"non-terminal symbol too long");
return EOF;
}
result[i]=0;
return c;
}
 
int
get_terminal(struct prs * prs, char * result)
{
int c;
int i;
 
c=EOF; /* this eliminates a compiler warning
about c may be used unassigned */
 
for (i=0; i<MAX_TERMINAL; i++){
c = get_char(prs);
if (c==' ' || c=='\n' || c=='|' || c=='\t' || c=='\r' || c==EOF)
break;
result[i]=(char)c;
}
 
if (i==MAX_TERMINAL ){
err(prs,"terminal symbol too long");
return EOF;
}
result[i]=0;
 
return c;
}
 
int
skip_comment(struct prs * prs)
{
int c;
do {
c=get_char(prs);
}while (c!='\n' && c!=EOF);
return c;
}
 
int get_left_hand_side(struct prs * prs)
{
int c;
char result[MAX_NONTERMINAL+1];
struct mgen_rule rule;
int exists;
 
while(1) {
c = skip_spaces(prs);
if (c==EOF)
return EOF;
if (c=='#' && prs->col==1){
c=skip_comment(prs);
unget_char(c,prs);
continue;
}
break;
}
 
 
if (c != '<' ){
err(prs,"'<' expected.");
return EOF;
}
if (prs->col != 1){
err(prs,"left hand side of a rule has to start at column 1.");
return EOF;
}
 
c =get_non_terminal(prs, result);
if (c==EOF)
return EOF;
 
rule.name = malloc(strlen(result)+1);
if (!rule.name){
prgerr("can't allocate memory");
return EOF;
}
(void)strcpy(rule.name,result);
rule.rhs_list=0;
rule.line = prs->line;
rule.rhs_list = NULL;
 
/* (void)printf("non-terminal found: %s\n",rule.name);*/
 
prs->current_rule =
mavl_insert(prs->rules, &rule, &exists);
 
if (!prs->current_rule){
prgerr("can't allocate memory\n");
return EOF;
}
 
if (exists){
char msg[MAX_NONTERMINAL+256];
(void)sprintf(msg,"symbol <%s> already defined.",result);
err(prs,msg);
return EOF;
}
 
prs->current_rhs_elem =append_rhs_elem(&(prs->current_rule->rhs_list));
if (!prs->current_rhs_elem)
return EOF;
prs->current_sym = &prs->current_rhs_elem->sym_list;
return 0;
}
 
int get_right_hand_side(struct prs *prs)
{
int c;
struct mgen_sym * sym;
/* int nsyms;
* nsyms = 0;*/
 
do{
c = skip_spaces(prs);
switch (c) {
case '<': {
char result[MAX_NONTERMINAL+1];
if (prs->col <= 1){
unget_char(c,prs);
return c;
}
c = get_non_terminal(prs,result);
if (c==EOF)
return EOF;
sym=append_sym(prs->current_sym,MGEN_NT_SYM,result);
if (!sym)
return EOF;
prs->current_sym = &sym->next;
break;
}
case '|':
prs->current_rhs_elem =append_rhs_elem(&(prs->current_rule->rhs_list));
if (!prs->current_rhs_elem)
return EOF;
prs->current_sym = &prs->current_rhs_elem->sym_list;
break;
 
default:{
char result[MAX_TERMINAL+1];
unget_char(c,prs);
c=get_terminal(prs,result);
/*printf("append terminal '%s' to <%s>\n", result,(*prs->current_sym));*/
sym=append_sym(prs->current_sym,MGEN_T_SYM,result);
if (!sym)
return EOF;
unget_char(c,prs);
prs->current_sym = &sym->next;
}
}
 
}while (c!=EOF);
 
return EOF;
}
 
/*
int mgen_skip(struct mgen_stream *mf, char *chrlist)
{
int c;
c=mgen_getc(mf);
}
*/
 
int get_assignment (struct prs * prs)
{
int c,i,n;
char * search = "::=";
 
c = skip_spaces(prs);
 
i=0; n=(int)strlen(search);
do {
if (c!=search[i]){
err(prs,"'::=' expected.");
return EOF;
}
i++;
c=getc(prs->infile);
}while(i<n);
return c;
}
 
/*
static int
cmp_nonterminal(const void *v1, const void *v2)
{
const char *s1,*s2;
s1 = ((struct mgen_rule *)v1)->name;
s2 = ((struct mgen_rule *)v2)->name;
 
return strcmp(s1,s2);
}
*/
 
void
print(struct mavl *t)
{
struct mavliter it;
void *data;
 
mavliter_init(&it, t);
(void)mavliter_seek_set(&it);
 
while ((data = mavliter_get(&it)) != NULL) {
struct mgen_rule * rule = (struct mgen_rule *)data;
struct rhs_elem *e;
struct mgen_sym *sym;
char * delim_or, *delim_spc;
 
delim_or="";
 
(void)printf("<%s> ::= ",rule->name);
e = rule->rhs_list;
while (e!=NULL){
sym = e->sym_list;
(void)printf("%s",delim_or);
delim_or="|";
delim_spc="";
while (sym!=NULL){
if (sym->type == MGEN_NT_SYM)
(void)printf("%s<%s>",delim_spc,sym->name);
else
(void)printf("%s%s",delim_spc,sym->name);
sym = sym->next;
delim_spc=" ";
}
e=e->next;
}
(void)printf("\n");
 
 
(void)mavliter_next(&it);
}
}
 
 
void
verify(struct prs * prs)
{
struct mavl *t;
struct mavliter it;
void *data;
 
t = prs->rules;
 
mavliter_init(&it, t);
(void)mavliter_seek_set(&it);
 
while ((data = mavliter_get(&it)) != NULL) {
struct mgen_rule * rule = (struct mgen_rule *)data;
struct rhs_elem *e;
struct mgen_sym *sym;
 
e = rule->rhs_list;
while (e!=NULL){
sym = e->sym_list;
while (sym!=NULL){
if (sym->type == MGEN_NT_SYM){
void * r;
struct mgen_rule trule;
trule.name = sym->name;
r = mavl_get(t,&trule);
if (!r){
char msg[MAX_NONTERMINAL+256];
(void)sprintf(msg,"unedfined non-terminal: <%s>",sym->name);
prs->line = rule->line;
prs->col = 0;
err(prs,msg);
return;
}
/* (void)printf("%s<%s>",delim_spc,sym->name);*/
}
sym = sym->next;
}
e=e->next;
}
(void)mavliter_next(&it);
}
}
 
int check_string(struct mgen_stream *mf, char *str)
{
int i,c;
i=0;
(void)printf("CHECK TERMINAL: '%s' - ",str);
 
while (str[i] != 0){
c=mgen_getc(mf);
(void)printf("CMP (%c,%c)",c,str[i]);
if (c==str[i]){
(void)printf(" ok "),
i++;
continue;
}
mgen_ungetc(c,mf);
while(i>0){
i--;
mgen_ungetc(str[i],mf);
}
(void)printf ("FALSE\n");
return 0;
}
(void)printf ("OK\n");
return 1;
}
 
 
void unget_string(struct mgen_stream *mf, char *str)
{
size_t i;
/* (void)printf("UNGET %s\n",str);*/
i=strlen(str);
while(i>0){
i--;
mgen_ungetc(str[i],mf);
}
}
 
 
 
int run_rule1(struct mavl * rules, char * rulename, struct mgen_stream *mf);
 
/*
int check_symlist(struct mavl * rules, struct mgen_sym *sym, struct mgen_stream *mf)
{
while (sym!=NULL){
switch( sym->type ){
case MGEN_NT_SYM:
if (!run_rule1(rules,sym->name,mf))
return 0;
break;
case MGEN_T_SYM:
if (!check_string(mf,sym->name))
return 0;
 
break;
}
sym = sym-> next;
}
return 1;
}
*/
 
 
int run_rule(struct mgen_parser *prs, char *rulename);
 
struct mgen_sym *
popsym(struct mgen_parser * prs){
struct mgen_sym * sym;
 
prs->stackptr--;
sym = prs->stack[prs->stackptr];
(void)printf("POPSYM: [%d:](%p)\n",prs->stackptr,sym);
print_symlist(sym);
(void)printf(" - %d \n",prs->stackptr);
return sym;
}
 
 
void
pushsym(struct mgen_parser * prs, struct mgen_sym * sym){
 
prs->stack[prs->stackptr]=sym;
prs->stackptr++;
(void)printf("PUSHSYM: ([%d:]%p)\n",prs->stackptr,sym);
print_symlist(sym);
(void)printf(" - %d \n",prs->stackptr);
 
}
 
 
int
run_sym(struct mgen_parser *prs, struct mgen_sym *sym)
{
int rc;
int fpos;
fpos = mgen_tell(prs->mf);
(void)printf("FPOS: %d\n",fpos);
 
(void)printf("ENTER run_sym: prs=%p",prs);
print_symlist(sym);
(void)printf("\n");
 
if (sym == NULL){
 
struct mgen_sym *psym;
if (prs->stackptr==0){
(void)printf("EXIT run_sym (0): TRUE");
print_symlist(sym);
(void)printf("\n");
return 1;
}
 
 
psym = popsym(prs);
rc = run_sym(prs,psym);
if (!rc){
pushsym(prs,psym);
mgen_seek(prs->mf,fpos);
(void)printf("SSEK is now: %d\n",mgen_tell(prs->mf));
}
 
(void)printf("EXIT run_sym (0): X %d",rc);
print_symlist(sym);
(void)printf("\n");
return rc;
}
 
switch( sym->type ){
case MGEN_T_SYM:
if (!check_string(prs->mf,sym->name)) {
(void)printf("EXIT run_sym(1): FALSE: ");
print_symlist(sym);
(void)printf("\n");
mgen_seek(prs->mf,fpos);
return 0;
}
rc = run_sym(prs,sym->next);
if (!rc){
mgen_seek(prs->mf,fpos);
}
return rc;
 
case MGEN_NT_SYM:
/*print_symlist(sym->next);*/
(void)printf("CALL run_rule: <%s>\n",sym->name);
pushsym(prs,sym->next);
rc = run_rule(prs,sym->name);
if (!rc){
(void)popsym(prs);
print_symlist(prs->stack[prs->stackptr]);
(void)printf("\n");
(void)printf("EXIT run_sym(2): FALSE: ");
print_symlist(sym);
(void)printf("\n");
mgen_seek(prs->mf,fpos);
return 0;
}
(void)printf("EXIT run_sym (1): TRUE");
print_symlist(sym);
(void)printf("\n");
return 1;
}
 
(void)printf("EXIT run_sym (2): FALSE: ");
print_symlist(sym);
(void)printf("\n");
mgen_seek(prs->mf,fpos);
return 0;
 
}
 
 
int
run_rhs_list(struct mgen_parser *prs, struct rhs_elem * e)
{
/* int i,c;*/
while (e!=NULL){
(void)printf("RUN RHS ELEM: ");
print_rhs_list(e);
(void)printf("\n");
 
if ( run_sym(prs,e->sym_list) ){
(void)printf("EXIT RHS ELEM: TRUE: ");
print_rhs_list(e);
(void)printf("\n");
return 1;
}
(void)printf("THE FPOS IS NOW: %d\n",mgen_tell(prs->mf));
 
(void)printf("NEXT RHS ELEM FOR:");
print_rhs_list(e);
(void)printf("\n");
 
e=e->next;
}
 
(void)printf("EXIT RHS ELEM: FALSE: ");
print_rhs_list(e);
(void)printf("\n");
 
return 0;
}
 
static int
run_rule(struct mgen_parser *prs, char *rulename)
{
 
struct mgen_rule *rule,rs;
/* struct rhs_elem *e;*/
 
rs.name = rulename;
rule = mavl_get(prs->rules,&rs);
if ( !rule ){
(void)printf("Fatal error rule not found %s\n",rulename);
return 0;
}
 
/* pushsym(prs,rule->rhs_list->next);*/
return run_rhs_list(prs,rule->rhs_list);
 
}
 
void
start(struct mavl * rules, struct mgen_stream * mf, char * start_sym)
{
int rc;
struct mgen_parser prs;
 
struct mgen_rule *rule,rs;
 
 
rs.name = start_sym;
printf("Start is here %p\n",rules);
rule = mavl_get(rules,&rs);
if ( !rule ){
(void)printf("error\n");
return;
}
 
 
prs.mf = mf;
prs.rules = rules;
prs.stackptr=0;
 
rc= run_rule(&prs,start_sym);
 
if (rc)
(void) printf("RC: true\n");
else
(void) printf("RC: false\n");
}
 
void run(struct mavl *rules, const char * filename)
{
struct mgen_stream *mf;
(void)printf("Mistart\n");
 
mf = mgen_open(filename, prgname);
if (mf !=0 ){
}
 
start(rules,mf,"Programm");
 
}
 
 
 
int
main(int argc, char *argv[])
{
int c;
struct prs prs;
struct mgen_stream *mf;
struct mgen_rule_set * rules;
 
if (argc>0)
prgname = argv[0];
else
prgname ="";
 
if (argc==1){
prs.infile = stdin;
prs.filename = NULL;
}
else{
prs.infile = fopen(argv[1],"rt");
prs.filename=argv[1];
if (!prs.infile){
(void)fprintf(stderr,
"%s: error: can't open '%s': %s\n",
prgname,prs.filename,strerror(errno)
);
return errno;
}
 
}
 
mf = mgen_open_stream(prs.infile,prgname);
if (!mf){
(void)fprintf(stderr,"Error: %s",strerror(errno));
return errno;
}
 
rules = mgen_read_rule_set(mf);
/*
prs.line=1;
prs.col=0;
prs.rules = mavl_create(cmp_nonterminal,
NULL, sizeof (struct mgen_rule) );
if (!prs.rules){
prgerr("can't allocate memory");
return errno;
}
do {
c = get_left_hand_side(&prs);
if (c==EOF)
break;
c = get_assignment(&prs);
if (c==EOF)
break;
c = get_right_hand_side(&prs);
 
}while(c!=EOF);
verify(&prs);
*/
 
 
 
 
if (argc==3){
mf = mgen_open(argv[2],prgname);
if (!mf){
perror("");
return 1;
}
/* mgen_set_block_size(mf,1112);
mgen_set_buf_size(mf,1118);
*/
 
(void)printf("call parse\n");
(void)printf("================================================\n");
mgen_parse(mf,rules,"Programm");
 
/*run(rules,argv[2]);*/
}
(void)printf("------------------------------\n");
print(rules);
 
return 0;
}
/tags/mgen/0.0.2/example.bnf
0,0 → 1,6
 
<Ziffer ausser Null> ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<Ziffer> ::= 0 | <Ziffer ausser Null>
<Zweistellige Zahl> ::= <Ziffer ausser Null> <Ziffer>
<Zehn bis Neunzehn> ::= 1 <Ziffer>
<Zweiundvierzig> ::= 42
/tags/mgen/0.0.2/mgen.h
0,0 → 1,162
/*
* Copyright 2019, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#ifndef _MGEN_H
#define _MGEN_H
 
 
#include <ctype.h>
#include <stdio.h>
#include <libmavl/mavl.h>
 
#ifndef MGEN_BUF_BLOCK_SIZE
#define MGEN_BUF_BLOCK_SIZE 1024
#endif
 
#ifndef MGEN_BUF_SIZE
#define MGEN_BUF_SIZE (8192)
#endif
 
/* representation of a dynamically
* growing (ring) buffer */
struct mgen_ring{
void *buf;
size_t pos;
size_t maxpos;
size_t abspos;
size_t absmaxpos;
 
size_t block_size;
size_t bufmax_size;
size_t buf_size;
size_t elem_size;
};
typedef struct mgen_ring MGEN_RING;
void mgen_ring_init(struct mgen_ring *m);
size_t mgen_ring_next(struct mgen_ring *m);
int mgen_ring_prev(struct mgen_ring *m);
int mgen_ring_add(struct mgen_ring *m);
int mgen_ring_alloc(MGEN_RING *ring);
int mgen_ring_seek(MGEN_RING * ring, size_t pos);
 
 
#define mgen_ring_set_block_size(r,s) ((r)->block_size=s)
#define mgen_ring_set_buffer_size(r,s) ((r)->bufmax_size=s)
 
 
 
struct mgen_stream {
FILE *infile; /* file pointer of current open file */
int line; /* line number */
int col; /* current column */
 
MGEN_RING ring;
char *buf;
int buflast;
int buffirst;
int bufptr;
int bufmax;
 
 
 
 
int prev_col;
 
int tab_size;
int block_size;
int buf_size;
 
const char *filename;
const char *prgname;
 
int eof:1;
 
 
};
 
typedef struct mgen_stream MGEN_FILE;
 
enum {
MGEN_NT_SYM, /* describes a non-terminal symbol */
MGEN_T_SYM /* a terminal symbol */
};
 
/* representation of a symbol */
struct mgen_sym {
int type;
struct mgen_sym * next;
char *name;
};
 
/*extern struct rhs_elem;*/
struct rhs_elem{
struct mgen_sym * sym_list;
struct rhs_elem * next;
};
 
struct mgen_rule {
char * name;
int line;
struct rhs_elem * rhs_list;
};
 
 
#define mgen_rule_set mavl
 
 
int mgen_getc(struct mgen_stream * mf);
struct mgen_stream * mgen_open(const char *filename, const char *prgname);
int mgen_ungetc(int c, struct mgen_stream *mf);
int mgen_skip_spaces(struct mgen_stream * mf );
void mgen_perror(struct mgen_stream *mf, char *msg, ...);
struct mgen_stream * mgen_open_stream(FILE *infile, const char *prgname);
struct mgen_rule_set * mgen_read_rule_set(struct mgen_stream *mf);
struct mgen_rule_set * mgen_create_rule_set();
int mgen_parse( struct mgen_stream *mf,
struct mgen_rule_set *rules,
const char * start);
 
/* debugging stuff */
void print_symlist(struct mgen_sym * sym);
void print_rhs_list(struct rhs_elem *e);
 
#define mgen_isspace(c) isspace(c)
 
 
#define mgen_tell(mf) (mf->ring.abspos)
 
/*#define mgen_seek(mf,pos) (mf->bufptr=(pos))*/
 
 
#define mgen_seek(mf,pos) mgen_ring_seek(&((mf)->ring),pos)
 
 
#define mgen_set_block_size(mf,s) mf->block_size=s
#define mgen_set_buf_size(mf,s) mf->buf_size=s
 
#endif
/tags/mgen/0.0.2/mgen_create_rule_set.c
0,0 → 1,46
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "mgen.h"
 
static int
cmp_rules(const void *v1, const void *v2)
{
const char *s1,*s2;
s1 = ((struct mgen_rule *)v1)->name;
s2 = ((struct mgen_rule *)v2)->name;
 
return strcmp(s1,s2);
}
 
 
struct mgen_rule_set *
mgen_create_rule_set()
{
return mavl_create(cmp_rules,
NULL, sizeof (struct mgen_rule) );
}
/tags/mgen/0.0.2/mgen_getc.c
0,0 → 1,77
/*
* Copyright 2019, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include "mgen.h"
 
/**
* Function: mgen_getc
* -------------------
* Read one character from inputstream.
*
* mf: mgen_stream to read from
*
* returns: the next character from stream.
*
*/
int
mgen_getc(struct mgen_stream * mf)
{
int c;
 
if (mf->ring.abspos != mf->ring.absmaxpos){
int pos;
pos = mgen_ring_alloc(&mf->ring);
c = ((char*)(mf->ring.buf))[mf->ring.pos];
mgen_ring_next(&mf->ring);
}
else{
mgen_ring_alloc(&mf->ring);
c = fgetc(mf->infile);
if (c==EOF)
return EOF;
 
((char*)(mf->ring.buf))[mf->ring.pos]=c;
mgen_ring_next(&mf->ring);
}
 
/* count line number an column number */
switch(c) {
case '\n':
mf->line++;
mf->prev_col = mf->col;
mf->col=0;
break;
case '\t':
mf->col+=mf->tab_size;
break;
default:
mf->col++;
}
return c;
}
 
/tags/mgen/0.0.2/mgen_open.c
0,0 → 1,98
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
 
#include "mgen.h"
 
static struct mgen_stream *
mgen_stream_create()
{
struct mgen_stream * mf;
mf = malloc(sizeof(struct mgen_stream));
if (!mf)
return NULL;
 
mgen_ring_init(&(mf->ring));
 
 
/* mf->buf = malloc(MGEN_BUF_BLOCK_SIZE);
if (!mf->buf){
free (mf);
return NULL;
}*/
 
mf->buf = NULL;
mf->bufmax = 0;
mf->buflast=0;
mf->buffirst=0;
mf->buf_size = MGEN_BUF_SIZE;
mf->block_size = MGEN_BUF_BLOCK_SIZE;
 
mf->line = 1;
mf->col=0;
mf->bufptr=0;
mf->eof=0;
return mf;
}
 
struct mgen_stream *
mgen_open_stream(FILE *infile, const char *prgname)
{
struct mgen_stream * mf;
mf = mgen_stream_create();
if (!mf){
return NULL;
}
mf->prgname = prgname;
mf->infile = infile;
return mf;
}
 
struct mgen_stream *
mgen_open(const char *filename, const char *prgname)
{
FILE * infile;
struct mgen_stream * mf;
 
infile = fopen(filename,"rt");
if (infile==NULL)
return NULL;
 
 
mf = mgen_open_stream(infile,prgname);
/* mf = mgen_stream_create();*/
if (!mf){
(void)fclose(infile);
return NULL;
}
 
/* mf->infile = infile;*/
return mf;
}
 
/tags/mgen/0.0.2/mgen_parse.c
0,0 → 1,158
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include "mgen.h"
 
 
struct status {
int fpos;
struct rhs_elem * e;
int sstackptr;
};
 
 
struct mgen_parser {
struct mavl * rules;
struct mgen_stream * mf;
struct mgen_sym *sstack[1000];
int sstackptr;
struct status ststack[1000];
int ststackptr;
};
 
 
 
 
static int
check_string(struct mgen_stream *mf, char *str)
{
int i,c;
i=0;
while (str[i] != 0){
c=mgen_getc(mf);
if (c==str[i]){
i++;
continue;
}
return 0;
}
return 1;
}
 
static struct rhs_elem *
get_rhs_list(struct mgen_parser * prs, char *rulename)
{
struct mgen_rule *rule,rs;
rs.name = rulename;
rule = mavl_get(prs->rules,&rs);
if ( !rule ){
(void)printf("Fatal error rule not found %s\n",rulename);
return 0;
}
 
return rule->rhs_list;
}
 
static int
run_rhs_list(struct mgen_parser *prs, struct rhs_elem * e)
{
struct mgen_sym * sym;
struct status * st;
int i;
 
mainloop:
/* push curent status on sstack */
i = prs->ststackptr++;
prs->ststack[i].fpos = mgen_tell(prs->mf);
prs->ststack[i].e = e;
prs->ststack[i].sstackptr=prs->sstackptr;
 
next_sym1:
if (!e) {
if (prs->ststackptr==1)
return 0;
prs->ststackptr--;
goto quirk;
}
sym=e->sym_list;
 
next_sym:
 
if (!sym) {
if (prs->sstackptr==0)
return 1;
/* sym = popsym(prs); */
sym = prs->sstack[--prs->sstackptr];
goto next_sym;
}
switch( sym->type ){
case MGEN_T_SYM:
if (check_string(prs->mf,sym->name)){
sym=sym->next;
goto next_sym;
}
quirk:
st = &(prs->ststack[prs->ststackptr-1]);
e=st->e->next;
st->e=e;
mgen_seek(prs->mf,st->fpos);
prs->sstackptr=st->sstackptr;
goto next_sym1;
 
case MGEN_NT_SYM:
e = get_rhs_list(prs,sym->name);
/* pushsym(prs,sym->next); */
if (sym->next)
prs->sstack[prs->sstackptr++]=sym->next;
goto mainloop;
}
 
/* this should never happen */
return 0;
}
 
int
mgen_parse(
struct mgen_stream *mf,
struct mgen_rule_set *rules,
const char * start)
{
struct mgen_parser prs;
int rc;
struct rhs_elem * e;
 
prs.rules = rules;
prs.mf = mf;
prs.sstackptr=0;
prs.ststackptr=0;
 
e = get_rhs_list(&prs,(char*)start);
 
rc = run_rhs_list(&prs,e);
return rc;
}
/tags/mgen/0.0.2/mgen_perror.c
0,0 → 1,49
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdarg.h>
 
#include "mgen.h"
 
void
mgen_perror(struct mgen_stream *mf, char *msg, ...)
{
va_list argp;
va_start(argp, msg);
 
if (mf->filename){
(void)fprintf(stderr,"\"%s\",",mf->filename);
}
 
(void)fprintf(stderr, "line %d, col %d: error: ",
mf->line, mf->col);
 
(void)vfprintf(stderr,msg,argp);
(void)fprintf(stderr,"\n");
va_end(argp);
}
/tags/mgen/0.0.2/mgen_print_rhs_list.c
0,0 → 1,53
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include "mgen.h"
 
void
print_rhs_list(struct rhs_elem *e)
{
struct mgen_sym *sym;
char * delim_or, *delim_spc;
delim_or="";
while (e!=NULL){
sym = e->sym_list;
(void)printf("%s",delim_or);
delim_or="|";
delim_spc="";
while (sym!=NULL){
if (sym->type == MGEN_NT_SYM)
(void)printf("%s<%s>",delim_spc,sym->name);
else
(void)printf("%s%s",delim_spc,sym->name);
sym = sym->next;
delim_spc=" ";
}
e=e->next;
}
}
 
 
/tags/mgen/0.0.2/mgen_print_symlist.c
0,0 → 1,44
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include "mgen.h"
 
void
print_symlist(struct mgen_sym * sym)
{
char *delim_spc;
delim_spc="";
while (sym!=NULL){
if (sym->type == MGEN_NT_SYM)
(void)printf("%s<%s>",delim_spc,sym->name);
else
(void)printf("%s%s",delim_spc,sym->name);
sym = sym->next;
delim_spc=" ";
}
}
 
/tags/mgen/0.0.2/mgen_read_rule_set.c
0,0 → 1,388
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <errno.h>
 
#include "mgen.h"
 
#define MAX_NONTERMINAL 1024
#define MAX_TERMINAL 1024
 
struct bnf0_prs {
struct mgen_rule * current_rule;
struct rhs_elem * current_rhs_elem;
struct mgen_sym ** current_sym;
struct mavl *rules;
};
static int
skip_comment(struct mgen_stream * mf)
{
int c;
do {
c=mgen_getc(mf);
}while (c!='\n' && c!=EOF);
return c;
}
 
static int
get_non_terminal(struct mgen_stream * mf, char * result)
{
int c;
int i;
 
c=EOF; /* this eliminates a compiler warning
about c may be used unassigned */
 
for (i=0; i<MAX_NONTERMINAL; i++){
c = mgen_getc(mf);
if (c=='>')
break;
if (c=='\n' || c==EOF){
mgen_perror(mf,"missing '>' at end of non-terminal");
return EOF;
}
result[i]=(char)c;
}
 
if (i==MAX_NONTERMINAL && c!='>'){
mgen_perror(mf,"non-terminal symbol too long");
return EOF;
}
result[i]=0;
return c;
}
 
static int
get_terminal(struct mgen_stream * mf, char * result)
{
int c;
int i;
 
c=EOF; /* this eliminates a compiler warning
about c may be used unassigned */
 
for (i=0; i<MAX_TERMINAL; i++){
c = mgen_getc(mf);
if (c==' ' || c=='\n' || c=='|' ||
c=='\t' || c=='\r' || c==EOF)
break;
result[i]=(char)c;
}
 
if (i==MAX_TERMINAL ){
mgen_perror(mf,"terminal symbol too long");
return EOF;
}
result[i]=0;
 
return c;
}
 
 
static struct rhs_elem *
append_rhs_elem(struct rhs_elem ** next)
{
while (*next!=NULL){
next = &((*next)->next);
}
*next = malloc(sizeof(struct rhs_elem));
if (!*next)
return NULL;
(*next)->sym_list=NULL;
(*next)->next=NULL;
return *next;
}
 
static struct mgen_sym *
append_sym(struct mgen_sym ** next, int type, char *name)
{
struct mgen_sym * sym;
sym = malloc( sizeof( struct mgen_sym));
if (!sym){
return NULL;
}
sym->name = malloc( strlen(name)+1);
if (!sym->name){
return NULL;
}
(void)strcpy (sym->name,name);
sym->type=type;
sym->next=NULL;
 
*next = sym;
return sym;
}
 
 
 
static int
get_left_hand_side(struct mgen_stream * mf, struct bnf0_prs * prs)
{
int c;
char result[MAX_NONTERMINAL+1];
struct mgen_rule rule;
int exists;
 
while(1) {
c = mgen_skip_spaces(mf);
if (c==EOF)
return EOF;
if (c=='#' && mf->col==1){
c=skip_comment(mf);
mgen_ungetc(c,mf);
continue;
}
break;
}
 
 
if (c != '<' ){
mgen_perror(mf,"'<' expected.");
return EOF;
}
if (mf->col != 1){
mgen_perror(mf,
"left hand side of a rule has to start at column 1.");
return EOF;
}
 
c = get_non_terminal(mf, result);
if (c==EOF)
return EOF;
 
rule.name = malloc(strlen(result)+1);
if (!rule.name){
mgen_perror(mf,"can't allocate memory.");
return EOF;
}
(void)strcpy(rule.name,result);
rule.rhs_list=0;
rule.line = mf->line;
rule.rhs_list = NULL;
 
/* (void)printf("non-terminal found: %s\n",rule.name);*/
 
prs->current_rule =
mavl_insert(prs->rules, &rule, &exists);
 
if (!prs->current_rule){
mgen_perror(mf,"can't allocate memory\n");
return EOF;
}
 
if (exists){
char msg[MAX_NONTERMINAL+256];
(void)sprintf(msg,"symbol <%s> is already defined.",result);
mgen_perror(mf,msg);
return EOF;
}
 
prs->current_rhs_elem =
append_rhs_elem(&(prs->current_rule->rhs_list));
 
if (!prs->current_rhs_elem)
return EOF;
prs->current_sym = &prs->current_rhs_elem->sym_list;
return 0;
}
 
static int
get_right_hand_side(struct mgen_stream *mf, struct bnf0_prs *prs)
{
int c;
struct mgen_sym * sym;
/* int nsyms;
* nsyms = 0;*/
 
do{
c = mgen_skip_spaces(mf);
switch (c) {
case '|':
prs->current_rhs_elem =
append_rhs_elem(
&(prs->current_rule->rhs_list)
);
if (!prs->current_rhs_elem)
return EOF;
prs->current_sym =
&prs->current_rhs_elem->sym_list;
break;
 
case '<': {
int c1;
char result[MAX_NONTERMINAL+1];
if (mf->col <= 1){
mgen_ungetc(c,mf);
return c;
}
c1 = mgen_getc(mf);
mgen_ungetc(c1,mf);
if (!mgen_isspace(c1)) {
c = get_non_terminal(mf,result);
if (c==EOF)
return EOF;
sym=append_sym(
prs->current_sym,
MGEN_NT_SYM,result
);
 
if (!sym) {
mgen_perror(mf,
"Can't allocate memory"
);
return EOF;
}
prs->current_sym = &sym->next;
break;
}
}
default:{
char result[MAX_TERMINAL+1];
mgen_ungetc(c,mf);
c=get_terminal(mf,result);
sym=append_sym(
prs->current_sym,MGEN_T_SYM,result
);
if (!sym){
mgen_perror(mf,
"Can't allocate memory"
);
return EOF;
}
mgen_ungetc(c,mf);
prs->current_sym = &sym->next;
}
}
 
}while (c!=EOF);
 
return EOF;
}
 
static int
get_assignment (struct mgen_stream * mf)
{
int c,i,n;
char * search = "::=";
 
c = mgen_skip_spaces(mf);
 
i=0; n=(int)strlen(search);
do {
if (c!=search[i]){
mgen_perror(mf,"'::=' expected.");
return EOF;
}
i++;
c=mgen_getc(mf);
}while(i<n);
return c;
}
 
static void
verify(struct bnf0_prs * prs)
{
struct mavl *t;
struct mavliter it;
void *data;
struct mgen_stream mf;
 
t = prs->rules;
 
mavliter_init(&it, t);
(void)mavliter_seek_set(&it);
 
while ((data = mavliter_get(&it)) != NULL) {
struct mgen_rule * rule = (struct mgen_rule *)data;
struct rhs_elem *e;
struct mgen_sym *sym;
 
e = rule->rhs_list;
while (e!=NULL){
sym = e->sym_list;
while (sym!=NULL){
if (sym->type == MGEN_NT_SYM){
void * r;
struct mgen_rule trule;
trule.name = sym->name;
r = mavl_get(t,&trule);
if (!r){
char msg[MAX_NONTERMINAL+256];
(void)sprintf(msg,"unedfined non-terminal: <%s>",sym->name);
mf.line = rule->line;
mf.col = 0;
mgen_perror(&mf,msg);
return;
}
/* (void)printf("%s<%s>",delim_spc,sym->name);*/
}
sym = sym->next;
}
e=e->next;
}
(void)mavliter_next(&it);
}
}
 
 
 
struct mgen_rule_set * mgen_read_rule_set(struct mgen_stream *mf)
{
struct bnf0_prs prs;
struct mgen_rule_set * rules;
int c;
 
prs.rules = mgen_create_rule_set();
if (!prs.rules){
mgen_perror(mf,"can't allocate memory");
return NULL;
}
 
do {
c = get_left_hand_side(mf,&prs);
if (c==EOF)
break;
c = get_assignment(mf);
if (c==EOF)
break;
c = get_right_hand_side(mf,&prs);
 
}while(c!=EOF);
verify(&prs);
 
return prs.rules;
}
/tags/mgen/0.0.2/mgen_ring.c
0,0 → 1,192
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include "mgen.h"
 
void
mgen_ring_init(struct mgen_ring *m)
{
m->buf=NULL;
m->pos=0;
m->maxpos=0;
m->abspos=0;
m->absmaxpos=0;
m->block_size=MGEN_BUF_BLOCK_SIZE;
m->bufmax_size=MGEN_BUF_SIZE;
m->buf_size=0;
m->elem_size=1;
}
 
int
mgen_ring_seek(MGEN_RING * ring, size_t pos)
{
if (ring->buf_size == ring->bufmax_size ){
size_t diff;
size_t npos;
 
diff = ring->absmaxpos-pos;
if (diff > ring->buf_size)
return 0;
 
npos = ring->maxpos - diff;
 
if ( ring->maxpos > diff ){
ring->pos = ring->maxpos -diff;
}
else{
ring->pos = ring->bufmax_size - (diff-ring->maxpos);
}
 
if (ring->pos == ring->bufmax_size)
ring->pos=0;
 
ring->abspos = pos;
return 1;
}
if (pos<0)
return 0;
ring->pos = pos;
ring->abspos = pos;
return 1;
}
 
int
mgen_ring_prev(struct mgen_ring *m)
{
if ( (m->buf_size!=m->bufmax_size) || (m->bufmax_size==0) ){
if (m->abspos>0){
m->pos--;
m->abspos--;
return 1;
}
return 0;
}
 
/* printf("%d >= %d\n",m->absmaxpos - m->abspos,m->bufmax_size);*/
if ((m->absmaxpos - m->abspos) >= m->bufmax_size){
/* printf("ERRR!\n");*/
return 0;
}
 
if(m->pos==0){
m->pos = m->bufmax_size-1;
m->abspos--;
return 1;
}
 
m->pos--;
m->abspos--;
return 1;
}
 
/**
* Add one element to mgen_ring */
int
mgen_ring_add(struct mgen_ring *m)
{
if (m->pos == m->buf_size) {
if ( (m->buf_size!=m->bufmax_size) || (m->bufmax_size==0) ){
size_t s;
void *newbuf;
s=m->buf_size+m->block_size*m->elem_size;
if ( s>m->bufmax_size && m->bufmax_size!=0) {
s = m->bufmax_size;
}
/* (void)printf("Reallocating buffer to %d\n",s); */
newbuf = realloc(m->buf,s);
if (!newbuf)
return -1;
m->buf = newbuf;
m->buf_size=s;
/* m->pos += m->elem_size;
m->abspos += m->elem_size;
*/ }
else{
m->pos = 0;
m->abspos ++;
if (m->absmaxpos<m->abspos)
m->absmaxpos=m->abspos;
 
/* printf("ABSPOS: pos:%d, abspos:%d, absmaxpos:%d\n",m->pos,m->abspos,m->absmaxpos);*/
/* (void)printf("ring rest\n"); */
return m->pos;
}
}
m->pos ++;
m->abspos ++;
if (m->absmaxpos<m->abspos)
m->absmaxpos=m->abspos;
/*printf("ABSPOS: pos:%d, abspos:%d, absmaxpos:%d\n",m->pos,m->abspos,m->absmaxpos);*/
return m->pos;
}
 
 
int
mgen_ring_alloc(MGEN_RING *ring)
{
if(ring->buf_size == ring->bufmax_size){
return ring->pos;
}
 
if (ring->pos==ring->buf_size){
size_t s;
void * newbuf;
 
s=ring->buf_size+ring->block_size*ring->elem_size;
if ( s>ring->bufmax_size && ring->bufmax_size!=0) {
s = ring->bufmax_size;
}
 
newbuf = realloc(ring->buf,s);
if (!newbuf)
return -1;
ring->buf = newbuf;
ring->buf_size=s;
return ring->pos;
}
 
return ring->pos;
}
 
size_t
mgen_ring_next(struct mgen_ring *m)
{
m->pos++;
if (m->pos == m->bufmax_size && m->bufmax_size!=0){
m->pos=0;
}
m->abspos++;
if (m->abspos > m->absmaxpos){
m->absmaxpos = m->abspos;
m->maxpos=m->pos;
}
return m->pos;
}
 
/tags/mgen/0.0.2/mgen_run.c
0,0 → 1,5
 
 
int mgen_run()
{
}
/tags/mgen/0.0.2/mgen_skip_spaces.c
0,0 → 1,43
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include "mgen.h"
 
int
mgen_skip_spaces(struct mgen_stream * mf )
{
int c;
while (1) {
c=mgen_getc(mf);
if ( mgen_isspace(c) ) {
continue;
}
break;
};
return c;
}
 
/tags/mgen/0.0.2/mgen_ungetc.c
0,0 → 1,76
/*
* Copyright 2019,2020, The PLANIX Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include "mgen.h"
 
int
mgen_ungetc(int c, MGEN_FILE *mf)
{
if (!&mf->ring.buf)
return EOF;
 
if (!mgen_ring_prev(&mf->ring))
return EOF;
 
((char*)mf->ring.buf)[mf->ring.pos]=c;
 
switch(c) {
case '\n':
mf->line--;
mf->col=mf->prev_col;
break;
case '\t':
mf->col-=8;
break;
default:
mf->col--;
}
return c;
}
/*
void
mgen_ungetc(int c, struct mgen_stream *mf)
{
mf->bufptr--;
mf->buf[mf->bufptr]=(char)c;
mf->eof=0;
 
switch(c) {
case '\n':
mf->line--;
mf->col=mf->prev_col;
break;
case '\t':
mf->col-=8;
break;
default:
mf->col--;
}
}
 
*/
/tags/mgen/0.0.2/mi.prg
0,0 → 1,0
PROGRAMGgtBEGIN...END.
/tags/mgen/0.0.2/mipascal.bnf
0,0 → 1,13
#
# mini pascal
#
 
<Programm> ::= PROGRAM <Bezeichner> BEGIN <Satzfolge> END .
<Bezeichner> ::= <Buchstabe> <Restbezeichner>
<Restbezeichner> ::= | <Buchstabe oder Ziffer> <Restbezeichner>
<Buchstabe oder Ziffer> ::= <Buchstabe> | <Ziffer>
<Grossbuchstabe> ::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<Kleinbuchstabe> ::= a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
<Buchstabe> ::= <Grossbuchstabe> | <Kleinbuchstabe>
<Ziffer> ::= 0|1|2|3|4|5|6|7|8|9
<Satzfolge> ::= ...
/tags/mgen/0.0.2/my.bnf
0,0 → 1,10
<Programm> ::= a b c
<Programm1> ::= <Wort> Z u m s e l
<Buchstabe> ::= <Kleinbuchstabe> | <Grossbuchstabe>
<Wort> ::= <Buchstabe> <Wortrest> <Delimiter>
<Wortrest> ::= <Buchstabe> <Wortrest> |
<Kleinbuchstabe> ::= a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
<Grossbuchstabe> ::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<Delimiter> ::= _ <Delimiterrest>
<Delimiterrest> ::= <Delimiter> |
 
/tags/mgen/0.0.2/my.prg
0,0 → 1,0
abc
/tags/mgen/0.0.2
Property changes:
Added: svn:mergeinfo
## -0,0 +0,3 ##
Merged /branches/bnf/bnf_cleanup:r123-126
Merged /branches/mgen-tmp:r152-155
Merged /branches/bnf/mgen:r129-190