나는 "입환 마당"알고리즘을 사용하는 것이를하고있는 중이 야 - 너무 거기에 psudocode 있습니다>https://en.wikipedia.org/wiki/Shunting-yard_algorithm
.
FTA : 컴퓨터 과학에서
는 차량 기지 알고리즘은 중위 표기법으로 지정 수학적 표현을 구문 분석하는 방법이다. RPN (Reverse Polish Notation) 또는 AST (Abstract Syntax Tree)라고도하는 접미사 표기법 문자열을 생성하는 데 사용할 수 있습니다. 이 알고리즘은 Edsger Dijkstra에 의해 발명되었으며 "shunting yard"알고리즘으로 명명되었습니다. 그 작업은 철도 셔틀 마당과 비슷하기 때문입니다. Dijkstra는 처음으로 Mathematisch Centrum 보고서 MR 34/61에서 Shunting Yard Algorithm에 대해 설명했습니다.
RPN의 평가와 마찬가지로, shunting yard 알고리즘은 스택 기반입니다. 중위어 표현은 대부분의 사람들이 익숙했던 수학 표기법의 형식입니다 (예 : "3 + 4"또는 "3 + 4 * (2-1)"). 변환에는 두 개의 텍스트 변수 (문자열), 입력 및 출력이 있습니다. 출력 대기열에 아직 추가되지 않은 연산자를 보유하는 스택도 있습니다. 변환을 위해 프로그램은 각 기호를 순서대로 읽고 해당 기호를 기반으로 작업을 수행합니다. 위 예제의 결과는 "3 4 +"또는 "3 4 2 1 - * +"입니다.
shunting-yard 알고리즘은 나중에 운영자 우선 구문 분석으로 일반화되었습니다.
코드, 그것은이 그것을 저장하는 방법 (그리고 C를 좋아하지 않는 경우 - http://rosettacode.org/wiki/Parsing/Shunting-yard_algorithm을 선택할 수) 아니라고 지적 이후 :
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
typedef struct {
const char *s;
int len, prec, assoc;
} str_tok_t;
typedef struct {
const char * str;
int assoc, prec;
regex_t re;
} pat_t;
enum assoc { A_NONE, A_L, A_R };
pat_t pat_eos = {"", A_NONE, 0};
pat_t pat_ops[] = {
{"^\\)", A_NONE, -1},
{"^\\*\\*", A_R, 3},
{"^\\^", A_R, 3},
{"^\\*", A_L, 2},
{"^/", A_L, 2},
{"^\\+", A_L, 1},
{"^-", A_L, 1},
{0}
};
pat_t pat_arg[] = {
{"^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"},
{"^[a-zA-Z_][a-zA-Z_0-9]*"},
{"^\\(", A_L, -1},
{0}
};
str_tok_t stack[256]; /* assume these are big enough */
str_tok_t queue[256];
int l_queue, l_stack;
#define qpush(x) queue[l_queue++] = x
#define spush(x) stack[l_stack++] = x
#define spop() stack[--l_stack]
void display(const char *s)
{
int i;
printf("\033[1;1H\033[JText | %s", s);
printf("\nStack| ");
for (i = 0; i < l_stack; i++)
printf("%.*s ", stack[i].len, stack[i].s); // uses C99 format strings
printf("\nQueue| ");
for (i = 0; i < l_queue; i++)
printf("%.*s ", queue[i].len, queue[i].s);
puts("\n\n<press enter>");
getchar();
}
int prec_booster;
#define fail(s1, s2) {fprintf(stderr, "[Error %s] %s\n", s1, s2); return 0;}
int init(void)
{
int i;
pat_t *p;
for (i = 0, p = pat_ops; p[i].str; i++)
if (regcomp(&(p[i].re), p[i].str, REG_NEWLINE|REG_EXTENDED))
fail("comp", p[i].str);
for (i = 0, p = pat_arg; p[i].str; i++)
if (regcomp(&(p[i].re), p[i].str, REG_NEWLINE|REG_EXTENDED))
fail("comp", p[i].str);
return 1;
}
pat_t* match(const char *s, pat_t *p, str_tok_t * t, const char **e)
{
int i;
regmatch_t m;
while (*s == ' ') s++;
*e = s;
if (!*s) return &pat_eos;
for (i = 0; p[i].str; i++) {
if (regexec(&(p[i].re), s, 1, &m, REG_NOTEOL))
continue;
t->s = s;
*e = s + (t->len = m.rm_eo - m.rm_so);
return p + i;
}
return 0;
}
int parse(const char *s) {
pat_t *p;
str_tok_t *t, tok;
prec_booster = l_queue = 0;
display(s);
while (*s) {
p = match(s, pat_arg, &tok, &s);
if (!p || p == &pat_eos) fail("parse arg", s);
/* Odd logic here. Don't actually stack the parens: don't need to. */
if (p->prec == -1) {
prec_booster += 100;
continue;
}
qpush(tok);
display(s);
re_op: p = match(s, pat_ops, &tok, &s);
if (!p) fail("parse op", s);
tok.assoc = p->assoc;
tok.prec = p->prec;
if (p->prec > 0)
tok.prec = p->prec + prec_booster;
else if (p->prec == -1) {
if (prec_booster < 100)
fail("unmatched)", s);
tok.prec = prec_booster;
}
while (l_stack) {
t = stack + l_stack - 1;
if (!(t->prec == tok.prec && t->assoc == A_L)
&& t->prec <= tok.prec)
break;
qpush(spop());
display(s);
}
if (p->prec == -1) {
prec_booster -= 100;
goto re_op;
}
if (!p->prec) {
display(s);
if (prec_booster)
fail("unmatched (", s);
return 1;
}
spush(tok);
display(s);
}
return 1;
}
int main()
{
int i;
const char *tests[] = {
"3 + 4 * 2/(1 - 5)^2^3", /* RC mandated: OK */
"123", /* OK */
"3+4 * 2/(1 - 5)^2^3.14", /* OK */
"(((((((1+2+3**(4 + 5))))))", /* bad parens */
"a^(b + c/d * .1e5)!", /* unknown op */
"(1**2)**3", /* OK */
0
};
if (!init()) return 1;
for (i = 0; tests[i]; i++) {
printf("Testing string `%s' <enter>\n", tests[i]);
getchar();
printf("string `%s': %s\n\n", tests[i],
parse(tests[i]) ? "Ok" : "Error");
}
return 0;
}
당신은 Aho Seti와 Ullman의 컴파일러 "용"책을 구입해야합니다. bison이라는 도구를 사용하면 "손으로"쓰는 데 소요되는 시간보다 훨씬 짧은 시간에 원하는 것을 얻을 수 있습니다. – Leo
불행하게도 나는이 프로젝트의 목적이 "손으로"모든 것을 할 목적으로 들소를 사용할 수 없다. 어쨌든 고마워. –