📄 cra.c
字号:
if (state->gen_state_no == -1) change = TRUE;
state->gen_state_no = 1;
}
return change;
}
/* mark all states not reachable from state 0 */
static void DeleteRedundantStates(void)
{
PStateNode state;
int s, change;
state = GetStateP(0);
CR_ASSERT(state != NULL);
state->gen_state_no = 0;
do {
change = FALSE;
for (s = root_state; s <= last_state; s++) {
state = GetStateP(s);
CR_ASSERT(state != NULL);
if (state->gen_state_no == -1) continue;
if (MarkToStates(&state->trans_list)) change = TRUE;
}
} while (change);
}
int MakeDeterministic(void)
{
int s, correct, changed;
last_sim_state = last_state;
if (last_state == 0) return TRUE;
FindCtxStates();
for (s = root_state; s <= last_state; s++) {
do {
changed = MakeUnique(s);
} while (changed);
}
correct = TRUE;
for (s = root_state; s <= last_state; s++) {
if (!MeltStates(s)) correct = FALSE;
}
CombineShifts();
return correct;
}
int StrToGraph(byte *name)
{
int next = 0, i, len, gp, first = 0;
len = strlen((char *) name);
for (i = 1; i <= len - 2; i++) {
gp = MakeGraph(T_CHAR, name[i]);
if (next) next = LinkGraph(next, gp);
else first = next = gp;
}
return first;
}
/* generate Ignore Chars */
static void GenIgnore(void)
{
int p;
PClassNode cn;
p = FindClass("@ignore_chars");
cn = GetClassP(p);
GenCode(fscan, "while (%C) Scan_NextCh();", &cn->data);
}
/* generate comment part in GET*/
static void GenCommentPart(void)
{
int p;
PCommentNode n;
Set set;
Set_Init(&set);
p = 0;
while (p < Collection_Count(&comment_tab)) {
n = (PCommentNode) Collection_At(&comment_tab, p);
Set_AddItem(&set, n->start_token[0]);
p++;
}
if (!Set_Empty(&set))
GenCode(fscan, "if ((%C) && Comment()) goto start;", &set);
Set_Done(&set);
}
/* generate State0 vector */
static void GenState0(void)
{
int i, n;
for (i = 0; i <= 254; i++) {
if (i % 30 == 0 && i / 30 > 0) GenCode(fscan, "$$");
n = GetTransition(0, (byte) i);
if (n < 0) n = 0;
GenCode(fscan, "%d,", n);
}
n = GetTransition(0, 255);
if (n < 0) n = 0;
GenCode(fscan, "%d", n);
}
/* generate literal class search */
static void fixname(char *s, char *d)
{
char temp[MAX_ID_LEN];
strcpy(temp, s); s = temp;
s[strlen(s) - 1] = '\0'; s++;
*d++ = '"';
while (*s) {
if (*s == '\\') *d++ = '\\';
if (*s == '"') *d++ = '\\';
*d++ = *s++;
}
*d++ = '"';
*d = '\0';
}
static void GenLiterals(void)
{
char token[MAX_ID_LEN], name[MAX_ID_LEN];
int i, p, start;
PTermNode n;
for (i = 33; i < 127; i++) {
p = 0;
start = 0;
while (p < term_tab.el_free) {
n = GetTermP(p);
CR_ASSERT(n != NULL);
if (n->type == T_LITTOKEN && n->name[1] == i) {
GetTermName(p, token);
if (start == 0) {
if (i != '\\') GenCode(fscan, "$1case '%c':$$", i);
else GenCode(fscan, "$1case %d:$$", i);
}
fixname(n->name, name);
GenCode(fscan, "$2if (EqualStr(%s)) return %s;$$", name, token);
start = 1;
}
p++;
}
if (start) GenCode(fscan, "$2break;$$");
}
}
/* generate comment function */
static void GenCommentBody(PCommentNode n)
{
CR_ASSERT(n != NULL);
GenCode(fscan, "$2while (1) {$$"
"$3if (Scan_Ch== %#) { /* 5 */$$", n->end_token[0]);
if (n->end_token[1] == 0) {
GenCode(fscan, "$4Level--; Scan_NextCh(); Scan_ComEols = Scan_CurrLine - StartLine;$$"
"$4if(Level == 0) return 1;$$");
} else {
GenCode(fscan, "$4Scan_NextCh();$$"
"$4if (Scan_Ch == %#) { /* 6 */$$", n->end_token[1]);
GenCode(fscan, "$5Level--; Scan_NextCh(); Scan_ComEols = Scan_CurrLine - StartLine;$$"
"$5if(Level == 0) return 1;$$"
"$4} /* 6 */ $$");
}
if (n->nested) {
GenCode(fscan, "$3} else /* 5 */$$");
GenCode(fscan, "$3if (Scan_Ch == %#) {$$", n->start_token[0]);
if (n->start_token[1] == 0) {
GenCode(fscan, "$4Level++; Scan_NextCh();$$");
} else {
GenCode(fscan, "$4Scan_NextCh();$$");
GenCode(fscan, "$4if (Scan_Ch == %#) { Level++; Scan_NextCh(); }$$", n->start_token[1]);
}
}
GenCode(fscan, "$3} else /* 5 */$$");
GenCode(fscan, "$3if (Scan_Ch == EOF_CHAR) return 0;$$$3else Scan_NextCh();$$");
GenCode(fscan, "$2} /* while */$$");
}
/* generate comment */
static void GenComment(PCommentNode n)
{
CR_ASSERT(n != NULL);
GenCode(fscan, "if (Scan_Ch == %#) { /* 1 */$$", n->start_token[0]);
if (n->start_token[1] == 0) {
GenCode(fscan, "$1Scan_NextCh();$$");
GenCommentBody(n);
} else {
GenCode(fscan, "$1Scan_NextCh();$$"
"$1if (Scan_Ch == %#) { /* 2 */$$"
"$2Scan_NextCh();$$", n->start_token[1]);
GenCommentBody(n);
GenCode(fscan, "$1} else { /* 2 */$$");
GenCode(fscan, "$2if (Scan_Ch == LF_CHAR) { Scan_CurrLine--; Scan_LineStart = OldLineStart; }$$");
GenCode(fscan, "$2Scan_BuffPos -= 2; Scan_CurrCol = OldCol - 1; Scan_NextCh();$$");
GenCode(fscan, "$1} /* 2 */$$");
}
GenCode(fscan, "} /* 1*/$$");
}
/* make the scanner */
/* generate State Transition */
static void GenStateTrans(int sn, PTransNode t, int is_context)
{
int to;
Set set1;
CR_ASSERT(t != NULL);
Set_Init(&set1);
if (t->type == T_CHAR) Set_AddItem(&set1, t->sym);
if (t->type == T_CLASS) {
PClassNode cn = GetClassP(t->sym);
Set_Copy(&set1, &cn->data);
}
to = Set_MinIndex(&t->to_states);
GenCode(fscan, "$1if (%C)",&set1);
if (t->tc == T_CONTEXT) { /* Transition With Context */
if (to != sn) GenCode(fscan, " { ctx++; state = %d;} else$$", to);
else GenCode(fscan, " ctx++; else$$");
} else {
if (is_context) { /* Normal Transition in Context State => Reset Context*/
if (to != sn) GenCode(fscan, " {ctx = 0; state = %d;} else$$", to);
else GenCode(fscan, " ctx = 0; else$$");
} else { /* Normal Transition */
if (to != sn) GenCode(fscan, " state = %d; else$$", to);
else GenCode(fscan, " /*same state*/; else$$");
}
}
Set_Done(&set1);
}
/* generate accepting token for a state */
static void GenStateAccept(int token, int is_context)
{
PTermNode tn;
if (is_context)
GenCode(fscan, "$1{$$"
"$2Scan_NextLen -= ctx; Scan_BuffPos -= ctx+1; Scan_CurrCol -= ctx+1; Scan_NextCh(); $$");
tn = GetTermP(token);
CR_ASSERT(tn != NULL);
if (tn->type == T_CLASSLITTOKEN)
GenCode(fscan, "%Ireturn CheckLiteral(%T);$$", 1 + is_context, token);
else {
if (token == 0) GenCode(fscan, "%Ireturn No_Sym;$$", 1 + is_context);
else GenCode(fscan, "%Ireturn %T;$$", 1 + is_context, token);
}
if (is_context) GenCode(fscan, "$1}$$");
}
/* generate state */
static void GenState(PStateNode state, int sn)
{
int i, c, is_context, t_count;
Collection *trans_tab;
PTransNode t;
CR_ASSERT(state != NULL);
if (state->gen_state_no == -1) return; /* unused stated */
is_context = (state->ctx == T_CONTEXT);
if (sn == 0) GenCode(fscan, " /* State 0; valid STATE0 Table$$");
GenCode(fscan, "case %d:$$", sn);
trans_tab = &state->trans_list;
c = Collection_Count(trans_tab);
t_count = 0;
for (i = 0; i < c; i++) {
t = GetTransP(trans_tab, i);
CR_ASSERT(t != NULL);
if (t->type == T_NONE) continue;
GenStateTrans(sn, t, is_context);
t_count++;
}
is_context = (state->ctx == T_CONTEXT && t_count == 0);
i = state->end_of;
if (i >= FIRST_PRAGMA) i = (i - FIRST_PRAGMA) + no_sym + 1;
GenStateAccept(i, is_context);
if (t_count) GenCode(fscan, "$1break;$$");
if (sn == 0) GenCode(fscan, " --------- End State0 --------- */$$");
}
void MakeScanner(void)
{
DeleteRedundantStates();
}
/* generate scanner */
int GenScannerOptions(FILE *Out, char *option)
{
fscan = Out;
if (!stricmp(option, "IgnoreCase")) {
GenCode(fscan, "%d", ignore_case);
} else
if (!stricmp(option, "State0")) {
GenState0();
} else
if (!stricmp(option, "Literals")) {
GenLiterals();
} else
if (!stricmp(option, "Comment")) {
Collection_ForEach(&comment_tab, (Collection_Func) GenComment);
} else
if (!stricmp(option, "GetDFA")) {
Collection_ForEachPos(&state_tab, (Collection_FuncPos) GenState);
} else
if (!stricmp(option, "GetIgnore")) {
GenIgnore();
} else
if (!stricmp(option, "GetComment")) {
GenCommentPart();
} else return 0;
return 1;
}
/* generate header file */
static void Func_GenHeaderItem(PTermNode n, int p)
{
char s[MAX_ID_LEN];
GetTermName(p, s);
fprintf(fhead, "#define %s\t%d\t/* %s */\n", s, p, n->name);
}
void GenScannerTokens(FILE *Out)
{
fhead = Out;
Collection_ForEachPos(&term_tab, (Collection_FuncPos) Func_GenHeaderItem);
fprintf(fhead, "#define %s\t%s\t/* %s */\n", "MAXT", "No_Sym", "Max Terminals");
}
/* initialize scanner generator tables */
void InitScannerTab(void)
{
Collection_Init(&state_tab, sizeof(StateNode), 50, 10);
Collection_Init(&melted_tab, sizeof(MeltedNode), 10, 5);
Collection_Init(&comment_tab, sizeof(CommentNode), 10, 5);
last_state = -1;
root_state = NewState();
}
/* destroy scanner generator tables */
static void Func_DoneState(PStateNode sn)
{
DoneState(sn);
}
static void Func_DoneMelt(PMeltedNode sn)
{
Set_Done(&sn->set);
}
void DoneScannerTab(void)
{
Collection_ForEach(&state_tab, (Collection_Func) Func_DoneState);
Collection_ForEach(&melted_tab, (Collection_Func) Func_DoneMelt);
Collection_Done(&state_tab);
Collection_Done(&melted_tab);
Collection_Done(&comment_tab);
}
/* dump state information to list file */
static void ShowState(PStateNode state, int sn)
{
Name name;
int i, c, tok;
Collection *trans_tab;
PTransNode t;
Set set1;
if (state->gen_state_no == -1) return;
fprintf(lstfile, "\n\nState %d: ", sn);
if (state->ctx) fprintf(lstfile, " Context State");
fprintf(lstfile, "\n");
Set_Init(&set1);
trans_tab = &state->trans_list;
c = Collection_Count(trans_tab);
for (i = 0; i < c; i++) {
t = GetTransP(trans_tab, i);
CR_ASSERT(t != NULL);
if (t->type == T_NONE) continue;
Set_Clean(&set1);
if (t->type == T_CHAR) Set_AddItem(&set1, t->sym);
if (t->type == T_CLASS) {
PClassNode cn = GetClassP(t->sym);
Set_Copy(&set1, &cn->data);
}
fprintf(lstfile, "\t");
Set_ForEach(&set1, (Set_Func) PrintAscii);
fprintf(lstfile, " -> ");
Set_ForEach(&t->to_states, (Set_Func) PrintInt);
if (t->tc == T_CONTEXT) fprintf(lstfile, " CONTEXT Trans");
fprintf(lstfile, "\n");
}
tok = state->end_of;
if (tok >= FIRST_PRAGMA) tok = (tok - FIRST_PRAGMA) + no_sym + 1;
if (tok) GetTermName(tok, name);
else strcpy(name, "No_Sym");
fprintf(lstfile, "\tAccept Token: %s (%d)\n", name, tok);
Set_Done(&set1);
}
void ShowDFA(void)
{
fprintf(lstfile, "\n\n\nDFA:\n");
Collection_ForEachPos(&state_tab, (Collection_FuncPos) ShowState);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -