📄 sor.g
字号:
;
<<found_error=1;>>
class_def!
: "class"
( NonTerm <<strncpy(CurClassName,LATEXT(1),MaxAtom);>>
| Token <<strncpy(CurClassName,LATEXT(1),MaxAtom);>>
)
<<if ( !GenCPP ) { err("class meta-op used without C++ option"); }>>
"\{"
;
/*
* Create a rule tree:
*
* NonTerm[arg_action, ret_val_action]
* |
* v
* block
*/
rule: <<SymEntry *p; int trouble=0, no_copy=0;>>
NonTerm^
<<
#0->file = CurFile;
#0->line = zzline;
CurRule = $1.text;
p = (SymEntry *) hash_get(symbols, $1.text);
if ( p==NULL ) {
p = (SymEntry *) hash_add(symbols, $1.text, (Entry *) newSymEntry($1.text));
p->token = NonTerm;
p->defined = 1;
p->definition = #0;
}
else if ( p->token != NonTerm ) {
err(eMsg2("rule definition clashes with %s definition: '%s'", zztokens[p->token], p->str));
trouble = 1;
}
else {
if ( p->defined ) {
trouble = 1;
err(eMsg1("rule multiply defined: '%s'", $1.text));
}
else {
p->defined = 1;
p->definition = #0;
}
}
>>
{ "!"! <<if (!trouble) #0->no_copy=no_copy=1;>> }
( { "\<"! } PassAction! <<if (!trouble) p->args = actiondup(LATEXT(1));>>
|
)
{ "\>"! PassAction! <<if (!trouble) p->rt = actiondup(LATEXT(1));>>
}
":"!
block[no_copy]
";"!
<<
if ( !trouble ) #0->refvars = RefVars;
RefVars=NULL;
>>
<<
if ( trouble ) #0 = NULL;
CurRule = NULL;
>>
;
<<found_error=1;>>
/* Create a tree for a block:
*
* BLOCK
* |
* v
* alt1 ---> alt2 ---> ... ---> altn
*/
block[int no_copy]
: <<int line=zzline, file=CurFile;>>
alt[$no_copy]
( "\|"! alt[$no_copy]
)*
<<
#0 = #( #[BLOCK], #0 );
#0->file = file;
#0->line = line;
>>
;
<<found_error=1;>>
/* Create a tree for an alternative:
*
* ALT
* |
* v
* e1 ---> e2 ---> ... ---> en
*/
alt[int no_copy]
: <<int line=zzline, file=CurFile; int local_no_copy=0;>>
{ "!"! <<local_no_copy=1;>> }
{
( labeled_element[$no_copy||local_no_copy]
| element[$no_copy||local_no_copy]
| tree[$no_copy||local_no_copy]
)+
}
<<
#0 = #( #[ALT], #0 );
#0->file = file;
#0->line = line;
>>
;
<<found_error=1;>>
/* a rule ref looks like:
*
* NonTerm
* |
* v
* arg_action ---> ret_val_action
*
* Blocks that have a suffix look like this:
*
* OP
* |
* v
* block
*
* Optional blocks look like:
*
* OPT
* |
* v
* block
*
* Predicates are like actions except they have a root: #( PRED_OP Action )
*/
element[int no_copy]
: <</**** SymEntry *p; **** MR10 ****/ int file,line; int local_no_copy=0;>>
token[$no_copy]
| <<file = CurFile; line=zzline;>>
NonTerm^
{ "!"! <<local_no_copy = 1;>> }
{ { "\<"! } PassAction <<#0->in = 1;>> }
{ "\>"! PassAction <<#0->out = 1;>> }
<<#0->file = file; #0->line=line;>>
<<#0->no_copy = $no_copy || local_no_copy;>>
| <<file = CurFile; line=zzline;>>
Action <<#1->action = actiondup(LATEXT(1));>>
{ "?"^ } <<#0->file = file; #0->line=line;>>
| <<file = CurFile; line=zzline;>>
"\("! block[$no_copy] "\)"!
( "\*"^
| "\+"^
| "?"^ <<found_guess_block=1;>>
|
)
<<#0->file = file; #0->line=line;>>
| "\{"^ block[$no_copy] "\}"!
| <<file = CurFile; line=zzline;>>
"."
{ "!"! <<local_no_copy = 1;>> }
<<#0->no_copy = $no_copy || local_no_copy;>>
<<#0->file = file; #0->line=line;>>
;
<<found_error=1;>>
/* labels on an element look like: #( LABEL element ) */
labeled_element[int no_copy]
: <<Attrib label; int file,line; SymEntry *s; int local_no_copy=0;>>
( Token! <<label = $1;>>
| NonTerm! <<label = $1;>>
)
<<
s = (SymEntry *) hash_get(symbols, label.text);
if ( s==NULL ) {
s = (SymEntry *) hash_add(symbols, label.text, (Entry *) newSymEntry(label.text));
s->token = LABEL;
}
else if ( s->token!=LABEL ) {
err(eMsg2("label definition clashes with %s definition: '%s'", zztokens[s->token], label.text));
}
>>
":"!
( <<file = CurFile; line=zzline;>>
token[$no_copy] <<strcpy(#1->label, label.text);>>
<<#0->file = file; #0->line=line;>>
| <<file = CurFile; line=zzline;>>
NonTerm^ <<strcpy(#1->label, label.text);>>
{ "!"! <<local_no_copy = 1;>> }
{ { "\<"! } PassAction <<#0->in = 1;>> }
{ "\>"! PassAction <<#0->out = 1;>> }
<<#0->file = file; #0->line=line;>>
<<#0->no_copy = $no_copy || local_no_copy;>>
| <<file = CurFile; line=zzline;>>
"." <<strcpy(#1->label, label.text);>>
{ "!"! <<local_no_copy = 1;>> }
<<#0->no_copy = $no_copy || local_no_copy;>>
<<#0->file = file; #0->line=line;>>
| ("\|" | ";" | PassAction | Action | Eof | "\(" | "\{" | "\)" | "\}" | "#\(")
<<
err("cannot label this grammar construct");
found_error = 1;
>>
)
;
<<found_error=1;>>
token[int no_copy]
: <<SymEntry *p; int file, line; int local_no_copy=0;>>
<<file = CurFile; line=zzline;>>
Token
<<#0->file = file; #0->line=line;>>
<<define_token($1.text);>>
{ ".."! Token!
{ "!"! <<local_no_copy=1;>>}
<<
if ( !UserDefdTokens ) {
err("range operator is illegal without #tokdefs directive");
}
else {
p = define_token($2.text);
require(p!=NULL, "token: hash table is broken");
#0->upper_range = p->token_type;
}
>>
| "!"! <<local_no_copy=1;>>
}
<<#0->no_copy = $no_copy||local_no_copy;>>
;
/* A tree description looks like:
*
* BT
* |
* v
* root ---> sibling1 ---> ... ---> siblingn
*/
tree[int no_copy]
: <<Attrib label; SymEntry *p, *s; int local_no_copy=0; AST *t=NULL;>>
"#\("!
( Token^ <<t=#1;>>
<<define_token($1.text);>>
{ ".."! Token! /* inline rather than 'token' because must be root */
{ "!"! <<local_no_copy=1;>>}
<<
if ( !UserDefdTokens ) {
err("range operator is illegal without #tokdefs directive");
}
else {
p = define_token($2.text);
require(p!=NULL, "element: hash table is broken");
t->upper_range = p->token_type;
}
>>
| "!"! <<local_no_copy=1;>>
}
<<t->no_copy = $no_copy||local_no_copy; t->is_root = 1;>>
| "."^
{ "!"! <<local_no_copy = 1;>> }
<<#1->no_copy = $no_copy || local_no_copy; #1->is_root = 1;>>
| ( Token! <<label = $1;>>
| NonTerm! <<label = $1;>>
)
<<
s = (SymEntry *) hash_get(symbols, label.text);
if ( s==NULL ) {
s = (SymEntry *) hash_add(symbols, label.text, (Entry *) newSymEntry(label.text));
s->token = LABEL;
}
else if ( s->token!=LABEL ) {
err(eMsg2("label definition clashes with %s definition: '%s'", zztokens[s->token], label.text));
}
>>
":"!
( Token^ <<strcpy(#1->label, label.text); t = #1;>>
<<define_token($1.text);>>
{ ".."! Token! /* inline rather than 'token' because must be root */
{ "!"! <<local_no_copy=1;>>}
<<
if ( !UserDefdTokens ) {
err("range operator is illegal without #tokdefs directive");
}
else {
p = define_token($2.text);
require(p!=NULL, "element: hash table is broken");
t->upper_range = p->token_type;
}
>>
| "!"! <<local_no_copy=1;>>
}
<<t->no_copy = $no_copy||local_no_copy;>>
| "."^ <<strcpy(#1->label, label.text);>>
{ "!"! <<local_no_copy = 1;>> }
<<#1->no_copy = $no_copy || local_no_copy;>>
)
<<t->is_root = 1;>>
)
( labeled_element[$no_copy] | element[$no_copy] | tree[$no_copy] )*
"\)"!
;
<<found_error=1;>>
#token NonTerm "[a-z] [A-Za-z0-9_]*"
#token Token "[A-Z] [A-Za-z0-9_]*"
#token "#[A-Za-z0-9_]*" <<warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >>
/* # t o k d e f s s t u f f */
#lexclass TOK_DEF_COMMENTS
#token "\*/" << zzmode(PARSE_ENUM_FILE); zzmore(); >>
#token "\*" << zzmore(); >>
#token "\n|\r|\r\n" << zzline++; zzmore(); >> /* MR16a */
#token "~[\n\r\*]+" << zzmore(); >> /* MR16a */
#lexclass TOK_DEF_CPP_COMMENTS
#token "\n|\r|\r\n" << zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); >> /* MR16a */
#token "~[\n\r]+" << zzskip(); >> /* MR16a */
#lexclass PARSE_ENUM_FILE
#token "[\t\ ]+" << zzskip(); >> /* Ignore White */
#token "\n|\r|\r\n" << zzline++; zzskip(); >> /* Track Line # */ /* MR16a */
#token "//" << zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >>
#token "/\*" << zzmode(TOK_DEF_COMMENTS); zzmore(); >>
#token "#ifndef" << >>
#token "#ifdef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
#token "#else" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
#token "#define" <<
>>
#token "#endif" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
#token "@" << /*zzmode(START); zzskip();*/ >>
enum_file!
: <<SymEntry *p=NULL;>>
{ "#ifndef" ID
{ "#define" ID /* ignore if it smells like a gate */
/* First #define after the first #ifndef (if any) is ignored */
}
}
( enum_def )+
| defines
|
;
defines!
: <<int maxt= -1; /**** char *t; **** MR10 ****/ SymEntry *p; int ignore=0;>>
(
"#define" ID
<<
p = (SymEntry *) hash_get(symbols, $2.text);
if ( p==NULL ) {
p = (SymEntry *) hash_add(symbols, $2.text,
(Entry *) newSymEntry($2.text));
require(p!=NULL, "can't add to sym tab");
p->token = Token;
list_add(&token_list, (void *)p);
set_orel(p->token_type, &referenced_tokens);
}
else
{
err(eMsg1("redefinition of token %s; ignored",$2.text));
ignore = 1;
}
>>
INT
<<
if ( !ignore ) {
p->token_type = atoi($3.text);
token_association(p->token_type, p->str);
/* fprintf(stderr, "#token %s=%d\n", p->str, p->token_type);*/
if ( p->token_type>maxt ) maxt=p->token_type;
ignore = 0;
}
>>
)+
<<token_type = maxt + 1;>> /* record max defined token */
;
enum_def!
: <<int maxt = -1, v= -1; /**** char *t; **** MR10 ****/ SymEntry *p; int ignore=0;>>
"enum" {ID}
"\{"
ID
<<
p = (SymEntry *) hash_get(symbols, $4.text);
if ( p==NULL ) {
p = (SymEntry *) hash_add(symbols, $4.text,
(Entry *) newSymEntry($4.text));
require(p!=NULL, "can't add to sym tab");
p->token = Token;
list_add(&token_list, (void *)p);
set_orel(p->token_type, &referenced_tokens);
}
else
{
err(eMsg1("redefinition of token %s; ignored",$4.text));
ignore = 1;
}
>>
( "=" INT <<v=atoi($2.text);>>
| <<v++;>>
)
<<
if ( !ignore ) {
/* fprintf(stderr, "#token %s=%d\n", p->str, v);*/
if ( v>maxt ) maxt=v;
p->token_type = v;
token_association(p->token_type, p->str);
ignore = 0;
}
>>
( ","
{ "DLGminToken" { "=" INT } /* 1.33MR6 compatibility */
| "DLGmaxToken" { "=" INT } /* 1.33MR6 compatibility */
| ID
<<
p = (SymEntry *) hash_get(symbols, $1.text);
if ( p==NULL ) {
p = (SymEntry *) hash_add(symbols, $1.text,
(Entry *) newSymEntry($1.text));
require(p!=NULL, "can't add to sym tab");
p->token = Token;
list_add(&token_list, (void *)p);
set_orel(p->token_type, &referenced_tokens);
}
else
{
err(eMsg1("redefinition of token %s; ignored",$1.text));
ignore = 1;
}
>>
( "=" INT <<v=atoi($2.text);>>
| <<v++;>>
)
<<
if ( !ignore ) {
/* fprintf(stderr, "#token %s=%d\n", p->str, v);*/
if ( v>maxt ) maxt=v;
p->token_type = v;
token_association(p->token_type, p->str);
ignore = 0;
}
>>
}
)*
"\}"
";"
<<token_type = maxt + 1;>> /* record max defined token */
;
#token INT "[0-9]+"
#token ID "[a-zA-Z_][_a-zA-Z0-9]*"
#lexclass START
<<
/* SORCERER-specific syntax error message generator
* (define USER_ZZSYN when compiling so don't get 2 definitions)
*/
void
#ifdef __USE_PROTOS
zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)
#else
zzsyn(text, tok, egroup, eset, etok, k, bad_text)
char *text, *egroup, *bad_text;
int tok;
int etok;
int k;
SetWordType *eset;
#endif
{
fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);
fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
if ( k==1 ) fprintf(stderr, " missing");
else
{
fprintf(stderr, "; \"%s\" not", bad_text);
if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
}
if ( zzset_deg(eset)>0 ) zzedecode(eset);
else fprintf(stderr, " %s", zztokens[etok]);
if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);
fprintf(stderr, "\n");
}
SymEntry *
#ifdef __USE_PROTOS
define_token(char *text)
#else
define_token(text)
char *text;
#endif
{
SymEntry *p;
p = (SymEntry *) hash_get(symbols, text);
if ( p==NULL ) {
if ( UserDefdTokens ) {
err(eMsg1("implicit token definition of '%s' not allowed with #tokdefs",text));
}
p = (SymEntry *) hash_add(symbols, text, (Entry *) newSymEntry(text));
p->token = Token;
p->token_type = token_type++;
token_association(p->token_type, p->str);
list_add(&token_list, (void *)p);
set_orel(p->token_type, &referenced_tokens);
}
else {
if ( p->token!=Token )
err(eMsg2("token definition clashes with %s definition: '%s'", zztokens[p->token], text));
}
return p;
}
>>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -