You are on page 1of 45

.

.
,
,
.
.
, , , ,
(, ,
-2, ) .,
(, ). ,
,

.

.

.
CISC, RISC. , Intel,
Motorola, Sun, RISC. ,

.

.

1.
:
-,
( ASCII ANSI) .
- ,
.

.

:
)

= =

. , X=0.06
, , F=-X/0.01
)
PRINT ( ) PRINT ()
, PRINT(X) PRINT(X+F)
)
.
:
+ ;
, ;
* ;
/ ;
ABS() ;

^ ( 0);
SQRT() ;
EXP() ;
LN() .

().
,
- .

2.
( ).
:
< > = L<C>; (L - , C )
< > = <'print',
'abs', 'sqrt', 'exp', 'ln'>
<> = <'+', '-', '/', '*', '(', ')', '.', '^'>
- .
, .
,
, .

3.
-
Borland ++ 6.0
, ASCII-,
, .

3.1

(Form1),

.
Panel1, RichEdit1, MainMenu1
OpenDialog1.

Panel1:
- (Height) = 289

(Width) = 449
Form1:
- AutoSize = true
Caption =
MainMenu1:

,
, .
Ctrl+O
Ctrl+X
F9


Object Inspector
MainMenu1
ShortCut .

RichEdit1
,

.
OpenDialog1:
(txt)

OpenDialog1. Object
Inspector OpenDialog1 Filter

*.txt - TXT
*.* -

, .
3.2
Unit1.cpp

#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"*Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------__fastcall TForm1::Open1Click(TObject *Sender)
{->Options.Clear();->Options

<<

ofAllowMultiSelect

<<

ofFileMustExist;(OpenDialog1->Execute())->Lines>LoadFromFile(OpenDialog1->FileName);
}
//--------------------------------------------------------------------------__fastcall TForm1::Calculate1Click(TObject *Sender)
{*code;buffer[1024];=

RichEdit1->Lines->GetText();*cb

parser_codebuffer_new(code);
/* */v1 = parser_evaluate(cb);
/*

*/->Lines-

>Add((v1.error));
/*

*/_value_free(&v1);
/* */

v1

parser_codebuffer_destroy(cb);
/* cb */(cb);
}__fastcall TForm1::Variable_print_all(ParserVariable *variables[])
{(!variables)

return;_t

i;buffer[1024];(i=0;

i<

MAX_VARIABLE_LIST_LEN; i++)
{(!variables[i]) continue;*var = variables[i];(var->val.type)
{TOK_NUMERIC:(buffer,"%s=%s\n",var->name,
parser_value_show_as_string(&var->val));->Lines->Add
(buffer);;TOK_STRING:(buffer,"%s=%s\n",var->name, var->val.s);->Lines>Add (buffer);;:(buffer, "%s %d.\n",
var->name, var->val.type);->Lines->Add (buffer);;
}
}
}
//--------------------------------------------------------------------------__fastcall TForm1::Exit1Click(TObject *Sender)
{();
}
Parser.cpp
#include "lexer.h"
#include "parser.h"
#include "Unit1.h"
#ifndef M_PI
#define M_PI 3.14159265358979323
#endifparser_statements(CodeBuffer

*cb);parser_assign(CodeBuffer

*cb);do_sqrt(ParserVal *a, int b);do_abs(ParserVal *, int);do_exp(ParserVal


*, int);do_ln(ParserVal *, int);do_pow(ParserVal *, int);do_integer(ParserVal

*,

int);do_round(ParserVal

*,

int);do_fraction(ParserVal

*,

int);do_boolean_str(int oper, ParserVal *v1, ParserVal *v2);do_boolean(int


oper, ParserVal *v1, ParserVal *v2);do_math(int oper, ParserVal *v1,
ParserVal *v2);do_unary(int oper, ParserVal *v1);do_power(ParserVal *v1,
ParserVal *v2);parser_do_print(ParserVal *, int);g_function_table[] = {
/* */
{"sqrt", 1, do_sqrt},
{"abs", 1, do_abs},
{"exp", 1, do_exp},
{"ln", 1, do_ln},
{"pow", 2, do_pow},
{"print", 1, parser_do_print},
{"int", 1, do_integer},
{"modf", 1, do_fraction}
};*lookup_builtin_function(char
*name);*builtin_function_arg_text(BuiltinFunction
parser_strlen(char

*func);_t

*s);execute_builtin_function(CodeBuffer

BuiltinFunction

*cb,

*func);parser_bool_or(CodeBuffer

*cb);parser_bool_and(CodeBuffer

*cb);parser_bool1(CodeBuffer

*cb);parser_bool2(CodeBuffer

*cb);parser_bool3(CodeBuffer

*cb);parser_level1(CodeBuffer

*cb);parser_level2(CodeBuffer

*cb);parser_level3(CodeBuffer

*cb);parser_level4(CodeBuffer

*cb);parser_level5(CodeBuffer
*msg,

int

*cb);parser_error(CodeBuffer

opt);parser_convert_to_numeric(ParserVal

*v);parser_convert_to_string(ParserVal
*v);is_string(ParserVal

*cb, char

*v);str_icmp(char

*v);is_numeric(ParserVal
*s1,

char

*s2);parser_add_strings(ParserVal *v1, ParserVal *v2);get_int_part(double

x);round_num(double d, unsigned int dec_places);


