in Iris/IrisCompiler/FrontEnd/Translator.cs [384:561]
protected void ParseStatement(bool allowEmpty = false)
{
FilePosition statementStart = _lexer.TokenStartPosition;
MethodGenerator.BeginSourceLine(statementStart);
if (Accept(Token.KwFor))
{
Symbol iterator;
FilePosition fp = _lexer.TokenStartPosition;
if (!Accept(Token.Identifier))
{
AddError(fp, "Expecting integer identifier.");
SkipStatement();
return;
}
// Initial assignment
iterator = LookupSymbol(fp, _lexeme);
VerifyExpressionType(fp, DerefType(iterator.Type), IrisType.Integer);
bool byRef = iterator.Type.IsByRef;
if (byRef)
EmitLoadSymbol(iterator, SymbolLoadMode.Raw);
Expect(Token.ChrAssign);
fp = _lexer.TokenStartPosition;
IrisType rhs = ParseExpression();
VerifyExpressionType(fp, rhs, IrisType.Integer);
if (byRef)
MethodGenerator.Store(rhs);
else
EmitStoreSymbol(iterator);
Expect(Token.KwTo);
// Loop start and condition
int loopLabel = GetNextLabel();
MethodGenerator.Label(loopLabel);
EmitLoadSymbol(iterator, SymbolLoadMode.Dereference);
fp = _lexer.TokenStartPosition;
rhs = ParseExpression();
VerifyExpressionType(fp, rhs, IrisType.Integer);
int exitLabel = GetNextLabel();
MethodGenerator.BranchCondition(Operator.GreaterThan, exitLabel);
// Loop body
Expect(Token.KwDo);
FilePosition forEndPosition = _lastParsedPosition;
MethodGenerator.EndSourceLine(forEndPosition);
ParseStatement();
// Loop end
MethodGenerator.BeginSourceLine(statementStart); // Source position is the same as the loop start.
Increment(iterator);
MethodGenerator.Goto(loopLabel);
MethodGenerator.Label(exitLabel);
MethodGenerator.EndSourceLine(forEndPosition);
}
else if (Accept(Token.KwWhile))
{
int loopLabel = GetNextLabel();
MethodGenerator.Label(loopLabel);
FilePosition fp = _lexer.TokenStartPosition;
IrisType type = ParseExpression();
VerifyExpressionType(fp, type, IrisType.Boolean);
int exitLabel = GetNextLabel();
MethodGenerator.BranchFalse(exitLabel);
Expect(Token.KwDo);
MethodGenerator.EndSourceLine(_lastParsedPosition);
ParseStatement();
MethodGenerator.Goto(loopLabel);
MethodGenerator.Label(exitLabel);
}
else if (Accept(Token.KwRepeat))
{
int loopLabel = GetNextLabel();
MethodGenerator.Label(loopLabel);
MethodGenerator.EmitNonCodeLineInfo(new SourceRange(statementStart, _lastParsedPosition));
ParseStatements(Token.KwUntil);
FilePosition fp = _lexer.TokenStartPosition;
IrisType type = ParseExpression();
VerifyExpressionType(fp, type, IrisType.Boolean);
MethodGenerator.BranchFalse(loopLabel);
MethodGenerator.EndSourceLine(_lastParsedPosition);
}
else if (Accept(Token.KwIf))
{
ParseIf();
}
else if (Accept(Token.KwBegin))
{
MethodGenerator.EmitNonCodeLineInfo(new SourceRange(statementStart, _lastParsedPosition));
ParseStatements(Token.KwEnd);
}
else if (Accept(Token.Identifier))
{
FilePosition fp = _lexer.TokenStartPosition;
string symbolName = _lexeme;
Symbol symbol = LookupSymbol(fp, symbolName);
IrisType lhs = symbol.Type;
bool assign = false;
bool isArray = false;
if (Accept(Token.ChrOpenBracket))
{
// Assignment to an array element.
isArray = true;
lhs = ProcessArrayAccess(fp, symbol, SymbolLoadMode.Raw);
}
if (Accept(Token.ChrAssign))
{
assign = true;
bool indirectAssign = false;
if (lhs.IsByRef)
{
lhs = lhs.GetElementType();
EmitLoadSymbol(symbol, SymbolLoadMode.Raw);
indirectAssign = true;
}
FilePosition exprPosition = _lexer.TokenStartPosition;
IrisType rhs = ParseExpression();
if (lhs.IsMethod)
{
AddError(fp, "Cannot assign to result of function or procedure call.");
}
else if (lhs != IrisType.Invalid)
{
if (rhs == IrisType.Void)
AddError(fp, "Cannot use procedure in assignment statement.");
else if (rhs != IrisType.Invalid && rhs != lhs)
AddError(exprPosition, string.Format("Cannot assign to '{0}' (type mismatch error).", symbolName));
if (isArray)
MethodGenerator.StoreElement(lhs);
else if (indirectAssign)
MethodGenerator.Store(lhs);
else
EmitStoreSymbol(symbol);
}
}
else if (isArray)
{
// This is an array subscript. Assignment is the only kind of statement that
// starts with an array subscript.
AddErrorAtTokenStart("Expecting ':='.");
SkipStatement();
}
if (!assign && !isArray)
{
bool skipArgList = !Accept(Token.ChrOpenParen);
ProcessCall(fp, symbol, skipArgList);
if (symbol.Type.IsFunction)
MethodGenerator.Pop();
}
MethodGenerator.EndSourceLine(_lastParsedPosition);
}
else if (Accept(Token.KwElse))
{
AddErrorAtTokenStart("Cannot start statement with 'else' or unexpected ';' after if statement.");
SkipStatement();
}
else if (!allowEmpty && !Accept(Token.ChrSemicolon))
{
AddErrorAtLastParsedPosition("Expecting statement.");
SkipStatement();
}
}