mirror of
https://github.com/dbalsom/x86_microcode.git
synced 2026-06-16 13:07:07 +03:00
Initial 80386 microcode commit.
This commit is contained in:
@@ -0,0 +1,492 @@
|
||||
#include "alfe/main.h"
|
||||
|
||||
#ifndef INCLUDED_PARSER_H
|
||||
#define INCLUDED_PARSER_H
|
||||
|
||||
#include "alfe/code.h"
|
||||
#include "alfe/space.h"
|
||||
|
||||
class Parser : Uncopyable
|
||||
{
|
||||
public:
|
||||
CodeList parseFromFile(File file)
|
||||
{
|
||||
CodeList c;
|
||||
parseFromFile(c, file);
|
||||
return c;
|
||||
}
|
||||
void parseFromString(Code code, String s)
|
||||
{
|
||||
CharacterSource source(s);
|
||||
do {
|
||||
CharacterSource s2 = source;
|
||||
if (s2.get() == -1)
|
||||
return;
|
||||
parseStatementOrFail(code, &source);
|
||||
} while (true);
|
||||
}
|
||||
private:
|
||||
void parseFromFile(Code code, File file)
|
||||
{
|
||||
parseFromString(code, file.contents());
|
||||
}
|
||||
bool parseStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
if (parseExpressionStatement(code, source))
|
||||
return true;
|
||||
if (parseFunctionDefinitionStatement(code, source))
|
||||
return true;
|
||||
if (parseAssignment(code, source))
|
||||
return true;
|
||||
if (parseCompoundStatement(code, source))
|
||||
return true;
|
||||
if (parseTycoDefinitionStatement(code, source))
|
||||
return true;
|
||||
if (parseNothingStatement(source))
|
||||
return true;
|
||||
if (parseIncrementDecrementStatement(code, source))
|
||||
return true;
|
||||
if (parseConditionalStatement(code, source))
|
||||
return true;
|
||||
if (parseSwitchStatement(code, source))
|
||||
return true;
|
||||
if (parseReturnStatement(code, source))
|
||||
return true;
|
||||
if (parseIncludeStatement(code, source))
|
||||
return true;
|
||||
if (parseBreakOrContinueStatement(code, source))
|
||||
return true;
|
||||
if (parseForeverStatement(code, source))
|
||||
return true;
|
||||
if (parseWhileStatement(code, source))
|
||||
return true;
|
||||
if (parseForStatement(code, source))
|
||||
return true;
|
||||
if (parseLabelStatement(code, source))
|
||||
return true;
|
||||
if (parseGotoStatement(code, source))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void parseStatementOrFail(Code code, CharacterSource* source)
|
||||
{
|
||||
if (!parseStatement(code, source))
|
||||
source->location().throwError("Expected statement");
|
||||
}
|
||||
bool parseExpressionStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
Expression expression = Expression::parse(&s);
|
||||
if (!expression.valid())
|
||||
return false;
|
||||
Span span;
|
||||
if (!Space::parseCharacter(&s, ';', &span))
|
||||
return false;
|
||||
_lastSpan = span;
|
||||
*source = s;
|
||||
if (!expression.mightHaveSideEffect())
|
||||
source->location().throwError("Statement has no effect");
|
||||
code.insert<ExpressionStatement>(expression, expression.span() + span);
|
||||
return true;
|
||||
}
|
||||
bool parseAssignment(Code code, CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
Expression left = Expression::parse(&s);
|
||||
Location operatorLocation = s.location();
|
||||
if (!left.valid())
|
||||
return false;
|
||||
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 false;
|
||||
|
||||
*source = s;
|
||||
Expression right = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
_lastSpan = span;
|
||||
|
||||
code.insert<ExpressionStatement>(FunctionCallExpression::binary(*op,
|
||||
span,
|
||||
FunctionCallExpression::unary(OperatorAmpersand(), Span(), left),
|
||||
right), left.span() + span);
|
||||
return true;
|
||||
}
|
||||
List<VariableDefinition> parseParameterList(CharacterSource* source)
|
||||
{
|
||||
List<VariableDefinition> list;
|
||||
VariableDefinition parameter = VariableDefinition::parse(source);
|
||||
if (!parameter.valid())
|
||||
return list;
|
||||
list.add(parameter);
|
||||
Span span;
|
||||
while (Space::parseCharacter(source, ',', &span)) {
|
||||
VariableDefinition parameter = VariableDefinition::parse(source);
|
||||
if (!parameter.valid())
|
||||
source->location().throwError("Expected parameter");
|
||||
list.add(parameter);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
bool parseFunctionDefinitionStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
TycoSpecifier returnTypeSpecifier = TycoSpecifier::parse(&s);
|
||||
if (!returnTypeSpecifier.valid())
|
||||
return false;
|
||||
Identifier name = Identifier::parse(&s);
|
||||
if (!name.valid())
|
||||
return false;
|
||||
Span span;
|
||||
if (!Space::parseCharacter(&s, '('))
|
||||
return false;
|
||||
*source = s;
|
||||
List<VariableDefinition> parameterList = parseParameterList(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
Span span;
|
||||
if (Space::parseKeyword(source, "from", &span)) {
|
||||
Expression dll = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
_lastSpan = span;
|
||||
code.insert<FunctionDefinitionFromStatement>(returnTypeSpecifier,
|
||||
name, parameterList, dll, returnTypeSpecifier.span() + span);
|
||||
return true;
|
||||
}
|
||||
CodeList body;
|
||||
parseStatementOrFail(body, source);
|
||||
code.insert<FunctionDefinitionCodeStatement>(returnTypeSpecifier,
|
||||
name, parameterList, body, returnTypeSpecifier.span() + _lastSpan);
|
||||
return true;
|
||||
}
|
||||
void parseStatementSequence(Code code, CharacterSource* source)
|
||||
{
|
||||
do {
|
||||
if (!parseStatement(code, source))
|
||||
return;
|
||||
} while (true);
|
||||
}
|
||||
bool parseCompoundStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseCharacter(source, '{', &span))
|
||||
return false;
|
||||
parseStatementSequence(code, source);
|
||||
Space::assertCharacter(source, '}', &span);
|
||||
_lastSpan = span;
|
||||
return true;
|
||||
}
|
||||
// TycoDefinitionStatement := TycoSignifier "=" TycoSpecifier ";"
|
||||
bool parseTycoDefinitionStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
CharacterSource s = *source;
|
||||
CharacterSource s2 = s;
|
||||
TycoSignifier tycoSignifier = TycoSignifier::parse(&s);
|
||||
if (!tycoSignifier.valid())
|
||||
return false;
|
||||
if (!Space::parseCharacter(&s, '='))
|
||||
return false;
|
||||
*source = s;
|
||||
TycoSpecifier tycoSpecifier = TycoSpecifier::parse(source);
|
||||
Span span;
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
_lastSpan = span;
|
||||
code.insert<TycoDefinitionStatement>(tycoSignifier, tycoSpecifier,
|
||||
tycoSignifier.span() + span);
|
||||
return true;
|
||||
}
|
||||
bool parseNothingStatement(CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "nothing", &span))
|
||||
return false;
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
_lastSpan = span;
|
||||
return true;
|
||||
}
|
||||
bool parseIncrementDecrementStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
Operator o = OperatorIncrement().parse(source, &span);
|
||||
if (!o.valid())
|
||||
o = OperatorDecrement().parse(source, &span);
|
||||
if (!o.valid())
|
||||
return false;
|
||||
Expression lValue = Expression::parse(source);
|
||||
Span span2;
|
||||
Space::assertCharacter(source, ';', &span2);
|
||||
_lastSpan = span2;
|
||||
code.insert<ExpressionStatement>(FunctionCallExpression::unary(o, span,
|
||||
FunctionCallExpression::unary(
|
||||
OperatorAmpersand(), Span(), lValue)),
|
||||
span + span2);
|
||||
return true;
|
||||
}
|
||||
void parseConditionalStatement2(Code code, CharacterSource* source,
|
||||
Span span, bool unlessStatement)
|
||||
{
|
||||
Space::assertCharacter(source, '(');
|
||||
Expression condition = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
CodeList conditionalCode;
|
||||
parseStatementOrFail(conditionalCode, source);
|
||||
span += _lastSpan;
|
||||
CodeList elseCode;
|
||||
if (Space::parseKeyword(source, "else"))
|
||||
parseStatementOrFail(elseCode, source);
|
||||
else {
|
||||
if (Space::parseKeyword(source, "elseIf"))
|
||||
parseConditionalStatement2(elseCode, source, span, false);
|
||||
else {
|
||||
if (Space::parseKeyword(source, "elseUnless"))
|
||||
parseConditionalStatement2(elseCode, source, span, true);
|
||||
}
|
||||
}
|
||||
if (unlessStatement)
|
||||
condition = !condition;
|
||||
code.insert<ConditionalStatement>(condition, conditionalCode, elseCode,
|
||||
span + _lastSpan);
|
||||
}
|
||||
// ConditionalStatement = (`if` | `unless`) ConditionedStatement
|
||||
// ((`elseIf` | `elseUnless`) ConditionedStatement)* [`else` Statement];
|
||||
// ConditionedStatement = "(" Expression ")" Statement;
|
||||
bool parseConditionalStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (Space::parseKeyword(source, "if", &span)) {
|
||||
parseConditionalStatement2(code, source, span, false);
|
||||
return true;
|
||||
}
|
||||
if (Space::parseKeyword(source, "unless", &span)) {
|
||||
parseConditionalStatement2(code, source, span, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
SwitchStatement::Case parseCase(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, ':');
|
||||
CodeList code;
|
||||
parseStatementOrFail(code, source);
|
||||
span += _lastSpan;
|
||||
if (defaultType)
|
||||
return SwitchStatement::Case(code, span);
|
||||
return SwitchStatement::Case(expressions, code, span);
|
||||
}
|
||||
bool parseSwitchStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "switch", &span))
|
||||
return false;
|
||||
Space::assertCharacter(source, '(');
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
Space::assertCharacter(source, '{');
|
||||
SwitchStatement::Case defaultCase;
|
||||
|
||||
CharacterSource s = *source;
|
||||
List<SwitchStatement::Case> cases;
|
||||
do {
|
||||
SwitchStatement::Case c = parseCase(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);
|
||||
_lastSpan = span;
|
||||
code.insert<SwitchStatement>(expression, defaultCase, cases, span);
|
||||
return true;
|
||||
}
|
||||
bool parseReturnStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "return", &span))
|
||||
return false;
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
_lastSpan = span;
|
||||
code.insert<ReturnStatement>(expression, span);
|
||||
return true;
|
||||
}
|
||||
bool parseIncludeStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "include", &span))
|
||||
return false;
|
||||
Expression expression = parseExpression(source);
|
||||
|
||||
StringLiteralExpression s(expression);
|
||||
if (!s.valid()) {
|
||||
expression.span().throwError("Argument to include must be a "
|
||||
"simple string");
|
||||
}
|
||||
String path = s.string();
|
||||
|
||||
//Resolver resolver;
|
||||
//resolver.resolve(expression);
|
||||
//Evaluator evaluator;
|
||||
//Value value = evaluator.evaluate(expression).convertTo(StringType());
|
||||
//String path = value.value<String>();
|
||||
|
||||
File lastFile = _currentFile;
|
||||
_currentFile = File(path, _currentFile.parent());
|
||||
parseFromFile(code, _currentFile);
|
||||
_currentFile = lastFile;
|
||||
}
|
||||
bool parseBreakOrContinueStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
int breakCount = 0;
|
||||
bool hasContinue = false;
|
||||
Span span;
|
||||
do {
|
||||
if (Space::parseKeyword(source, "break", &span))
|
||||
++breakCount;
|
||||
else
|
||||
break;
|
||||
} while (true);
|
||||
if (Space::parseKeyword(source, "continue", &span))
|
||||
hasContinue = true;
|
||||
if (breakCount == 0 && !hasContinue)
|
||||
return false;
|
||||
Space::assertCharacter(source, ';', &span);
|
||||
_lastSpan = span;
|
||||
code.insert<BreakOrContinueStatement>(span, breakCount, hasContinue);
|
||||
return true;
|
||||
}
|
||||
bool parseForeverStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "forever", &span))
|
||||
return false;
|
||||
CodeList body;
|
||||
parseStatementOrFail(body, source);
|
||||
code.insert<ForeverStatement>(body, span);
|
||||
return true;
|
||||
}
|
||||
bool parseWhileStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
CodeList doCode;
|
||||
bool foundDo = false;
|
||||
if (Space::parseKeyword(source, "do", &span)) {
|
||||
foundDo = true;
|
||||
parseStatementOrFail(doCode, 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 false;
|
||||
}
|
||||
Space::assertCharacter(source, '(');
|
||||
Expression condition = Expression::parse(source);
|
||||
Space::assertCharacter(source, ')');
|
||||
CodeList body;
|
||||
parseStatementOrFail(body, source);
|
||||
CodeList doneCode;
|
||||
if (Space::parseKeyword(source, "done"))
|
||||
parseStatementOrFail(doneCode, source);
|
||||
span += _lastSpan;
|
||||
if (foundUntil)
|
||||
condition = !condition;
|
||||
code.insert<WhileStatement>(doCode, condition, body, doneCode, span);
|
||||
return true;
|
||||
}
|
||||
bool parseForStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "for", &span))
|
||||
return false;
|
||||
Space::assertCharacter(source, '(');
|
||||
CodeList preCode;
|
||||
if (!parseStatement(preCode, source))
|
||||
Space::assertCharacter(source, ';');
|
||||
Expression expression = Expression::parse(source);
|
||||
Space::assertCharacter(source, ';');
|
||||
CodeList postCode;
|
||||
parseStatement(postCode, source);
|
||||
Space::parseCharacter(source, ')');
|
||||
CodeList body;
|
||||
parseStatement(body, source);
|
||||
span += _lastSpan;
|
||||
CodeList doneCode;
|
||||
if (Space::parseKeyword(source, "done")) {
|
||||
parseStatementOrFail(doneCode, source);
|
||||
span += _lastSpan;
|
||||
}
|
||||
code.insert<ForStatement>(preCode, expression, postCode, body,
|
||||
doneCode, span);
|
||||
return true;
|
||||
}
|
||||
bool parseLabelStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
CharacterSource s2 = *source;
|
||||
Identifier identifier = Identifier::parse(&s2);
|
||||
if (!identifier.valid())
|
||||
return false;
|
||||
Span span;
|
||||
if (!Space::parseCharacter(&s2, ':', &span))
|
||||
return false;
|
||||
_lastSpan = span;
|
||||
code.insert<LabelStatement>(identifier, identifier.span() + span);
|
||||
return true;
|
||||
}
|
||||
bool parseGotoStatement(Code code, CharacterSource* source)
|
||||
{
|
||||
Span span;
|
||||
if (!Space::parseKeyword(source, "goto", &span))
|
||||
return false;
|
||||
Expression expression = Expression::parseOrFail(source);
|
||||
Span span2;
|
||||
Space::parseCharacter(source, ';', &span);
|
||||
code.insert<GotoStatement>(expression, span);
|
||||
return true;
|
||||
}
|
||||
|
||||
Span _lastSpan;
|
||||
File _currentFile;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_PARSER_H
|
||||
Reference in New Issue
Block a user