mirror of
https://github.com/dbalsom/x86_microcode.git
synced 2026-06-23 13:17:20 +03:00
Initial 80386 microcode commit.
This commit is contained in:
@@ -0,0 +1,989 @@
|
||||
#include "alfe/main.h"
|
||||
|
||||
#ifndef INCLUDED_STATEMENT_H
|
||||
#define INCLUDED_STATEMENT_H
|
||||
|
||||
#include "alfe/parse_tree_object.h"
|
||||
|
||||
template<class T> class StatementT;
|
||||
typedef StatementT<void> Statement;
|
||||
|
||||
template<class T> class IdentifierT;
|
||||
typedef IdentifierT<void> Identifier;
|
||||
|
||||
class ExpressionStatement;
|
||||
|
||||
template<class T> class FunctionDefinitionStatementT;
|
||||
typedef FunctionDefinitionStatementT<void> FunctionDefinitionStatement;
|
||||
|
||||
class CompoundStatement;
|
||||
|
||||
class TycoDefinitionStatement;
|
||||
|
||||
class NothingStatement;
|
||||
|
||||
class IncrementDecrementStatement;
|
||||
|
||||
class ConditionalStatement;
|
||||
|
||||
class SwitchStatement;
|
||||
|
||||
class ReturnStatement;
|
||||
|
||||
class IncludeStatement;
|
||||
|
||||
template<class T> class BreakOrContinueStatementT;
|
||||
typedef BreakOrContinueStatementT<void> BreakOrContinueStatement;
|
||||
|
||||
class ForeverStatement;
|
||||
|
||||
class WhileStatement;
|
||||
|
||||
class ForStatement;
|
||||
|
||||
template<class T> class LabelStatementT;
|
||||
typedef LabelStatementT<void> LabelStatement;
|
||||
|
||||
class GotoStatement;
|
||||
|
||||
class Context
|
||||
{
|
||||
public:
|
||||
virtual ~Context() { }
|
||||
};
|
||||
|
||||
template<class T> class StatementT : public ParseTreeObject
|
||||
{
|
||||
public:
|
||||
static Statement parse(CharacterSource* source)
|
||||
{
|
||||
Statement statement = ExpressionStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = FunctionDefinitionStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = ExpressionStatement::parseAssignment(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = CompoundStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = TycoDefinitionStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = NothingStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = IncrementDecrementStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = ConditionalStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = SwitchStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = ReturnStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = IncludeStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = BreakOrContinueStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = ForeverStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = WhileStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = ForStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
statement = LabelStatement::parse(source);
|
||||
if (statement.valid())
|
||||
return statement;
|
||||
return GotoStatement::parse(source);
|
||||
}
|
||||
static Statement parseOrFail(CharacterSource* source)
|
||||
{
|
||||
Statement statement = parse(source);
|
||||
if (!statement.valid())
|
||||
source->location().throwError("Expected statement");
|
||||
return statement;
|
||||
}
|
||||
StatementT() { }
|
||||
void resolve(Scope* scope) { body()->resolve(scope); }
|
||||
protected:
|
||||
StatementT(Handle other) : ParseTreeObject(other) { }
|
||||
|
||||
class Body : public ParseTreeObject::Body
|
||||
{
|
||||
public:
|
||||
Body(const Span& span) : ParseTreeObject::Body(span) { }
|
||||
virtual void resolve(Scope* scope) = 0;
|
||||
};
|
||||
|
||||
Body* body() { return as<Body>(); }
|
||||
};
|
||||
|
||||
class ExpressionStatement : public Statement
|
||||
{
|
||||
public:
|
||||
ExpressionStatement(Expression expression, Span span)
|
||||
: ExpressionStatement(create<Body>(expression, span)) { }
|
||||
|
||||
static ExpressionStatement parse(CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
Expression expression = Expression::parse(&s);
|
||||
if (!expression.valid())
|
||||
return ExpressionStatement();
|
||||
Span span;
|
||||
if (!Space::parseCharacter(&s, ';', &span))
|
||||
return ExpressionStatement();
|
||||
*source = s;
|
||||
if (!expression.mightHaveSideEffect())
|
||||
source->location().throwError("Statement has no effect");
|
||||
return ExpressionStatement(expression, expression.span() + span);
|
||||
}
|
||||
|
||||
static ExpressionStatement parseAssignment(CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
Expression left = Expression::parse(&s);
|
||||
Location operatorLocation = s.location();
|
||||
if (!left.valid())
|
||||
return ExpressionStatement();
|
||||
Span span;
|
||||
|
||||
static const Operator ops[] = {
|
||||
OperatorAssignment(), OperatorAddAssignment(),
|
||||
OperatorSubtractAssignment(), OperatorMultiplyAssignment(),
|
||||
OperatorDivideAssignment(), OperatorModuloAssignment(),
|
||||
OperatorShiftLeftAssignment(), OperatorShiftRightAssignment(),
|
||||
OperatorBitwiseAndAssignment(), OperatorBitwiseOrAssignment(),
|
||||
OperatorBitwiseXorAssignment(), OperatorPowerAssignment(),
|
||||
Operator()};
|
||||
|
||||
const Operator* op;
|
||||
for (op = ops; op->valid(); ++op)
|
||||
if (Space::parseOperator(&s, op->toString(), &span))
|
||||
break;
|
||||
if (!op->valid())
|
||||
return ExpressionStatement();
|
||||
|
||||
*source = s;
|
||||
Expression right = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
|
||||
return ExpressionStatement(FunctionCallExpression::binary(*op, span,
|
||||
FunctionCallExpression::unary(OperatorAmpersand(), Span(), left),
|
||||
right), left.span() + span);
|
||||
}
|
||||
private:
|
||||
ExpressionStatement() { }
|
||||
ExpressionStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Expression& expression, const Span& span)
|
||||
: Statement::Body(span), _expression(expression) { }
|
||||
void resolve(Scope* scope) { _expression.resolve(scope); }
|
||||
private:
|
||||
Expression _expression;
|
||||
};
|
||||
};
|
||||
|
||||
class FromStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static FromStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "from", &span))
|
||||
return FromStatement();
|
||||
Expression dll = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
return create<Body>(dll, span);
|
||||
}
|
||||
private:
|
||||
FromStatement() { }
|
||||
FromStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Expression& expression, const Span& span)
|
||||
: Statement::Body(span), _expression(expression) { }
|
||||
void resolve(Scope* scope) { _expression.resolve(scope); }
|
||||
private:
|
||||
Expression _expression;
|
||||
};
|
||||
};
|
||||
|
||||
template<class T> class FunctionDefinitionStatementT : public Statement
|
||||
{
|
||||
public:
|
||||
static FunctionDefinitionStatement parse(CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
TycoSpecifier returnTypeSpecifier = TycoSpecifier::parse(&s);
|
||||
if (!returnTypeSpecifier.valid())
|
||||
return FunctionDefinitionStatement();
|
||||
Identifier name = Identifier::parse(&s);
|
||||
if (!name.valid())
|
||||
return FunctionDefinitionStatement();
|
||||
Span span;
|
||||
if (!Space::parseCharacter(&s, '('))
|
||||
return FunctionDefinitionStatement();
|
||||
*source = s;
|
||||
List<VariableDefinitionT<T>> parameterList =
|
||||
parseParameterList(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
Statement body = FromStatement::parse(source);
|
||||
if (!body.valid())
|
||||
body = Statement::parseOrFail(source);
|
||||
return create<Body>(returnTypeSpecifier, name, parameterList, body);
|
||||
}
|
||||
private:
|
||||
static List<VariableDefinitionT<T>> parseParameterList(
|
||||
CharacterSource* source)
|
||||
{
|
||||
List<VariableDefinitionT<T>> list;
|
||||
VariableDefinitionT<T> parameter =
|
||||
VariableDefinitionT<T>::parse(source);
|
||||
if (!parameter.valid())
|
||||
return list;
|
||||
list.add(parameter);
|
||||
Span span;
|
||||
while (Space::parseCharacter(source, ',', &span)) {
|
||||
VariableDefinitionT<T> parameter =
|
||||
VariableDefinitionT<T>::parse(source);
|
||||
if (!parameter.valid())
|
||||
source->location().throwError("Expected parameter");
|
||||
list.add(parameter);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
FunctionDefinitionStatementT() { }
|
||||
FunctionDefinitionStatementT(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const TycoSpecifier& returnTypeSpecifier, const Identifier& name,
|
||||
const List<VariableDefinitionT<T>>& parameterList,
|
||||
const Statement& body)
|
||||
: Statement::Body(returnTypeSpecifier.span() + body.span()),
|
||||
_returnTypeSpecifier(returnTypeSpecifier), _name(name),
|
||||
_parameterList(parameterList), _body(body) { }
|
||||
TypeT<T> type() const
|
||||
{
|
||||
FunctionType t(_returnTypeSpecifier);
|
||||
for (auto p : _parameterList)
|
||||
t.instantiate(p.type());
|
||||
return t;
|
||||
}
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
_returnTypeSpecifier.resolve(scope);
|
||||
for (auto p : _parameterList) {
|
||||
p.resolve(scope);
|
||||
_scope.addObject(p.identifier(), p);
|
||||
}
|
||||
_scope.setParentScope(scope);
|
||||
_body.resolve(&_scope);
|
||||
}
|
||||
private:
|
||||
TycoSpecifier _returnTypeSpecifier;
|
||||
Identifier _name;
|
||||
List<VariableDefinitionT<T>> _parameterList;
|
||||
Statement _body;
|
||||
Scope _scope;
|
||||
};
|
||||
};
|
||||
|
||||
class StatementSequence : public ParseTreeObject
|
||||
{
|
||||
public:
|
||||
StatementSequence() { }
|
||||
static StatementSequence parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
List<Statement> sequence;
|
||||
do {
|
||||
Statement statement = Statement::parse(source);
|
||||
if (!statement.valid())
|
||||
break;
|
||||
span += statement.span();
|
||||
sequence.add(statement);
|
||||
} while (true);
|
||||
return create<Body>(sequence, span);
|
||||
}
|
||||
void resolve(Scope* scope) { body()->resolve(scope); }
|
||||
List<Statement>::Iterator begin() { return body()->begin(); }
|
||||
List<Statement>::Iterator end() { return body()->end(); }
|
||||
private:
|
||||
StatementSequence(Handle other) : ParseTreeObject(other) { }
|
||||
|
||||
class Body : public ParseTreeObject::Body
|
||||
{
|
||||
public:
|
||||
Body(const List<Statement>& sequence, const Span& span)
|
||||
: ParseTreeObject::Body(span), _sequence(sequence) { }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
for (auto s : _sequence)
|
||||
s.resolve(scope);
|
||||
}
|
||||
List<Statement>::Iterator begin() { return _sequence.begin(); }
|
||||
List<Statement>::Iterator end() { return _sequence.end(); }
|
||||
private:
|
||||
List<Statement> _sequence;
|
||||
};
|
||||
|
||||
Body* body() { return as<Body>(); }
|
||||
};
|
||||
|
||||
class CompoundStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static CompoundStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseCharacter(source, '{', &span))
|
||||
return CompoundStatement();
|
||||
StatementSequence sequence = StatementSequence::parse(source);
|
||||
Space::assertCharacter(source, '}', &span);
|
||||
return create<Body>(sequence, span);
|
||||
}
|
||||
private:
|
||||
CompoundStatement() { }
|
||||
CompoundStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const StatementSequence& sequence, const Span& span)
|
||||
: Statement::Body(span), _sequence(sequence) { }
|
||||
void resolve(Scope* scope) { _sequence.resolve(scope); }
|
||||
private:
|
||||
StatementSequence _sequence;
|
||||
};
|
||||
};
|
||||
|
||||
// TycoDefinitionStatement := TycoSignifier "=" TycoSpecifier ";"
|
||||
class TycoDefinitionStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static TycoDefinitionStatement parse(CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
CharacterSource s2 = s;
|
||||
TycoSignifier tycoSignifier = TycoSignifier::parse(&s);
|
||||
if (!tycoSignifier.valid())
|
||||
return TycoDefinitionStatement();
|
||||
if (!Space::parseCharacter(&s, '='))
|
||||
return TycoDefinitionStatement();
|
||||
*source = s;
|
||||
TycoSpecifier tycoSpecifier = TycoSpecifier::parse(source);
|
||||
Span span;
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
return create<Body>(tycoSignifier, tycoSpecifier,
|
||||
tycoSignifier.span() + span);
|
||||
}
|
||||
private:
|
||||
TycoDefinitionStatement() { }
|
||||
TycoDefinitionStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const TycoSignifier& tycoSignifier,
|
||||
const TycoSpecifier& tycoSpecifier, const Span& span)
|
||||
: Statement::Body(span), _tycoSignifier(tycoSignifier),
|
||||
_tycoSpecifier(tycoSpecifier) { }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
|
||||
}
|
||||
private:
|
||||
TycoSignifier _tycoSignifier;
|
||||
TycoSpecifier _tycoSpecifier;
|
||||
};
|
||||
};
|
||||
|
||||
class NothingStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static NothingStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "nothing", &span))
|
||||
return NothingStatement();
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
return create<Body>(span);
|
||||
}
|
||||
private:
|
||||
NothingStatement() { }
|
||||
NothingStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Span& span) : Statement::Body(span) { }
|
||||
void resolve(Scope* scope) { }
|
||||
};
|
||||
};
|
||||
|
||||
class IncrementDecrementStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static Statement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
Operator o = OperatorIncrement().parse(source, &span);
|
||||
if (!o.valid())
|
||||
o = OperatorDecrement().parse(source, &span);
|
||||
if (!o.valid())
|
||||
return Statement();
|
||||
Expression lValue = Expression::parse(source);
|
||||
Span span2;
|
||||
Space::assertCharacter(source, ';', &span2);
|
||||
return ExpressionStatement(FunctionCallExpression::unary(o, span,
|
||||
FunctionCallExpression::unary(
|
||||
OperatorAmpersand(), Span(), lValue)),
|
||||
span + span2);
|
||||
}
|
||||
};
|
||||
|
||||
// ConditionalStatement = (`if` | `unless`) ConditionedStatement
|
||||
// ((`elseIf` | `elseUnless`) ConditionedStatement)* [`else` Statement];
|
||||
// ConditionedStatement = "(" Expression ")" Statement;
|
||||
class ConditionalStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static ConditionalStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (Space::parseKeyword(source, "if", &span))
|
||||
return parse2(source, span, false);
|
||||
if (Space::parseKeyword(source, "unless", &span))
|
||||
return parse2(source, span, true);
|
||||
return ConditionalStatement();
|
||||
}
|
||||
private:
|
||||
static ConditionalStatement parse2(CharacterSource* source, Span span,
|
||||
bool unlessStatement)
|
||||
{
|
||||
Space::assertCharacter(source, '(');
|
||||
Expression condition = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
Statement statement = Statement::parseOrFail(source);
|
||||
span += statement.span();
|
||||
Statement elseStatement;
|
||||
if (Space::parseKeyword(source, "else")) {
|
||||
elseStatement = Statement::parseOrFail(source);
|
||||
span += elseStatement.span();
|
||||
}
|
||||
else
|
||||
if (Space::parseKeyword(source, "elseIf")) {
|
||||
elseStatement = parse2(source, span, false);
|
||||
span += elseStatement.span();
|
||||
}
|
||||
else
|
||||
if (Space::parseKeyword(source, "elseUnless")) {
|
||||
elseStatement = parse2(source, span, true);
|
||||
span += elseStatement.span();
|
||||
}
|
||||
if (unlessStatement)
|
||||
condition = !condition;
|
||||
return create<Body>(condition, statement, elseStatement, span);
|
||||
}
|
||||
|
||||
ConditionalStatement() { }
|
||||
ConditionalStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Expression& condition, const Statement& trueStatement,
|
||||
const Statement& falseStatement, const Span& span)
|
||||
: Statement::Body(span), _condition(condition),
|
||||
_trueStatement(trueStatement), _falseStatement(falseStatement) { }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
_condition.resolve(scope);
|
||||
_trueStatement.resolve(scope);
|
||||
_falseStatement.resolve(scope);
|
||||
}
|
||||
private:
|
||||
Expression _condition;
|
||||
Statement _trueStatement;
|
||||
Statement _falseStatement;
|
||||
};
|
||||
};
|
||||
|
||||
class SwitchStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static SwitchStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "switch", &span))
|
||||
return SwitchStatement();
|
||||
Space::assertCharacter(source, '(');
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
Space::assertCharacter(source, '{');
|
||||
Case defaultCase;
|
||||
|
||||
CharacterSource s = *source;
|
||||
List<Case> cases;
|
||||
do {
|
||||
Case c = Case::parse(source);
|
||||
if (!c.valid())
|
||||
break;
|
||||
if (c.isDefault()) {
|
||||
if (defaultCase.valid())
|
||||
s.location().throwError(
|
||||
"This switch statement already has a default case");
|
||||
defaultCase = c;
|
||||
}
|
||||
else
|
||||
cases.add(c);
|
||||
} while (true);
|
||||
Space::assertCharacter(source, '}', &span);
|
||||
return create<Body>(expression, defaultCase, cases, span);
|
||||
}
|
||||
private:
|
||||
SwitchStatement() { }
|
||||
SwitchStatement(Handle other) { }
|
||||
|
||||
class Case : public ParseTreeObject
|
||||
{
|
||||
public:
|
||||
static Case parse(CharacterSource* source)
|
||||
{
|
||||
List<Expression> expressions;
|
||||
bool defaultType;
|
||||
Span span;
|
||||
if (Space::parseKeyword(source, "case", &span)) {
|
||||
defaultType = false;
|
||||
do {
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
expressions.add(expression);
|
||||
if (!Space::parseCharacter(source, ','))
|
||||
break;
|
||||
} while (true);
|
||||
}
|
||||
else {
|
||||
defaultType = true;
|
||||
if (!Space::parseKeyword(source, "default", &span))
|
||||
source->location().throwError("Expected case or default");
|
||||
}
|
||||
Space::assertCharacter(source, ':');
|
||||
Statement statement = Statement::parseOrFail(source);
|
||||
span += statement.span();
|
||||
if (defaultType)
|
||||
return create<DefaultBody>(statement, span);
|
||||
return create<ValueBody>(expressions, statement, span);
|
||||
}
|
||||
bool isDefault() const { return body()->isDefault(); }
|
||||
void resolve(Scope* scope) { body()->resolve(scope); }
|
||||
|
||||
Case() { }
|
||||
|
||||
class Body : public ParseTreeObject::Body
|
||||
{
|
||||
public:
|
||||
Body(const Statement& statement, const Span& span)
|
||||
: ParseTreeObject::Body(span), _statement(statement) { }
|
||||
virtual bool isDefault() const = 0;
|
||||
virtual void resolve(Scope* scope)
|
||||
{
|
||||
_statement.resolve(scope);
|
||||
}
|
||||
private:
|
||||
Statement _statement;
|
||||
};
|
||||
private:
|
||||
Case(Handle other) : ParseTreeObject(other) { }
|
||||
|
||||
Body* body() { return as<Body>(); }
|
||||
const Body* body() const { return as<Body>(); }
|
||||
|
||||
class DefaultBody : public Body
|
||||
{
|
||||
public:
|
||||
DefaultBody(const Statement& statement, const Span& span)
|
||||
: Body(statement, span) { }
|
||||
bool isDefault() const { return true; }
|
||||
};
|
||||
class ValueBody : public Body
|
||||
{
|
||||
public:
|
||||
ValueBody(const List<Expression>& expressions,
|
||||
const Statement& statement, const Span& span)
|
||||
: Body(statement, span), _expressions(expressions) { }
|
||||
bool isDefault() const { return false; }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
for (auto e : _expressions)
|
||||
e.resolve(scope);
|
||||
Body::resolve(scope);
|
||||
}
|
||||
private:
|
||||
List<Expression> _expressions;
|
||||
};
|
||||
};
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Expression& expression, const Case& defaultCase,
|
||||
const List<Case>& cases, const Span& span)
|
||||
: Statement::Body(span), _expression(expression),
|
||||
_defaultCase(defaultCase), _cases(cases) { }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
_expression.resolve(scope);
|
||||
_defaultCase.resolve(scope);
|
||||
for (auto c : _cases)
|
||||
c.resolve(scope);
|
||||
}
|
||||
private:
|
||||
Expression _expression;
|
||||
Case _defaultCase;
|
||||
List<Case> _cases;
|
||||
};
|
||||
};
|
||||
|
||||
class ReturnStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static ReturnStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "return", &span))
|
||||
return ReturnStatement();
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
return create<Body>(expression, span);
|
||||
}
|
||||
private:
|
||||
ReturnStatement() { }
|
||||
ReturnStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Expression& expression, const Span& span)
|
||||
: Statement::Body(span), _expression(expression) { }
|
||||
void resolve(Scope* scope) { _expression.resolve(scope); }
|
||||
private:
|
||||
Expression _expression;
|
||||
};
|
||||
};
|
||||
|
||||
class IncludeStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static IncludeStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "include", &span))
|
||||
return IncludeStatement();
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
return create<Body>(expression, span);
|
||||
}
|
||||
private:
|
||||
IncludeStatement() { }
|
||||
IncludeStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Expression& expression, const Span& span)
|
||||
: Statement::Body(span), _expression(expression) { }
|
||||
void resolve(Scope* scope) { _expression.resolve(scope); }
|
||||
private:
|
||||
Expression _expression;
|
||||
};
|
||||
};
|
||||
|
||||
template<class T> class BreakOrContinueStatementT : public Statement
|
||||
{
|
||||
public:
|
||||
static BreakOrContinueStatement parse(CharacterSource* source)
|
||||
{
|
||||
BreakOrContinueStatement breakStatement = parseBreak(source);
|
||||
if (breakStatement.valid())
|
||||
return breakStatement;
|
||||
return parseContinue(source);
|
||||
}
|
||||
private:
|
||||
BreakOrContinueStatementT() { }
|
||||
BreakOrContinueStatementT(Handle other) : Statement(other) { }
|
||||
|
||||
static BreakOrContinueStatement parseBreak(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "break", &span))
|
||||
return BreakOrContinueStatement();
|
||||
BreakOrContinueStatement statement = parse(source);
|
||||
if (!statement.valid())
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
else
|
||||
span += statement.span();
|
||||
return create<BreakBody>(statement, span);
|
||||
}
|
||||
|
||||
static BreakOrContinueStatement parseContinue(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "continue", &span))
|
||||
return BreakOrContinueStatement();
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
return create<ContinueBody>(span);
|
||||
}
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Span& span) : Statement::Body(span) { }
|
||||
void resolve(Scope* scope) { }
|
||||
};
|
||||
|
||||
class BreakBody : public Body
|
||||
{
|
||||
public:
|
||||
BreakBody(const BreakOrContinueStatement& statement, const Span& span)
|
||||
: Body(span), _statement(statement) { }
|
||||
private:
|
||||
BreakOrContinueStatementT<T> _statement;
|
||||
};
|
||||
|
||||
class ContinueBody : public Body
|
||||
{
|
||||
public:
|
||||
ContinueBody(const Span& span) : Body(span) { }
|
||||
};
|
||||
};
|
||||
|
||||
class ForeverStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static ForeverStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "forever", &span))
|
||||
return ForeverStatement();
|
||||
Statement statement = Statement::parseOrFail(source);
|
||||
return create<Body>(statement, span + statement.span());
|
||||
}
|
||||
private:
|
||||
ForeverStatement() { }
|
||||
ForeverStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Statement& statement, const Span& span)
|
||||
: Statement::Body(span), _statement(statement) { }
|
||||
void resolve(Scope* scope) { _statement.resolve(scope); }
|
||||
private:
|
||||
Statement _statement;
|
||||
};
|
||||
};
|
||||
|
||||
class WhileStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static WhileStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
Statement doStatement;
|
||||
bool foundDo = false;
|
||||
if (Space::parseKeyword(source, "do", &span)) {
|
||||
foundDo = true;
|
||||
doStatement = Statement::parseOrFail(source);
|
||||
}
|
||||
bool foundWhile = false;
|
||||
bool foundUntil = false;
|
||||
if (Space::parseKeyword(source, "while", &span))
|
||||
foundWhile = true;
|
||||
else
|
||||
if (Space::parseKeyword(source, "until", &span))
|
||||
foundUntil = true;
|
||||
if (!foundWhile && !foundUntil) {
|
||||
if (foundDo)
|
||||
source->location().throwError("Expected while or until");
|
||||
return WhileStatement();
|
||||
}
|
||||
Space::assertCharacter(source, '(');
|
||||
Expression condition = Expression::parse(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
Statement statement = Statement::parseOrFail(source);
|
||||
span += statement.span();
|
||||
Statement doneStatement;
|
||||
if (Space::parseKeyword(source, "done")) {
|
||||
doneStatement = Statement::parseOrFail(source);
|
||||
span += doneStatement.span();
|
||||
}
|
||||
if (foundUntil)
|
||||
condition = !condition;
|
||||
return create<Body>(doStatement, condition, statement,
|
||||
doneStatement, span);
|
||||
}
|
||||
private:
|
||||
WhileStatement() { }
|
||||
WhileStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Statement& doStatement, const Expression& condition,
|
||||
const Statement& statement, const Statement& doneStatement,
|
||||
const Span& span)
|
||||
: Statement::Body(span), _doStatement(doStatement),
|
||||
_condition(condition), _statement(statement),
|
||||
_doneStatement(doneStatement) { }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
_doStatement.resolve(scope);
|
||||
_condition.resolve(scope);
|
||||
_statement.resolve(scope);
|
||||
_doneStatement.resolve(scope);
|
||||
}
|
||||
private:
|
||||
Statement _doStatement;
|
||||
Expression _condition;
|
||||
Statement _statement;
|
||||
Statement _doneStatement;
|
||||
};
|
||||
};
|
||||
|
||||
class ForStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static ForStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "for", &span))
|
||||
return ForStatement();
|
||||
Space::assertCharacter(source, '(');
|
||||
Statement preStatement = Statement::parse(source);
|
||||
if (!preStatement.valid())
|
||||
Space::assertCharacter(source, ';');
|
||||
Expression expression = Expression::parse(source);
|
||||
Space::assertCharacter(source, ';');
|
||||
Statement postStatement = Statement::parse(source);
|
||||
Space::parseCharacter(source, ')');
|
||||
Statement statement = Statement::parseOrFail(source);
|
||||
span += statement.span();
|
||||
Statement doneStatement;
|
||||
if (Space::parseKeyword(source, "done")) {
|
||||
doneStatement = Statement::parseOrFail(source);
|
||||
span += doneStatement.span();
|
||||
}
|
||||
return create<Body>(preStatement, expression, postStatement,
|
||||
statement, doneStatement, span);
|
||||
}
|
||||
private:
|
||||
ForStatement() { }
|
||||
ForStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Statement& preStatement, const Expression& condition,
|
||||
const Statement& postStatement, const Statement& statement,
|
||||
const Statement& doneStatement, const Span& span)
|
||||
: Statement::Body(span), _preStatement(preStatement),
|
||||
_condition(condition), _postStatement(postStatement),
|
||||
_statement(statement), _doneStatement(doneStatement) { }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
_preStatement.resolve(scope);
|
||||
_condition.resolve(scope);
|
||||
_postStatement.resolve(scope);
|
||||
_statement.resolve(scope);
|
||||
_doneStatement.resolve(scope);
|
||||
}
|
||||
private:
|
||||
Statement _preStatement;
|
||||
Expression _condition;
|
||||
Statement _postStatement;
|
||||
Statement _statement;
|
||||
Statement _doneStatement;
|
||||
};
|
||||
};
|
||||
|
||||
template<class T> class LabelStatementT : public Statement
|
||||
{
|
||||
public:
|
||||
static LabelStatement parse(CharacterSource* source)
|
||||
{
|
||||
CharacterSource s2 = *source;
|
||||
Identifier identifier = Identifier::parse(&s2);
|
||||
if (!identifier.valid())
|
||||
return LabelStatement();
|
||||
Span span;
|
||||
if (!Space::parseCharacter(&s2, ':', &span))
|
||||
return LabelStatement();
|
||||
return create<Body>(identifier, identifier.span() + span);
|
||||
}
|
||||
private:
|
||||
LabelStatementT() { }
|
||||
LabelStatementT(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Identifier& identifier, const Span& span)
|
||||
: Statement::Body(span), _identifier(identifier) { }
|
||||
void resolve(Scope* scope)
|
||||
{
|
||||
|
||||
}
|
||||
private:
|
||||
IdentifierT<T> _identifier;
|
||||
};
|
||||
};
|
||||
|
||||
class GotoStatement : public Statement
|
||||
{
|
||||
public:
|
||||
static GotoStatement parse(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "goto", &span))
|
||||
return GotoStatement();
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
Span span2;
|
||||
Space::parseCharacter(source, ';', &span);
|
||||
return create<Body>(expression, span);
|
||||
}
|
||||
private:
|
||||
GotoStatement() { }
|
||||
GotoStatement(Handle other) : Statement(other) { }
|
||||
|
||||
class Body : public Statement::Body
|
||||
{
|
||||
public:
|
||||
Body(const Expression& expression, const Span& span)
|
||||
: Statement::Body(span), _expression(expression) { }
|
||||
void resolve(Scope* scope) { _expression.resolve(scope); }
|
||||
private:
|
||||
Expression _expression;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // INCLUDED_STATEMENT_H
|
||||
Reference in New Issue
Block a user