📄 reader.cpp
字号:
// Reader.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include "CodeObject.h"
#include "TokenMaker.h"
#include "Grammar.h"
// Global standard handles
FILE * pOut;
FILE * pIn;
namespace IO
{
int ReadLine(char * buffer, unsigned max, FILE * stream)
{
int nChar;
unsigned nIndex = 0;
while(nIndex < max-1)
{
switch(nChar = fgetc(stream))
{
case EOF: // End of file
buffer[nIndex] = 0;
if (nIndex == 0)
return 0;
return 1;
case 0x0A:
buffer[nIndex] = 0;
return 1;
case 0x0D:
continue;
default:
buffer[nIndex++] = nChar;
}
}
buffer[max-1] = '\0';
return -1;
}
void WriteLine(const char * buffer, FILE * stream)
{
fputs(buffer, stream);
fputc('\n', stream);
}
};
int ParseExpression(CppList<CodeObject*> * pTokenList, Grammar * pG, CodeObject ** ppResult)
{
/*
Breakdown:
for (start = first; start != end; start++)
if start type = Input
done
grammar begin
while next != end
grammar next
if error
exit
if continue
continue
if not found break while
if found
create object within list
restart from the very beginning
*/
CodeObject * pStart;
CodeObject * pNext;
CppList<CodeObject*>::iterator _Start;
CppList<CodeObject*>::iterator _Next;
CodeObject * pNew = NULL;
Grammar::Result r;
// Dummy NULL token so the for loop works
pNew = new CodeObject;
pNew->Line = 0;
pNew->Type = Null;
pTokenList->push_back(pNew);
Restart: // Yeah, that's right... I use goto. In this case, it DOES make clearer code
for(_Start = pTokenList->begin(); _Start != pTokenList->end(); _Start++)
{
pStart = *_Start;
_Next = _Start;
pG->Begin();
while(_Next != pTokenList->end())
{
pNext = *_Next;
r = pG->Next(pNext->Type);
if (r == Grammar::BadInput)
{
IO::WriteLine("Unexpected Failure!!!", pOut);
*ppResult = NULL;
return -1;
}
else if (r == Grammar::Continue)
{
_Next++;
continue;
}
else if (r == Grammar::NotFound)
break;
else if (r == Grammar::Found)
{
pNew = new CodeObject;
pNew->Line = pStart->Line;
pNew->Type = pG->GetResult();
pTokenList->splice(pNew->Descendants->begin(), *pNew->Descendants, _Start, _Next);
pTokenList->insert(_Next, pNew);
goto Restart;
}
}
}
pStart = *pTokenList->begin();
if (pStart->Type != Input)
{
IO::WriteLine(" Failure: Bad Input!!!", pOut);
*ppResult = NULL;
return -1;
}
*ppResult = pStart;
pTokenList->pop_front(); // Lose ownership of result
pStart = *pTokenList->begin();
delete pStart; // Delete dummy NULL object
pTokenList->pop_front();
return 0;
}
int main(int argc, char* argv[])
{
char line[256];
pIn = fopen("Input.txt", "rt");
if (/* Write Output to a file == */ false)
pOut = fopen("Output.txt", "wt");
else
pOut = stdout; /*Write to console*/
Utility::MallocList<char *> strList;
if (!pIn)
printf("Error!\n");
else
while(IO::ReadLine(line, 256, pIn))
strList.push_back(strdup(line));
/*
Grammar description in BNF:
Value -> Integer
Expression -> Value | (Expression Operator Expression) | (OpenParenthesis Expression CloseParenthesis)
Operator -> PlusSign
Input -> Expression, EndOfFile
'Integer', 'OpenParenthesis', 'CloseParenthesis', and 'PlusSign' are
created by the token parser and terminals
'Input' is the completed result
*/
Grammar::Rule r1 = {Value,{Integer, Null}};
Grammar::Rule r2 = {Expression,{Value, Null}};
Grammar::Rule r3 = {Expression,{Expression, Operator, Expression, Null}};
Grammar::Rule r4 = {Expression,{OpenParenthesis, Expression, CloseParenthesis, Null}};
Grammar::Rule r5 = {Operator,{PlusSign, Null}};
Grammar::Rule r6 = {Input,{Expression, EndOfFile, Null}};
Grammar g;
g.AddRule(&r1);
g.AddRule(&r2);
g.AddRule(&r3);
g.AddRule(&r4);
g.AddRule(&r5);
g.AddRule(&r6);
IO::WriteLine("Grammar Tree:\n", pOut);
g.Dump(pOut, true, 0);
IO::WriteLine("\nParsing Tokens:\n", pOut);
CppList<CodeObject *> tokenList;
if (TokenMaker::MakeTokens(&strList, &tokenList))
IO::WriteLine(LastError, pOut);
for(CppList<CodeObject*>::iterator _Iter = tokenList.begin(); _Iter != tokenList.end(); _Iter++)
{
CodeObject * pObj = *_Iter;
pObj->Dump(pOut, true, 0);
}
IO::WriteLine("\nParsing Expression:\n", pOut);
CodeObject * pInput;
if (!ParseExpression(&tokenList, &g, &pInput))
{
IO::WriteLine("\nResult:\n", pOut);
pInput->Dump(pOut, true);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -