class
Token:
def
__init__(
self
,
type
, value
=
None
):
self
.
type
=
type
self
.value
=
value
class
Lexer:
def
__init__(
self
, text):
self
.text
=
text
self
.pos
=
0
def
get_next_token(
self
):
if
self
.pos >
=
len
(
self
.text):
return
Token(
"EOF"
)
current_char
=
self
.text[
self
.pos]
if
current_char.isalpha():
identifier
=
""
while
self
.pos <
len
(
self
.text)
and
self
.text[
self
.pos].isalnum():
identifier
+
=
self
.text[
self
.pos]
self
.pos
+
=
1
return
Token(
"IDENTIFIER"
, identifier)
if
current_char.isdigit():
self
.pos
+
=
1
return
Token(
"NUMBER"
,
int
(current_char))
if
current_char
in
"+-*/"
:
self
.pos
+
=
1
return
Token(
"OPERATOR"
, current_char)
if
current_char
=
=
"="
:
self
.pos
+
=
1
return
Token(
"ASSIGN"
,
"="
)
if
current_char
=
=
";"
:
self
.pos
+
=
1
return
Token(
"SEMICOLON"
,
";"
)
if
current_char
=
=
"("
:
self
.pos
+
=
1
return
Token(
"LPAREN"
,
"("
)
if
current_char
=
=
")"
:
self
.pos
+
=
1
return
Token(
"RPAREN"
,
")"
)
if
current_char
in
" \t"
:
self
.pos
+
=
1
return
self
.get_next_token()
raise
ValueError(
"Invalid character"
)
class
Parser:
def
__init__(
self
, lexer):
self
.lexer
=
lexer
self
.current_token
=
self
.lexer.get_next_token()
self
.variables
=
{}
def
parse(
self
):
results
=
[]
while
self
.current_token.
type
!
=
"EOF"
:
result
=
self
.parse_statement()
results.append(result)
if
self
.current_token.
type
=
=
"SEMICOLON"
:
self
.eat(
"SEMICOLON"
)
return
results
def
parse_statement(
self
):
if
self
.current_token.
type
=
=
"IDENTIFIER"
:
variable_name
=
self
.current_token.value
self
.eat(
"IDENTIFIER"
)
self
.eat(
"ASSIGN"
)
expression_value
=
self
.parse_expression()
self
.variables[variable_name]
=
expression_value
return
expression_value
elif
self
.current_token.
type
=
=
"SEMICOLON"
:
self
.eat(
"SEMICOLON"
)
return
None
else
:
return
self
.parse_expression()
def
parse_expression(
self
, min_precedence
=
0
):
left
=
self
.parse_atom()
while
self
.current_token.
type
=
=
"OPERATOR"
and
self
.precedence(
self
.current_token.value) >
=
min_precedence:
operator
=
self
.current_token.value
self
.eat(
"OPERATOR"
)
right
=
self
.parse_expression(
self
.precedence(operator)
+
1
)
left
=
self
.apply_operator(left, operator, right)
return
left
def
parse_atom(
self
):
if
self
.current_token.
type
=
=
"NUMBER"
:
value
=
self
.current_token.value
self
.eat(
"NUMBER"
)
return
value
elif
self
.current_token.
type
=
=
"IDENTIFIER"
:
variable_name
=
self
.current_token.value
self
.eat(
"IDENTIFIER"
)
if
variable_name
in
self
.variables:
return
self
.variables[variable_name]
else
:
raise
ValueError(f
"Undefined variable: {variable_name}"
)
elif
self
.current_token.
type
=
=
"LPAREN"
:
self
.eat(
"LPAREN"
)
expression
=
self
.parse_expression()
self
.eat(
"RPAREN"
)
return
expression
else
:
raise
ValueError(
"Invalid syntax"
)
def
eat(
self
, token_type):
if
self
.current_token.
type
=
=
token_type:
self
.current_token
=
self
.lexer.get_next_token()
else
:
raise
ValueError(
"Unexpected token"
)
def
precedence(
self
, operator):
precedence
=
{
"+"
:
1
,
"-"
:
1
,
"*"
:
2
,
"/"
:
2
}
return
precedence.get(operator,
0
)
def
apply_operator(
self
, left, operator, right):
if
operator
=
=
"+"
:
return
left
+
right
elif
operator
=
=
"-"
:
return
left
-
right
elif
operator
=
=
"*"
:
return
left
*
right
elif
operator
=
=
"/"
:
return
left
/
right
def
calculate(expression):
lexer
=
Lexer(expression)
parser
=
Parser(lexer)
results
=
parser.parse()
return
results
expression
=
"x = 3 * (4-1); y = 2*x + 2;"
results
=
calculate(expression)
print
(results)