In this chapter, we will build on mul.pb, so make a copy of it (name it "parens.pb").
To have the same source as I do, search and replace ecx into ebp.
Here is the old grammar:
digit ::= 0..9
integer ::= <digit> {<digit>}
value ::= <integer>
mulop ::= * | /
addop ::= + | -
mulexp ::= <value> { <mulop> <value> }
addexp ::= <mulexp> { <addop> <mulexp> }
expression ::= <addexp>
What does value() do? It puts a value in eax.
What does expression() do? It puts a value in eax.
What is inside a parenthesis? Is it not just another ordinary expression? Yes.
So, why not do it like this?
value ::= <integer> | '(' <expression> ')'
That's what we are going to do. Change Value() into this:
Declare Expression()
Procedure Value()
; value ::= <integer> | '(' <expression> ')'
If IsDigit(Look)
Emit("mov eax, " + GetInteger())
ElseIf Look = '('
MatchWhite('(')
Expression()
MatchWhite(')')
EndIf
EndProcedure
We had to forward declare Expression() to avoid an error message (since it's defined later in the source code). Also you can see two calls to a new function here: MatchWhite(). What it does is to verify that Look is a certain character, discard Look, and then eat any following whitespace. Here's the implementation, put it in base2.pb:
Procedure Match(C.c)
If Look <> C
Expected(Chr(C))
EndIf
GetLook()
EndProcedure
Procedure MatchWhite(C.c)
Match(C)
EatWhite()
EndProcedure
Now that was simple, right? Unfortunately it's not quite right just yet. Currently Expression() gives an error message if it does not reach the end of the line. We must change that. Here is the entire code, with the end of line check moved out of Expression():
; paren.pb
IncludeFile "..\base2.pb"
; Procedure.s VarRef(Var.s)
; ProcedureReturn "[v_" + Var + "]"
; EndProcedure
Declare Expression()
Procedure Value()
; value ::= <integer> | '(' <expression> ')'
If IsDigit(Look)
Emit("mov eax, " + GetInteger())
ElseIf Look = '('
MatchWhite('(')
Expression()
MatchWhite(')')
EndIf
EndProcedure
Procedure MulExp()
; mulexp ::= <value> {* <value>}
Value()
While Look = '*'
GetLookWhite()
Emit("push eax")
Value()
Emit("pop ebp")
Emit("imul eax, ebp")
Wend
EndProcedure
Procedure AddExp()
; addexp ::= <mulexp> {+ <mulexp> }
MulExp()
While Look = '+'
GetLookWhite()
Emit("push eax")
MulExp()
Emit("pop ebp")
Emit("add eax, ebp")
Wend
EndProcedure
Procedure Expression()
; expression ::= <AddExp>
AddExp()
EndProcedure
Init()
Expression()
If Look <> 0
Expected("End of line")
EndIf
Input()
No comments:
Post a Comment