/* token
*/
TokenRec currToken;parser_evaluate(CodeBuffer *cb)
{
/* parsing col 0, line 1 */>curr_pos = 0;>line_num = 1;
(cb->char_backbuf,

'\0',

MAX_CHAR_BACKBUF_LEN);>tok_backbuf_count

0;_variable_add_standard_constants(cb);v1 = parser_statements(cb);
/* v1 .
parser_value_free(&v1); */v1;
}parser_do_print(ParserVal

*v,

int

{buffer[1024];_convert_to_numeric(v);>s
parser_format_string(":%g",

arg_count)
=

v->d);->RichEdit1->Lines->Add(v-

>s);;
}parser_statements(CodeBuffer *cb)
{v1;_value_init_to_numeric(&v1, 0.0);_get_token(cb, &currToken);
(currToken.type != TOK_EOF)
{= parser_assign(cb);(v1.error)
{_error(cb, v1.error, TRUE);v1;
}(v1.type)
{TOK_STRING:;TOK_NUMERIC:
break;'\n':
/* */;
}
}
/* V1 .

parser_value_free(&v1);
*/v1;
}parser_assign(CodeBuffer *cb)
{v1;**variables = parser_variable_create_list();
/* token token '=' */
while (currToken.type == TOK_IDENT && lexer_lookahead(cb, '=',
TRUE/*remove it*/))
{*var = (ParserVariable *)calloc(1, sizeof(ParserVariable));>name =
parser_format_string("%s",

currToken.str);_value_init_to_numeric(&var-

>val, 0.0);
/*

*/_variable_add_to_list(variables, var);_get_token(cb, &currToken);


}
/* */= parser_bool1(cb);
if (!v1.error)
{_t i;(i = 0; i < MAX_VARIABLE_LIST_LEN; i++)
{(!variables[i])

continue;_value_copy(&v1,

&variables[i]-

>val);_variable_add_to_list(cb->variable_list, variables[i]);
}
}(variables);v1;
}parser_bool1(CodeBuffer *cb)
{oper;v1 = parser_bool2(cb);
oper = currToken.type;
/* : '&&' AND */
while (oper == TOK_AND)
{_PAR2(" parser_bool1 (&&): =%c
v1=%s\n",

oper,

parser_value_show_as_string(&v1));_get_token(cb,

&currToken);v2 = parser_bool2(cb);_boolean(oper, &v1, &v2);


/* Free v2 */_value_free(&v2);= currToken.type;(v1.error) break;
}v1;
}parser_bool2(CodeBuffer *cb)
{oper;v1 = parser_bool3(cb);
oper = currToken.type;
/* : '||' OR */
while (oper == TOK_OR)
{_PAR2(" parser_bool2 (||): =%c v1=
%s\n",

oper,

parser_value_show_as_string(&v1));_get_token(cb,

&currToken);v2 = parser_bool3(cb);_boolean(oper, &v1, &v2);


/* Free v2 */_value_free(&v2);= currToken.type;(v1.error) break;
}v1;
}parser_bool3(CodeBuffer *cb)
{oper;v1 = parser_level1(cb);
oper = currToken.type;
/* : ==, >, >=, <, <= */
while (oper == TOK_EQ || oper == TOK_GT || oper == TOK_LT ||
oper == TOK_LE || oper == TOK_GE)
{_PAR2(" parser_bool3 (==, >, >=, <, <=): =%c

v1=%s\n",

parser_value_show_as_string(&v1));_get_token(cb,

oper,
&currToken);v2

parser_level1(cb);_boolean(oper, &v1, &v2);


/* Free v2 */_value_free(&v2);= currToken.type;(v1.error) break;
}v1;
}parser_level1(CodeBuffer *cb)
{oper;v1 = parser_level2(cb);

oper = currToken.type;
/* : +, - */
while (oper == TOK_PLUS || oper == '-')
{_PAR2(" parser_level1 (+/-): =%c
v1=%s\n",

oper,

parser_value_show_as_string(&v1));_get_token(cb,

&currToken);v2 = parser_level2(cb);_math(oper, &v1, &v2);


/* Free v2 */_value_free(&v2);= currToken.type;(v1.error) break;
}v1;
}parser_level2(CodeBuffer *cb)
{oper;v1 = parser_level3(cb);= currToken.type;
// *, /(oper == TOK_MUL || oper == TOK_DIV)
{_PAR2(" parser_level2: =%c v1=
%s\n",

oper,

parser_value_show_as_string(&v1));_get_token(cb,

&currToken);v2 = parser_level3(cb);_math(oper, &v1, &v2);


/* Free v2 */_value_free(&v2);= currToken.type;(v1.error) break;
}v1;
}parser_level3(CodeBuffer *cb)
{v1 = parser_level4(cb);
/* '^' : 2^3 = 8. */(currToken.type == TOK_EXP)
{_get_token(cb,

&currToken);("parser_level3:
v1=%s\n",

TOK_EXP,

parser_value_show_as_string(&v1));_PAR2("
=%c

=%c

v1=%s\n",

parser_level3:
TOK_EXP,

parser_value_show_as_string(&v1));v2 = parser_level3(cb); /* Recursively


*/_power(&v1, &v2);
/* Free v2 */_value_free(&v2);
}v1;

}parser_level4(CodeBuffer *cb)
{
int oper;
oper = 0;
/* +/- . (+3) + -3. */(currToken.type == '-' ||
currToken.type == '+')
{= currToken.type;_get_token(cb, &currToken);
}v1 = parser_level5(cb);(oper != 0)
{_PAR2(" parser_level4 ( +/-): =%c
v1=%s\n", oper, parser_value_show_as_string(&v1));_unary(oper,
&v1);
}v1;
}parser_level5(CodeBuffer *cb)
{val;v1;

//=

{.type=TOK_NUMERIC,

{.d=0.0},.error=NULL};.type=TOK_NUMERIC;.d=0.0;
v1.error=NULL;
/* token */
val = currToken;(currToken.type)
{
/* '(' ')'.
. "((2 + 5) * 6)"
*/TOK_PAROPEN:_get_token(cb, &currToken);
v1 = parser_bool1(cb);
/* ')' ? */(currToken.type != TOK_PARCLOSE)
{
/* ')' */
v1.error = parser_format_string(" ')'.");

}_get_token(cb,

&currToken);;TOK_NUMERIC:.type

TOK_NUMERIC;.d = currToken.val.d;_get_token(cb, &currToken);


break;TOK_IDENT:
{
/*

*/*func

lookup_builtin_function(currToken.str);
if (func)
{
/* '(' */
if (!lexer_lookahead(cb, '(',TRUE/*remove it*/))
{
/* '(' */.error = parser_format_string("
'(' %s.\n", func->name);l_end_ident;
}_get_token(cb, &currToken);= execute_builtin_function(cb, func);
/* ')' ? */(currToken.type != TOK_PARCLOSE)
{
/* ')' */.error = parser_format_string("
')'. '%s'.", currToken.str);
}
}
{ /* */i = parser_variable_find(cb->variable_list,
currToken.str);(i > -1)
{*var = cb->variable_list[i];_value_copy(&var->val, &v1);
}
{
/* */
v1.error

parser_format_string("

'%s'.", currToken.str);
}
}_end_ident:_get_token(cb, &currToken);
};TOK_STRING:
/*

"

'

*/_value_set_to_string(&v1,

currToken.str);_get_token(cb, &currToken);;'\n':';':
/* */.type = '\n';
lexer_get_token(cb,

&currToken);;:.error

parser_format_string("

=
'%s'",

currToken.str);_get_token(cb, &currToken);
}_PAR2(" parser_level5: type=%d v1=%s.\n",
val.type, parser_value_show_as_string(&v1));v1;
}do_boolean_str(int oper, ParserVal *v1, ParserVal *v2)
{_convert_to_string(v1);_convert_to_string(v2);ret = strcmp(v1->s,
v2->s);(oper)
{
/* v1 == v2 */TOK_EQ:_value_set_to_numeric(v1, (double)(ret ==
0));;
/* v1 > v2 */TOK_GT:_value_set_to_numeric(v1, (double)(ret > 0));;
/* v1 >= v2 */TOK_GE:_value_set_to_numeric(v1, (double)(ret > 0 ||
ret == 0));;
/* v1 < v2 */TOK_LT:_value_set_to_numeric(v1, (double)(ret < 0));;
/* v1 <= v2 */TOK_LE:_value_set_to_numeric(v1, (double)(ret < 0 ||
ret == 0));;
/*

v1

&&

parser_strlen(v2->s)))
{

v2

*/TOK_AND:(!(parser_strlen(v1->s)

&&

/* Set v1 to zero (FALSE) */_value_free(v1);


};
/* v1 || v2 */TOK_OR:(!parser_strlen(v1->s))
{
/* Copy v2 to v1 */_value_free(v1);_value_copy(v2, v1);
};
}
}do_boolean(int oper, ParserVal *v1, ParserVal *v2)
{(is_string(v1) || is_string(v2))
{_boolean_str(oper, v1, v2);;
}_convert_to_numeric(v1);_convert_to_numeric(v2);(oper)
{
/* v1 == v2 */TOK_EQ:->d = (v1->d == v2->d);;
/* v1 > v2 */TOK_GT:->d = (v1->d > v2->d);;
/* v1 >= v2 */TOK_GE:->d = (v1->d >= v2->d);;
/* v1 < v2 */TOK_LT:->d = (v1->d < v2->d);;
/* v1 <= v2 */TOK_LE:->d = (v1->d <= v2->d);;
/* v1 && v2 */TOK_AND:(v1->d == 0.0 || v2->d == 0.0)
{
/* Set v1 to zero (FALSE) */->d = 0.0;
};
/* v1 || v2 */TOK_OR:(v1->d == 0.0)
{
/* Copy v2 to v1 */->d = v2->d;
};
}
}do_math(int oper, ParserVal *v1, ParserVal *v2)

{(oper == '+')
{(is_string(v1) || is_string(v2))
{_add_strings(v1, v2);
}
{->d = v1->d + v2->d;
};
}((is_string(v1) || is_string(v2)))
{->error

parser_format_string("

'%c'.", oper);
return;
}_convert_to_numeric(v1);_convert_to_numeric(v2);(oper)
{'-':->d = v1->d - v2->d;;'*':->d = v1->d * v2->d;;'/':(v2->d != 0.0)->d
= v1->d / v2->d;
{->error = parser_format_string(" .");
};
}
}do_power(ParserVal *v1, ParserVal *v2)
{_convert_to_numeric(v1);_convert_to_numeric(v2);(is_numeric(v1)
&& is_numeric(v2))
{d = v1->d;i;(i=1; i<(long)v2->d; i++) v1->d *= d;
}
{->error

parser_format_string("

'^'.");
}
}do_unary(int oper, ParserVal *v)
{_convert_to_numeric(v);(!is_numeric(v))
{>error = parser_format_string("

'%c' .", oper);;


}>d = -v->d;
}is_numeric(ParserVal *v)
{v->type == TOK_NUMERIC;
}is_string(ParserVal *v)
{v->type == TOK_STRING;
}parser_convert_to_numeric(ParserVal *v)
{(v->type == TOK_NUMERIC) return;
/* ATM we do not convert string to numeric value */
}parser_convert_to_string(ParserVal *v)
{
/* */
if (v->type == TOK_STRING) return;
/* Value as string picture */*p = parser_value_show_as_string(v);>s =
(char*)

calloc(MAX_NUMERIC_LEN,

sizeof(char));_t

len

min(parser_strlen(p), MAX_NUMERIC_LEN-1);(len)(v->s, p, len);


*(v->s + len) = '\0';>type = TOK_STRING;
}*parser_value_show_as_string(ParserVal *v)
{
/*

Static

char

buffer,

return

pointer

to

it

*/char

buf[MAX_TOKEN_LEN];
/* ? */(v->type == TOK_STRING)
{_t len = min(parser_strlen(v->s), MAX_TOKEN_LEN);(buf, v->s,
len);
*(buf + len) = '\0';buf;
}
/* */ceil_diff = ceil(v->d) - v->d;floor_diff = v->d -

floor(v->d);diff, res;(ceil_diff < floor_diff)


{= ceil_diff;= ceil(v->d);
}
{= floor_diff;= floor(v->d);
}(diff < 0.0009)(buf, "%ld", (long)res); /* */
else(buf, "%.3f", v->d); /*
*/
return buf;
}parser_value_as_numeric(ParserVal *v)
{(v->type == TOK_NUMERIC)v->d;0.0;
}*parser_value_as_string(ParserVal *v)
{
/* Do not free the value.points to a static char buffer.
*/parser_value_show_as_string(v);
}parser_value_as_boolean(ParserVal *v)
{(v->type

==

TOK_NUMERIC)(int)v->d

""))TRUE;(str_icmp(v->s,

!=

0;(str_icmp(v->s,

"1"))TRUE;(str_icmp(v->s,

""))FALSE;(str_icmp(v->s, "0"))FALSE;FALSE;
}parser_add_strings(ParserVal *v1, ParserVal *v2)
{_convert_to_string(v1);_convert_to_string(v2);
size_t len1 = min(parser_strlen(v1->s), MAX_TOKEN_LEN);_t len2
= min(parser_strlen(v2->s), MAX_TOKEN_LEN);
char *p = (char*)calloc(len1 + len2 + 1, sizeof(char));(len1)(p, v1->s,
len1);(len2)(p + len1, v2->s, len2);
*(p + len1 + len2) = '\0';(v1->s);->s = p;
}
/* ************************** */

/* Numeric and string values */


/*

**************************

*/parser_value_set_to_numeric(ParserVal *v, double d)


{_value_free(v);_value_init_to_numeric(v, d);
}parser_value_set_to_string(ParserVal *v, char *s)
{_value_free(v);_value_init_to_string(v, s);
}parser_value_init_to_numeric(ParserVal *v, double d)
{>d = d;>type = TOK_NUMERIC;>error = NULL;
}parser_value_init_to_string(ParserVal *v, char *s)
{_t

len

min(parser_strlen(s),

MAX_TOKEN_LEN);>s

(char*)calloc(len + 1, sizeof(char));(len)(v->s, s, len);


*(v->s + len) = '\0';>type = TOK_STRING;>error = NULL;
}parser_value_free(ParserVal *v)
{_value_delete(v);
}parser_value_copy(ParserVal *from_v, ParserVal *to_v)
{
*to_v = *from_v;(from_v->type != TOK_STRING) return;_t len =
min(parser_strlen(from_v->s),

MAX_TOKEN_LEN);_v->s

calloc(len + 1, sizeof(char));(len)(to_v->s, from_v->s, len);


*(to_v->s+len) = '\0';
}parser_value_delete(ParserVal *v)
{(v->type == TOK_STRING)
{
/* Free string value */(v->s) free(v->s);>s = NULL;
}
/* Free error */(v->error) free(v->error);>error = NULL;
/*it keep the type.

=(char*)

*/
}do_sqrt(ParserVal *v, int arg_count)
{
/* Return sqrt(v[0]) in v[0] */[0].d = sqrt(v[0].d);
}do_abs(ParserVal *v, int arg_count)
{
/* Return abs(v[0]) in v[0]. */[0].d = fabs(v[0].d);
}do_exp(ParserVal *v, int arg_count)
{
/* Return exp(v[0]) in v[0]. */[0].d = exp(v[0].d);
}do_ln(ParserVal *v, int arg_count)
{
/* Return log(v[0]) in v[0]. */[0].d = log(v[0].d);
}do_pow(ParserVal *v, int arg_count)
{
/* Return pow(v[0], v[1]) in v[0]. */[0].d = pow(v[0].d, v[1].d);
}do_integer(ParserVal *v, int arg_count)
{
/* Return integer (whole part of) v[0] in v[0]. */(v[0].d, &v[0].d/*int
part*/);
}do_fraction(ParserVal *v, int arg_count)
{
/* Return fraction (decimal part of) v[0] in v[0]. */int_part;
[0].d/*fraction*/ = modf(v[0].d, &int_part);
}do_round(ParserVal *v, int arg_count)
{
/* Round v[0] to nearest n decimal. n = {0...10}.[1] contains n.

Returns the rounded value in v[0].


*/
/*

TODO:

Find

better

way

to

do

this

*/char

buf[MAX_NUMERIC_LEN];char format[MAX_NUMERIC_LEN];
sprintf(format, "%%.%df", (int)v[1].d);(buf, format, v[0].d);
v[0].d = atof(buf);
}*lookup_builtin_function(char *name)
{i;(i=0; i< sizeof(g_function_table)/sizeof(g_function_table[0]); i++)
{(!strcmp(g_function_table[i].name, name))&g_function_table[i];
}NULL;
}execute_builtin_function(CodeBuffer *cb, BuiltinFunction *func)
{v[MAX_FUNC_ARGS];i;(i=0;

i<

MAX_FUNC_ARGS;

i+

+)_value_init_to_numeric(&v[i], 0.0);(!func) return v[0];arg_count = 0;


(func->num_args)
{[arg_count] = parser_bool1(cb);_count++;(arg_count >= func>num_args || arg_count >= MAX_FUNC_ARGS) break;(func->num_args
== (int)'*')
{(currToken.type == ',')
{
/* Removed comma */
; /* ok */
}if (currToken.type == ')')
{;
}
{[0].error = parser_format_string("Missing ',' or ')' at function%s.",
func->name);v[0];
}

}
{
/* Remove comma between expressions */(currToken.type !=
TOK_COMMA)
{*p

builtin_function_arg_text(func);[0].error

parser_format_string("Missing ',' at function%s. Function%s takes%s


arguments.", func->name, func->name, p);(p);v[0];
}
}
/* Next token */_get_token(cb, &currToken);
}(arg_count == 0)
{*p

builtin_function_arg_text(func);[0].error

parser_format_string("

. %s %s

().", func->name, p);(p);v[0];


}>func(v, arg_count);v[0];
}*builtin_function_arg_text(BuiltinFunction *func)
{*p;(func->num_args

==

'*')=

parser_format_string("%d",

MAX_FUNC_ARGS);= parser_format_string("%d", func->num_args);


/* You should free() the value after usage */p;
}*parser_copy_string(char *s)
{_t

len

min(parser_strlen(s),

MAX_TOKEN_LEN);*tmp

(char*)calloc(len+1, sizeof(char));(len)(tmp, s, len);


*(tmp+len) = '\0';tmp;
}*parser_quote_string(char *s)
{_t len = min(parser_strlen(s), MAX_TOKEN_LEN);*tmp;(len > 0
&& (*s == '"' || *s == '\''))
{parser_copy_string(s);

}=(char*) calloc(len + 3/* " + \0 + " */, sizeof(char));


*tmp = '"';(len)(tmp+1, s, len);
*(tmp+len+1) = '"';
*(tmp+len+2) = '\0';tmp;
}_t parser_strlen(char *s)
{(!s) return (size_t)0;strlen(s);
}*parser_format_string(const char *fmt,...)
{*msg

(char*)calloc(MAX_TOKEN_LEN,

sizeof(char));_list

args;_start(args, fmt);(msg, fmt, args);_end(args);msg;


}parser_error(CodeBuffer *cb, char *msg, int opt)
{buffer[1024];(opt && cb)(buffer, " %d:
%s\n", lexer_line_num(cb), msg);(buffer, " %s\n", msg);>RichEdit1->Lines->Add(buffer);
}
/* */parser_variable_add_value(CodeBuffer *cb, char
*name, ParserVal *value)
{(value->type == TOK_STRING)_variable_add_string_var(cb, name,
value->s, FALSE/*quoted*/);_variable_add_numeric_var(cb, name, value>d);
}parser_variable_add_numeric_var(CodeBuffer *cb, char *name,
double val)
{(!(cb

&&

name))

return;*var

parser_variable_create_new(name);_value_init_to_numeric(&var->val,
val);_variable_add_to_list(cb->variable_list, var);
}parser_variable_add_string_var(CodeBuffer *cb, char *name, char
*val, int quoted)
{(!(cb && name)) return;*var = parser_variable_create_new(name);

/* "" ? */(quoted)
{*tmp = parser_quote_string(val);_value_init_to_string(&var->val,
tmp);(tmp);
}_value_init_to_string(&var->val,

val);_variable_add_to_list(cb-

>variable_list, var);
}parser_variable_add_standard_constants(CodeBuffer *cb)
{(!cb) return;
}**parser_variable_create_list()
{
/* */**list;
list

(ParserVariable

**)calloc(MAX_VARIABLE_LIST_LEN,

sizeof(ParserVariable));list;
}*parser_variable_create_new(char *name)
{*var = (ParserVariable *)calloc(1, sizeof(ParserVariable));>name =
parser_format_string("%s", name);
/*

0.0

(TOK_NUMERIC)

*/_value_init_to_numeric(&var->val, 0.0);var;
}parser_variable_add_to_list(ParserVariable

*variables[],

ParserVariable *var)
{i;= parser_variable_find(variables, var->name);
if (i > -1)
{ /* */
parser_variable_delete(variables[i]);[i] = var;i;
}
/*

MAX_VARIABLE_LIST_LEN; i++)
{(!variables[i])

*/(i

0;

i<

{[i] = var;i;
}
}_error(NULL, " .\n", FALSE);-1;
}parser_variable_find(ParserVariable *variables[], char *name)
{i;(i=0; i< MAX_VARIABLE_LIST_LEN; i++)
{(!variables[i]) break;(!strcmp(name, variables[i]->name)) return i;
}-1;
}parser_variable_print_all(ParserVariable *variables[])
{(!variables) return;_t i;(i=0; i< MAX_VARIABLE_LIST_LEN; i++)
{(!variables[i]) continue;*var = variables[i];(var->val.type)
{TOK_NUMERIC:("%s=%s
parser_value_show_as_string

(numeric).\n",

var->name,

(&var->val));;TOK_STRING:("%s=%s

(string).\n", var->name, var->val.s);;:("%s


%d.\n", var->name, var->val.type);;
}
}
}*parser_variable_get_debug_text(ParserVariable *variables[])
{
/* Return a long string (text) with variable names and values.for
inspection and debugging.
*/(!variables)

return

parser_format_string(":\n");_t

NULL;*text
i;(i=0;

=
i<

MAX_VARIABLE_LIST_LEN; i++)
{(!variables[i]) continue;*var = variables[i];*tmp;= NULL;(var>val.type)
{TOK_NUMERIC:=
var->name,

parser_format_string("%s=%s

(numeric).\n",

parser_value_show_as_string(&var->val));;TOK_STRING:=

parser_format_string("%s=%s

(string).\n",

var->name,

var->val.s);;:=

parser_format_string("%s %d.\n", var>name, var->val.type);;


}(tmp)
{*tmp2 = parser_format_string("%s%s", text, tmp);(text);= tmp2;
}(tmp);
}text;
}parser_variable_delete(ParserVariable *var)
{(!var) return;_value_delete(&var->val);(var->name);>name = NULL;
}parser_variable_delete_all(ParserVariable *variables[])
{(!variables) return;_t i;(i=0; i< MAX_VARIABLE_LIST_LEN; i++)
{_variable_delete(variables[i]);
}(variables);= NULL;
}str_icmp(char *s1, char *s2)
{strcmp(s1, s2);
}
Lexer.cpp
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "lexer.h"
#include

"parser.h"lexer_lookahead_token(CodeBuffer

*cb,

char

*_token, int _remove/* ?*/, int _eat_nl/*


? '\n' ?*/)
{tok;ret = FALSE;(1)
{_get_token(cb,

&tok);(tok.type

==

TOK_EOF)

break;=

(!

strcmp(tok.str, _token));(!ret && (_eat_nl && tok.type == '\n')) continue;(!


ret)
{_put_token_back(cb, &tok);
}
{(!_remove)_put_token_back(cb, &tok);
};
}ret;
}lexer_put_token_back(CodeBuffer *cb, TokenRec *_tokRec)
{(cb->tok_backbuf_count >= MAX_TOKEN_BACKBUF_LEN-1)
{_error(cb, " Token .\n");
}>tok_backbuf[cb->tok_backbuf_count]

*_tokRec;>tok_backbuf_count++;
}lexer_get_token_from_backbuf(CodeBuffer

*cb,

TokenRec

*_tokRec)
{
/* ? */(cb->tok_backbuf_count > 0)
{>tok_backbuf_count--;
*_tokRec = cb->tok_backbuf[cb->tok_backbuf_count];
/* */TRUE;
}
{ /* \0 */
*_tokRec->str = '\0';
_tokRec->type = TOK_EOF;
}
/* */
return FALSE;
}lexer_get_token(CodeBuffer *cb, TokenRec *_tokRec)

{
/* Token */
char ch;ch2 = 0;*cPtr;char buf[MAX_TOKEN_LEN];
/* token */(_tokRec, sizeof(TokenRec), '\0');
*buf = *(buf+1) = *(buf+2) = '\0';
*(_tokRec->str) = *(_tokRec->str+1) = *(_tokRec->str+2) = '\0';
_tokRec->type = TOK_EOF;
/* token */
if (lexer_get_token_from_backbuf(cb, _tokRec))
{_tokRec->type;
}
/* , ,
*/
ch = lexer_get_charEx(cb);
/* */
switch (ch)
{'=':
_tokRec->type = TOK_ASSIGN;
/* == */(lexer_lookahead(cb, '=',1))
_tokRec->type = TOK_EQ;;'+':
/* += */(lexer_lookahead(cb, '=',1))
_tokRec->type = TOK_ASPLUS;
/* ++ */if (lexer_lookahead(cb, '+',1))
_tokRec->type = TOK_INCR;
/* + */
_tokRec->type = TOK_PLUS;;'-':
/* -= */(lexer_lookahead(cb, '=',1))

_tokRec->type = TOK_ASMINUS;
/* -- */if (lexer_lookahead(cb, '-',1))
_tokRec->type = TOK_DECR;
/* - */
_tokRec->type = TOK_MINUS;;'*':
/* *= */(lexer_lookahead(cb, '=',1))
_tokRec->type = TOK_ASMUL;
/* * */
_tokRec->type = TOK_MUL;;'/':
/* /= */(lexer_lookahead(cb, '=',1))
_tokRec->type = TOK_ASDIV;
/* / */
_tokRec->type = TOK_DIV;;'^':
/* ^ */
_tokRec->type = TOK_EXP;;'%':
/*%= (modulus) */(lexer_lookahead(cb, '=',1))
_tokRec->type = TOK_ASMOD;
/*% */
_tokRec->type = TOK_MOD;
break;
}
/* . ? */(_tokRec->type != TOK_EOF)
{
*(_tokRec->str) = ch;
*(_tokRec->str+1) = '\0';
goto l_end;
}

/* ? */(ch == TOK_EOF)
{
_tokRec->type = ch;
goto l_end;
}
/* ? */(ch == ';' || ch == '\n')
{
_tokRec->type = ch;
*(_tokRec->str) = ch;
goto l_end;
}(strchr("(),.{}", ch))
{
/* ) (;., } { */
_tokRec->type = ch;
*(_tokRec->str) = ch;l_end;
}
// = tolower(ch);((ch2 >= 'a' && ch2 <= 'z') ||
strchr("_$", ch))
{
*buf = ch;= buf +1;= lexer_get_char(cb);((isalnum(ch) || strchr("_$",
ch)) && ch != TOK_EOF)
{
*cPtr++ = ch;= lexer_get_char(cb);
}
*cPtr = '\0';
/* */
lexer_put_back(cb, ch);

_tokRec->type

TOK_IDENT;len

min(strlen(buf),

MAX_TOKEN_LEN);(_tokRec->str, buf, len);


*(_tokRec->str + len) = '\0';
}
/* "xxx" 'xxx' */
else if (ch == '"' || ch == '\'')
{chStart = ch;= buf;
ch2 = '\0'; // ".....\"...."
while (1)
{= lexer_get_char(cb);(ch == TOK_EOF) break;
// \" \'(ch == chStart && ch2 != '\\')
{;
}
{= *cPtr;
*cPtr++ = ch;
}
}
*cPtr = '\0';len = min(strlen(buf), MAX_TOKEN_LEN);
strncpy(_tokRec->str, buf, len);
*(_tokRec->str + len) = '\0';
_tokRec->type = TOK_STRING;
}
/* ; 123, 0.51,.67, -2.67, +89, -4e3,
+2e-9*/
else if (strchr("0123456789+-.", ch))
{hasDecimal = 0;hasExp = 0;hasExpSign = 0;= buf;
*cPtr++ = ch;(ch == '.') { hasDecimal = 1; }

/* :
.67, -2.67, +89, -4e3, +2e-9
*/
/* 0x7FCD
0XA. */is_hex = FALSE;(ch == '0')
{_hex = lexer_lookahead(cb, 'x', 1/**/);(!is_hex)_hex =
lexer_lookahead(cb, 'X', 1/**/);
}
/* 'x' "0x" */
if (is_hex)
*cPtr++ = 'x';int count = 0;/* */(1)
{= lexer_get_char(cb);(ch == TOK_EOF) break;(ch == '.' && !
hasDecimal)
{
*cPtr++ = ch;= 1;
}if ((ch == 'e' || ch == 'E') && !hasExp)
{
*cPtr++ = ch;= 1;
}if (strchr("+-", ch) && hasExp && (!hasExpSign))
{
*cPtr++ = ch;= ch;
}if (strchr("0123456789", ch))
{
*cPtr++ = ch;
}if (is_hex && strchr("ABCDEFabcdef", ch))
{
*cPtr++ = ch;

};(count++ > MAX_TOKEN_LEN) break;


}
/* */
lexer_put_back(cb, ch);
*cPtr = '\0';d = atof(buf);
_tokRec->type = TOK_NUMERIC;
/* */
int len = min(strlen(buf), MAX_TOKEN_LEN);
strncpy(_tokRec->str, buf, len);
*(_tokRec->str + len) = '\0';(hasDecimal || hasExpSign == (int)'-')
{
_tokRec->val.d = d;
}
{
/* */
_tokRec->val.d = (long)d;
}
} /* */
{
/* . */
_tokRec->type = TOK_EOF;
}_end:
/* token (*_tokRec)
*/
_tokRec->line_num = lexer_line_num(cb);_tokRec->type;
}lexer_line_num(CodeBuffer *cb)
{cb->line_num;

}lexer_put_back(CodeBuffer *cb, char _ch)


{_t

len

strlen(cb->char_backbuf);(len

MAX_CHAR_BACKBUF_LEN - 1)
{
*(cb->char_backbuf + len) = _ch;
*(cb->char_backbuf + len+1) = '\0';
}
{_error(cb, " Parser' .");
}
}lexer_remove_line(CodeBuffer *cb)
{ch = lexer_get_char(cb);(ch != TOK_EOF && ch != '\n')
{= lexer_get_char(cb);
}_put_back(cb, ch);
}lexer_get_charEx(CodeBuffer *cb)
{ch;ch2;move;= lexer_get_char(cb);(ch != TOK_EOF)
{= 0;
/* */(isspace(ch))
{= lexer_get_char(cb);
}
/* '#' */
if (ch == '#')
{_remove_line(cb);= lexer_get_char(cb);
}
/* ()? */(ch == '\n' || ch == ';')
{ch;
}
/* */(isspace(ch))

<

{= lexer_get_char(cb);
}
/* '/ *'
*/
if (ch == '/')
{= lexer_get_char(cb);
if (ch2 == '/')
{
/* */
ch = lexer_get_char(cb);(ch != TOK_EOF && ch != '\n')
{= lexer_get_char(cb);
}= 1;
}if (ch2 == '*')
{count = 1; // /* /* /*... */ */ */=
lexer_get_char(cb);= 0;(ch != TOK_EOF)
{
// '*/'(ch == '/' && ch2 == '*')
{(--count <= 0)
{= 1;;
}
}
// /*
else if (ch == '*' && ch2 == '/')
{++;
}if (ch == '\n'|| ch == '\r')
{
;

}
/* */= ch;= lexer_get_char(cb);
}(ch == TOK_EOF && count)
{_error(cb, " /*... */ ");
}
}
{_put_back(cb, ch2);
}
}(move)= lexer_get_char(cb);;
}ch;
}lexer_lookahead(CodeBuffer *cb, int _match_ch, int _remove)
{ret;ch = lexer_get_charEx(cb);(ch == _match_ch)
{(!_remove) lexer_put_back(cb, ch);= 1;
}
{_put_back(cb, ch);= 0;
}ret;
}lexer_get_char(CodeBuffer *cb)
{ch = TOK_EOF;
/* */
if (cb->char_backbuf[0] != '\0')
{_t len = strlen(cb->char_backbuf);= *(cb->char_backbuf + len - 1);
*(cb->char_backbuf + len-1) = '\0';ch;
}(!cb->text)TOK_EOF;if (*(cb->text + cb->curr_pos) == TOK_EOF)
{TOK_EOF;
}= *(cb->text + cb->curr_pos);(ch == '\n')>line_num++;>curr_pos+
+;ch;
}lexer_error(CodeBuffer *cb, char *_msg)

{(stderr, " :%s.%s\n", (cb->name ? cb->name :


""), _msg);
}lexer_match(char *tok1, char *tok2)
{(!(tok1 && tok2)) return FALSE;
size_t len1 = strlen(tok1);_t len2 = strlen(tok2);(len2 < len1)
/*

token,

lexer_match("abcd", "ab") => TRUE */


return !strncmp(tok1, tok2, len2);
else
/* Token */
return !strcmp(tok1, tok2);
}*lexer_codebuffer_new(char *code)
{*cb = (CodeBuffer *)calloc(1, sizeof(CodeBuffer));
lexer_codebuffer_init(cb);
/* */
size_t len = min(strlen(code), 40960);
if (len)
{>text =(char*) calloc(len+1, sizeof(char));(cb->text, code, len);
}cb;
}lexer_codebuffer_init(CodeBuffer *cb)
{>text = cb->name = NULL;>curr_pos = 0;>line_num = 1;(cb>char_backbuf, '\0', MAX_CHAR_BACKBUF_LEN);
/* Token */>tok_backbuf_count = 0;
/*

(MAX_VARIABLE_LIST_LEN) */
cb->variable_list = parser_variable_create_list();
}lexer_codebuffer_destroy(CodeBuffer *cb)

{(!cb) return;
/* */
free(cb->text);
free(cb->name);>curr_pos = 0;->line_num = 1;
/* */
parser_variable_delete_all(cb->variable_list);>variable_list = NULL;
(cb->char_backbuf, '\0', MAX_CHAR_BACKBUF_LEN);
/* Token */>tok_backbuf_count = 0;
}

4.
:
a=sqrt(36)=abs(-6)=2^2=exp(30)=ln(10)(a)(b)(c)(d)
(e)=3.4+2.6(f)=a+b*c-d/e*f(g)

:6
:6
:4
:1.06865e+13
:2.30259
:6
:-2.78465e+13



-
, .


1. .., .., .., ..
. .: -, 2003.- 296 .
2.

.., .., .., ..

. , 2000. -115.
.

. . - .: , 1988.

- 448 .
4. .. - .:
, 2003 .