initial import of python-console
This commit is contained in:
parent
66670831b8
commit
c63274342f
43
3rdparty/python-console/CMakeLists.txt
vendored
Normal file
43
3rdparty/python-console/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
cmake_minimum_required( VERSION 2.8 )
|
||||||
|
project( PythonInterpreter )
|
||||||
|
|
||||||
|
find_package( Qt4 REQUIRED )
|
||||||
|
include( ${QT_USE_FILE} )
|
||||||
|
find_package( PythonLibs REQUIRED )
|
||||||
|
include_directories( ${PYTHON_INCLUDE_DIRS} )
|
||||||
|
|
||||||
|
add_executable( test_python_interpreter test_python_interpreter.cpp Interpreter.cpp )
|
||||||
|
target_link_libraries( test_python_interpreter ${PYTHON_LIBRARIES} )
|
||||||
|
|
||||||
|
qt4_wrap_cpp( Console_MOC Console.h )
|
||||||
|
add_executable( test_console test_console.cpp
|
||||||
|
Console.cpp ${Console_MOC}
|
||||||
|
ColumnFormatter.cpp
|
||||||
|
Interpreter.cpp
|
||||||
|
ParseHelper.cpp
|
||||||
|
ParseHelper.BlockParseState.cpp
|
||||||
|
ParseHelper.BracketParseState.cpp
|
||||||
|
ParseHelper.ContinuationParseState.cpp
|
||||||
|
ParseMessage.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries( test_console ${QT_LIBRARIES} ${PYTHON_LIBRARIES} )
|
||||||
|
|
||||||
|
add_executable( test_parse_helper test_parse_helper.cpp
|
||||||
|
ParseHelper.cpp
|
||||||
|
ParseHelper.BlockParseState.cpp
|
||||||
|
ParseHelper.ContinuationParseState.cpp
|
||||||
|
ParseListener.cpp
|
||||||
|
ParseMessage.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable( test_cli test_cli.cpp
|
||||||
|
ParseHelper.cpp
|
||||||
|
ParseHelper.BlockParseState.cpp
|
||||||
|
ParseHelper.ContinuationParseState.cpp
|
||||||
|
ParseListener.cpp
|
||||||
|
ParseMessage.cpp
|
||||||
|
Interpreter.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries( test_cli
|
||||||
|
${PYTHON_LIBRARIES}
|
||||||
|
)
|
141
3rdparty/python-console/ColumnFormatter.cpp
vendored
Normal file
141
3rdparty/python-console/ColumnFormatter.cpp
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ColumnFormatter.h"
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
bool ColumnFormatter::load(const std::string& fn)
|
||||||
|
{
|
||||||
|
items.clear();
|
||||||
|
std::ifstream ifs(fn.c_str());
|
||||||
|
if (!ifs.is_open())
|
||||||
|
return false;
|
||||||
|
std::string str;
|
||||||
|
while (!ifs.eof())
|
||||||
|
{
|
||||||
|
std::getline( ifs, str );
|
||||||
|
if (!ifs.eof())
|
||||||
|
items.push_back(str);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ColumnFormatter::solve(int width)
|
||||||
|
{
|
||||||
|
bool fits = true;
|
||||||
|
int i = 1;
|
||||||
|
while (fits)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
std::vector<int> widths = divideItems(i);
|
||||||
|
int columnWidth = width / i;
|
||||||
|
for (int j = 0; j < widths.size(); ++j)
|
||||||
|
{
|
||||||
|
fits &= (widths[j] < columnWidth);
|
||||||
|
}
|
||||||
|
if (!fits)
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> ColumnFormatter::divideItems(int numColumns)
|
||||||
|
{
|
||||||
|
columns.clear();
|
||||||
|
for (int i = 0; i < numColumns; ++i)
|
||||||
|
columns.push_back(std::list<std::string>());
|
||||||
|
for (int i = 0; i < items.size(); ++i)
|
||||||
|
{
|
||||||
|
columns[i % numColumns].push_back(items[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// count the fattest item in each column
|
||||||
|
std::vector<int> res(numColumns);
|
||||||
|
for (int i = 0; i < numColumns; ++i)
|
||||||
|
{
|
||||||
|
for (std::list<std::string>::const_iterator it =
|
||||||
|
columns[i].begin(); it != columns[i].end(); ++it)
|
||||||
|
{
|
||||||
|
if (res[i] < it->size())
|
||||||
|
res[i] = it->size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColumnFormatter::format(int width)
|
||||||
|
{
|
||||||
|
m_formattedOutput.clear();
|
||||||
|
int cols = solve(width);
|
||||||
|
std::vector<int> colWidths(cols, width / cols);
|
||||||
|
int rem = width % cols;
|
||||||
|
for (int i = 0; i < rem; ++i)
|
||||||
|
{
|
||||||
|
colWidths[i]++;
|
||||||
|
}
|
||||||
|
divideItems(cols);
|
||||||
|
std::vector< std::list<std::string>::const_iterator > its;
|
||||||
|
std::vector< std::list<std::string>::const_iterator > it_ends;
|
||||||
|
for (int i = 0; i < columns.size(); ++i)
|
||||||
|
{
|
||||||
|
its.push_back(columns[i].begin());
|
||||||
|
it_ends.push_back(columns[i].end());
|
||||||
|
}
|
||||||
|
bool done = false;
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
std::stringstream row_ss;
|
||||||
|
for (int i = 0; i < columns.size(); ++i)
|
||||||
|
{
|
||||||
|
std::stringstream item_ss;
|
||||||
|
std::string item;
|
||||||
|
if (its[i] != it_ends[i])
|
||||||
|
{
|
||||||
|
item = *its[i];
|
||||||
|
++its[i];
|
||||||
|
}
|
||||||
|
item_ss << std::left << std::setw(colWidths[i]) << item;
|
||||||
|
row_ss << item_ss.str();
|
||||||
|
}
|
||||||
|
m_formattedOutput.push_back(row_ss.str());
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
for (int i = 0; i < columns.size(); ++i)
|
||||||
|
{
|
||||||
|
done &= (its[i] == it_ends[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<std::string>& ColumnFormatter::formattedOutput() const
|
||||||
|
{
|
||||||
|
return m_formattedOutput;
|
||||||
|
}
|
77
3rdparty/python-console/ColumnFormatter.h
vendored
Normal file
77
3rdparty/python-console/ColumnFormatter.h
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef COLUMN_FORMATTER_H
|
||||||
|
#define COLUMN_FORMATTER_H
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Format a list of items into as many columns as width permits.
|
||||||
|
*/
|
||||||
|
class ColumnFormatter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<std::string> items;
|
||||||
|
std::vector< std::list<std::string> > columns;
|
||||||
|
std::list< std::string > m_formattedOutput;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Load items from file, one item per line.
|
||||||
|
*/
|
||||||
|
bool load(const std::string& fn);
|
||||||
|
|
||||||
|
template <class InputIterator>
|
||||||
|
void setItems(InputIterator begin, InputIterator end)
|
||||||
|
{
|
||||||
|
items.clear();
|
||||||
|
for (InputIterator it = begin; it != end; ++it)
|
||||||
|
{
|
||||||
|
items.push_back(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Determine the number of columns that the items can be into, given a
|
||||||
|
width limit.
|
||||||
|
*/
|
||||||
|
int solve(int width);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Divide items into numColumns.
|
||||||
|
*/
|
||||||
|
std::vector<int> divideItems(int numColumns);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Generate formatted output, the items formatted into as many columns as can
|
||||||
|
be fit in width.
|
||||||
|
*/
|
||||||
|
void format(int width);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get output.
|
||||||
|
*/
|
||||||
|
const std::list<std::string>& formattedOutput() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COLUMN_FORMATTER_H
|
297
3rdparty/python-console/Console.cpp
vendored
Normal file
297
3rdparty/python-console/Console.cpp
vendored
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
#include "Console.h"
|
||||||
|
#include "Interpreter.h"
|
||||||
|
#include "ColumnFormatter.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QFont>
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
const QString Console::PROMPT = ">>> ";
|
||||||
|
const QString Console::MULTILINE_PROMPT = "... ";
|
||||||
|
const QColor Console::NORMAL_COLOR = QColor::fromRgbF( 0, 0, 0 );
|
||||||
|
const QColor Console::ERROR_COLOR = QColor::fromRgbF( 1.0, 0, 0 );
|
||||||
|
const QColor Console::OUTPUT_COLOR = QColor::fromRgbF( 0, 0, 1.0 );
|
||||||
|
|
||||||
|
Console::Console( QWidget* parent ):
|
||||||
|
QTextEdit( parent ),
|
||||||
|
m_interpreter( new Interpreter )
|
||||||
|
{
|
||||||
|
QFont font;
|
||||||
|
font.setFamily("Courier New");
|
||||||
|
setFont(font);
|
||||||
|
m_parseHelper.subscribe( this );
|
||||||
|
displayPrompt( );
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::~Console( )
|
||||||
|
{
|
||||||
|
delete m_interpreter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::keyPressEvent( QKeyEvent* e )
|
||||||
|
{
|
||||||
|
switch ( e->key() )
|
||||||
|
{
|
||||||
|
case Qt::Key_Return:
|
||||||
|
handleReturnKeyPress( );
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Qt::Key_Tab:
|
||||||
|
autocomplete( );
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Qt::Key_Backspace:
|
||||||
|
if ( ! canBackspace( ) )
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Up:
|
||||||
|
previousHistory( );
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Qt::Key_Down:
|
||||||
|
nextHistory( );
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Qt::Key_Left:
|
||||||
|
if ( ! canGoLeft( ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextEdit::keyPressEvent( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::handleReturnKeyPress( )
|
||||||
|
{
|
||||||
|
if ( ! cursorIsOnInputLine( ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString line = getLine( );
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << line.toStdString( ) << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_parseHelper.process( line.toStdString( ) );
|
||||||
|
if ( m_parseHelper.buffered( ) )
|
||||||
|
{
|
||||||
|
append("");
|
||||||
|
displayPrompt( );
|
||||||
|
}
|
||||||
|
if ( line.size( ) )
|
||||||
|
{
|
||||||
|
m_historyBuffer.push_back( line.toStdString( ) );
|
||||||
|
m_historyIt = m_historyBuffer.end();
|
||||||
|
}
|
||||||
|
moveCursorToEnd( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::parseEvent( const ParseMessage& message )
|
||||||
|
{
|
||||||
|
// handle invalid user input
|
||||||
|
if ( message.errorCode )
|
||||||
|
{
|
||||||
|
setTextColor( ERROR_COLOR );
|
||||||
|
append(message.message.c_str());
|
||||||
|
|
||||||
|
setTextColor( NORMAL_COLOR );
|
||||||
|
append("");
|
||||||
|
displayPrompt( );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// interpret valid user input
|
||||||
|
int errorCode;
|
||||||
|
std::string res;
|
||||||
|
if ( message.message.size() )
|
||||||
|
res = m_interpreter->interpret( message.message, &errorCode );
|
||||||
|
if ( errorCode )
|
||||||
|
{
|
||||||
|
setTextColor( ERROR_COLOR );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setTextColor( OUTPUT_COLOR );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( res.size( ) )
|
||||||
|
{
|
||||||
|
append(res.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
setTextColor( NORMAL_COLOR );
|
||||||
|
|
||||||
|
// set up the next line on the console
|
||||||
|
append("");
|
||||||
|
displayPrompt( );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Console::getLine( )
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
cursor.movePosition( QTextCursor::StartOfLine );
|
||||||
|
cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, Console::PROMPT.size( ) );
|
||||||
|
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
|
||||||
|
QString line = cursor.selectedText( );
|
||||||
|
cursor.clearSelection( );
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Console::cursorIsOnInputLine( )
|
||||||
|
{
|
||||||
|
int cursorBlock = textCursor( ).blockNumber( );
|
||||||
|
QTextCursor bottomCursor = textCursor( );
|
||||||
|
bottomCursor.movePosition( QTextCursor::End );
|
||||||
|
int bottomBlock = bottomCursor.blockNumber( );
|
||||||
|
return ( cursorBlock == bottomBlock );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Console::inputLineIsEmpty( )
|
||||||
|
{
|
||||||
|
QTextCursor bottomCursor = textCursor( );
|
||||||
|
bottomCursor.movePosition( QTextCursor::End );
|
||||||
|
int col = bottomCursor.columnNumber( );
|
||||||
|
return ( col == Console::PROMPT.size( ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Console::canBackspace( )
|
||||||
|
{
|
||||||
|
if ( ! cursorIsOnInputLine( ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( inputLineIsEmpty( ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Console::canGoLeft( )
|
||||||
|
{
|
||||||
|
if ( cursorIsOnInputLine( ) )
|
||||||
|
{
|
||||||
|
QTextCursor bottomCursor = textCursor( );
|
||||||
|
int col = bottomCursor.columnNumber( );
|
||||||
|
return (col > Console::PROMPT.size( ));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::displayPrompt( )
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
cursor.movePosition( QTextCursor::End );
|
||||||
|
if ( m_parseHelper.buffered( ) )
|
||||||
|
{
|
||||||
|
cursor.insertText( Console::MULTILINE_PROMPT );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor.insertText( Console::PROMPT );
|
||||||
|
}
|
||||||
|
cursor.movePosition( QTextCursor::EndOfLine );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::autocomplete( )
|
||||||
|
{
|
||||||
|
if ( ! cursorIsOnInputLine( ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString line = getLine( );
|
||||||
|
const std::list<std::string>& suggestions =
|
||||||
|
m_interpreter->suggest( line.toStdString( ) );
|
||||||
|
if (suggestions.size() == 1)
|
||||||
|
{
|
||||||
|
line = suggestions.back().c_str();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// try to complete to longest common prefix
|
||||||
|
std::string prefix =
|
||||||
|
LongestCommonPrefix(suggestions.begin(), suggestions.end());
|
||||||
|
if (prefix.size() > line.size())
|
||||||
|
{
|
||||||
|
line = prefix.c_str();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ColumnFormatter fmt;
|
||||||
|
fmt.setItems(suggestions.begin(), suggestions.end());
|
||||||
|
fmt.format(width() / 10);
|
||||||
|
setTextColor( OUTPUT_COLOR );
|
||||||
|
const std::list<std::string>& formatted = fmt.formattedOutput();
|
||||||
|
for (std::list<std::string>::const_iterator it = formatted.begin();
|
||||||
|
it != formatted.end(); ++it)
|
||||||
|
{
|
||||||
|
append(it->c_str());
|
||||||
|
}
|
||||||
|
std::cout << width() << "\n";
|
||||||
|
setTextColor( NORMAL_COLOR );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up the next line on the console
|
||||||
|
append("");
|
||||||
|
displayPrompt( );
|
||||||
|
moveCursorToEnd( );
|
||||||
|
cursor.insertText( line );
|
||||||
|
moveCursorToEnd( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::previousHistory( )
|
||||||
|
{
|
||||||
|
if ( ! cursorIsOnInputLine( ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! m_historyBuffer.size( ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
cursor.movePosition( QTextCursor::StartOfLine );
|
||||||
|
cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, Console::PROMPT.size( ) );
|
||||||
|
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
|
||||||
|
cursor.removeSelectedText( );
|
||||||
|
if ( m_historyIt != m_historyBuffer.begin( ) )
|
||||||
|
{
|
||||||
|
--m_historyIt;
|
||||||
|
}
|
||||||
|
cursor.insertText( m_historyIt->c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::nextHistory( )
|
||||||
|
{
|
||||||
|
if ( ! cursorIsOnInputLine( ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! m_historyBuffer.size( ) )
|
||||||
|
return;
|
||||||
|
if ( m_historyIt == m_historyBuffer.end( ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
cursor.movePosition( QTextCursor::StartOfLine );
|
||||||
|
cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, Console::PROMPT.size( ) );
|
||||||
|
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
|
||||||
|
cursor.removeSelectedText( );
|
||||||
|
++m_historyIt;
|
||||||
|
if ( m_historyIt == m_historyBuffer.end( ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cursor.insertText( m_historyIt->c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::moveCursorToEnd( )
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
cursor.movePosition( QTextCursor::End );
|
||||||
|
setTextCursor( cursor );
|
||||||
|
}
|
78
3rdparty/python-console/Console.h
vendored
Normal file
78
3rdparty/python-console/Console.h
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
python-console
|
||||||
|
Copyright (C) 2018 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ATSUI_CONSOLE_H
|
||||||
|
#define ATSUI_CONSOLE_H
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QColor>
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
#include "ParseListener.h"
|
||||||
|
|
||||||
|
class QWidget;
|
||||||
|
class QKeyEvent;
|
||||||
|
class Interpreter;
|
||||||
|
|
||||||
|
class Console : public QTextEdit, ParseListener
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Console( QWidget* parent = 0 );
|
||||||
|
virtual ~Console( );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// override QTextEdit
|
||||||
|
virtual void keyPressEvent( QKeyEvent* e );
|
||||||
|
|
||||||
|
virtual void handleReturnKeyPress( );
|
||||||
|
|
||||||
|
/**
|
||||||
|
Handle a compilable chunk of Python user input.
|
||||||
|
*/
|
||||||
|
virtual void parseEvent( const ParseMessage& message );
|
||||||
|
|
||||||
|
QString getLine( );
|
||||||
|
bool cursorIsOnInputLine( );
|
||||||
|
bool inputLineIsEmpty( );
|
||||||
|
bool canBackspace( );
|
||||||
|
bool canGoLeft( );
|
||||||
|
void displayPrompt( );
|
||||||
|
void autocomplete( );
|
||||||
|
void previousHistory( );
|
||||||
|
void nextHistory( );
|
||||||
|
void moveCursorToEnd( );
|
||||||
|
|
||||||
|
static const QString PROMPT;
|
||||||
|
static const QString MULTILINE_PROMPT;
|
||||||
|
|
||||||
|
static const QColor NORMAL_COLOR;
|
||||||
|
static const QColor ERROR_COLOR;
|
||||||
|
static const QColor OUTPUT_COLOR;
|
||||||
|
|
||||||
|
Interpreter* m_interpreter;
|
||||||
|
ParseHelper m_parseHelper;
|
||||||
|
std::list<std::string> m_historyBuffer;
|
||||||
|
std::list<std::string>::const_iterator m_historyIt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ATSUI_CONSOLE_H
|
231
3rdparty/python-console/Interpreter.cpp
vendored
Normal file
231
3rdparty/python-console/Interpreter.cpp
vendored
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
#include "Interpreter.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
|
PyThreadState* Interpreter::MainThreadState = NULL;
|
||||||
|
|
||||||
|
Interpreter::Interpreter( )
|
||||||
|
{
|
||||||
|
PyEval_AcquireLock( );
|
||||||
|
m_threadState = Py_NewInterpreter( );
|
||||||
|
|
||||||
|
PyObject *module = PyImport_ImportModule("__main__");
|
||||||
|
loc = glb = PyModule_GetDict(module);
|
||||||
|
SetupRedirector( m_threadState );
|
||||||
|
PyRun_SimpleString("import sys\n"
|
||||||
|
"import redirector\n"
|
||||||
|
"sys.path.insert(0, \".\")\n" // add current path
|
||||||
|
"sys.stdout = redirector.redirector()\n"
|
||||||
|
"sys.stderr = sys.stdout\n"
|
||||||
|
"import rlcompleter\n"
|
||||||
|
"sys.completer = rlcompleter.Completer()\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
PyEval_ReleaseThread( m_threadState );
|
||||||
|
}
|
||||||
|
|
||||||
|
Interpreter::~Interpreter( )
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "delete interpreter\n";
|
||||||
|
#endif
|
||||||
|
PyEval_AcquireThread( m_threadState );
|
||||||
|
Py_EndInterpreter( m_threadState );
|
||||||
|
PyEval_ReleaseLock( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Interpreter::test( )
|
||||||
|
{
|
||||||
|
PyEval_AcquireThread( m_threadState );
|
||||||
|
|
||||||
|
PyObject* py_result;
|
||||||
|
PyObject* dum;
|
||||||
|
std::string command = "print 'Hello world'\n";
|
||||||
|
py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input);
|
||||||
|
if ( py_result == 0 )
|
||||||
|
{
|
||||||
|
std::cout << "Huh?\n";
|
||||||
|
PyEval_ReleaseThread( m_threadState );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dum = PyEval_EvalCode ((PyCodeObject *)py_result, glb, loc);
|
||||||
|
Py_XDECREF (dum);
|
||||||
|
Py_XDECREF (py_result);
|
||||||
|
|
||||||
|
std::cout << GetResultString( m_threadState );
|
||||||
|
GetResultString( m_threadState ) = "";
|
||||||
|
|
||||||
|
PyEval_ReleaseThread( m_threadState );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Interpreter::interpret( const std::string& command, int* errorCode )
|
||||||
|
{
|
||||||
|
PyEval_AcquireThread( m_threadState );
|
||||||
|
*errorCode = 0;
|
||||||
|
|
||||||
|
PyObject* py_result;
|
||||||
|
PyObject* dum;
|
||||||
|
std::string res;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "interpreting (" << command << ")\n";
|
||||||
|
#endif
|
||||||
|
py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input);
|
||||||
|
if ( py_result == 0 )
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "Huh?\n";
|
||||||
|
#endif
|
||||||
|
if ( PyErr_Occurred( ) )
|
||||||
|
{
|
||||||
|
*errorCode = 1;
|
||||||
|
PyErr_Print( );
|
||||||
|
res = GetResultString( m_threadState );
|
||||||
|
GetResultString( m_threadState ) = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
PyEval_ReleaseThread( m_threadState );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
dum = PyEval_EvalCode ((PyCodeObject *)py_result, glb, loc);
|
||||||
|
Py_XDECREF (dum);
|
||||||
|
Py_XDECREF (py_result);
|
||||||
|
if ( PyErr_Occurred( ) )
|
||||||
|
{
|
||||||
|
*errorCode = 1;
|
||||||
|
PyErr_Print( );
|
||||||
|
}
|
||||||
|
|
||||||
|
res = GetResultString( m_threadState );
|
||||||
|
GetResultString( m_threadState ) = "";
|
||||||
|
|
||||||
|
PyEval_ReleaseThread( m_threadState );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<std::string>& Interpreter::suggest( const std::string& hint )
|
||||||
|
{
|
||||||
|
PyEval_AcquireThread( m_threadState );
|
||||||
|
m_suggestions.clear();
|
||||||
|
int i = 0;
|
||||||
|
std::string command = boost::str(
|
||||||
|
boost::format("sys.completer.complete('%1%', %2%)\n")
|
||||||
|
% hint
|
||||||
|
% i);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << command << "\n";
|
||||||
|
#endif
|
||||||
|
std::string res;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
PyObject* py_result;
|
||||||
|
PyObject* dum;
|
||||||
|
py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input);
|
||||||
|
dum = PyEval_EvalCode ((PyCodeObject *)py_result, glb, loc);
|
||||||
|
Py_XDECREF (dum);
|
||||||
|
Py_XDECREF (py_result);
|
||||||
|
res = GetResultString( m_threadState );
|
||||||
|
GetResultString( m_threadState ) = "";
|
||||||
|
++i;
|
||||||
|
command = boost::str(
|
||||||
|
boost::format("sys.completer.complete('%1%', %2%)\n")
|
||||||
|
% hint
|
||||||
|
% i);
|
||||||
|
if (res.size())
|
||||||
|
{
|
||||||
|
// throw away the newline
|
||||||
|
res = res.substr(1, res.size() - 3);
|
||||||
|
m_suggestions.push_back(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (res.size());
|
||||||
|
|
||||||
|
PyEval_ReleaseThread( m_threadState );
|
||||||
|
return m_suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Interpreter::Initialize( )
|
||||||
|
{
|
||||||
|
Py_Initialize( );
|
||||||
|
PyEval_InitThreads( );
|
||||||
|
MainThreadState = PyEval_SaveThread( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Interpreter::Finalize( )
|
||||||
|
{
|
||||||
|
PyEval_RestoreThread( MainThreadState );
|
||||||
|
Py_Finalize( );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string& Interpreter::GetResultString( PyThreadState* threadState )
|
||||||
|
{
|
||||||
|
static std::map< PyThreadState*, std::string > ResultStrings;
|
||||||
|
if ( !ResultStrings.count( threadState ) )
|
||||||
|
{
|
||||||
|
ResultStrings[ threadState ] = "";
|
||||||
|
}
|
||||||
|
return ResultStrings[ threadState ];
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* Interpreter::RedirectorInit(PyObject *, PyObject *)
|
||||||
|
{
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* Interpreter::RedirectorWrite(PyObject *, PyObject *args)
|
||||||
|
{
|
||||||
|
char* output;
|
||||||
|
PyObject *selfi;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args,"Os",&selfi,&output))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string outputString( output );
|
||||||
|
PyThreadState* currentThread = PyThreadState_Get( );
|
||||||
|
std::string& resultString = GetResultString( currentThread );
|
||||||
|
resultString = resultString + outputString;
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyMethodDef Interpreter::ModuleMethods[] = { {NULL,NULL,0,NULL} };
|
||||||
|
PyMethodDef Interpreter::RedirectorMethods[] =
|
||||||
|
{
|
||||||
|
{"__init__", Interpreter::RedirectorInit, METH_VARARGS,
|
||||||
|
"initialize the stdout/err redirector"},
|
||||||
|
{"write", Interpreter::RedirectorWrite, METH_VARARGS,
|
||||||
|
"implement the write method to redirect stdout/err"},
|
||||||
|
{NULL,NULL,0,NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
void Interpreter::SetupRedirector( PyThreadState* threadState )
|
||||||
|
{
|
||||||
|
PyMethodDef *def;
|
||||||
|
|
||||||
|
/* create a new module and class */
|
||||||
|
PyObject *module = Py_InitModule("redirector", ModuleMethods);
|
||||||
|
PyObject *moduleDict = PyModule_GetDict(module);
|
||||||
|
PyObject *classDict = PyDict_New();
|
||||||
|
PyObject *className = PyString_FromString("redirector");
|
||||||
|
PyObject *fooClass = PyClass_New(NULL, classDict, className);
|
||||||
|
PyDict_SetItemString(moduleDict, "redirector", fooClass);
|
||||||
|
Py_DECREF(classDict);
|
||||||
|
Py_DECREF(className);
|
||||||
|
Py_DECREF(fooClass);
|
||||||
|
|
||||||
|
/* add methods to class */
|
||||||
|
for (def = RedirectorMethods; def->ml_name != NULL; def++) {
|
||||||
|
PyObject *func = PyCFunction_New(def, NULL);
|
||||||
|
PyObject *method = PyMethod_New(func, NULL, fooClass);
|
||||||
|
PyDict_SetItemString(classDict, def->ml_name, method);
|
||||||
|
Py_DECREF(func);
|
||||||
|
Py_DECREF(method);
|
||||||
|
}
|
||||||
|
}
|
97
3rdparty/python-console/Interpreter.h
vendored
Normal file
97
3rdparty/python-console/Interpreter.h
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
python-console
|
||||||
|
Copyright (C) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INTERPRETER_H
|
||||||
|
#define INTERPRETER_H
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <Python.h>
|
||||||
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
|
/*
|
||||||
|
* The following undefs for C standard library macros prevent
|
||||||
|
* build errors of the following type on mac ox 10.7.4 and XCode 4.3.3
|
||||||
|
*
|
||||||
|
/usr/include/c++/4.2.1/bits/localefwd.h:57:21: error: too many arguments provided to function-like macro invocation
|
||||||
|
isspace(_CharT, const locale&);
|
||||||
|
^
|
||||||
|
/usr/include/c++/4.2.1/bits/localefwd.h:56:5: error: 'inline' can only appear on functions
|
||||||
|
inline bool
|
||||||
|
^
|
||||||
|
/usr/include/c++/4.2.1/bits/localefwd.h:57:5: error: variable 'isspace' declared as a template
|
||||||
|
isspace(_CharT, const locale&);
|
||||||
|
^
|
||||||
|
*/
|
||||||
|
#undef isspace
|
||||||
|
#undef isupper
|
||||||
|
#undef islower
|
||||||
|
#undef isalpha
|
||||||
|
#undef isalnum
|
||||||
|
#undef toupper
|
||||||
|
#undef tolower
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Wraps a Python interpreter, which you can pass commands as strings to interpret
|
||||||
|
and get strings of output/error in return.
|
||||||
|
*/
|
||||||
|
class Interpreter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
static PyThreadState* MainThreadState;
|
||||||
|
|
||||||
|
PyThreadState* m_threadState;
|
||||||
|
PyObject* glb;
|
||||||
|
PyObject* loc;
|
||||||
|
|
||||||
|
std::list< std::string > m_suggestions;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Instantiate a Python interpreter.
|
||||||
|
*/
|
||||||
|
Interpreter( );
|
||||||
|
virtual ~Interpreter( );
|
||||||
|
|
||||||
|
void test( );
|
||||||
|
std::string interpret( const std::string& command, int* errorCode );
|
||||||
|
const std::list<std::string>& suggest( const std::string& hint );
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call this before constructing and using Interpreter.
|
||||||
|
*/
|
||||||
|
static void Initialize( );
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call this when done using Interpreter.
|
||||||
|
*/
|
||||||
|
static void Finalize( );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void SetupRedirector( PyThreadState* threadState );
|
||||||
|
static PyObject* RedirectorInit(PyObject *, PyObject *);
|
||||||
|
static PyObject* RedirectorWrite(PyObject *, PyObject *args);
|
||||||
|
static std::string& GetResultString( PyThreadState* threadState );
|
||||||
|
static PyMethodDef ModuleMethods[];
|
||||||
|
static PyMethodDef RedirectorMethods[];
|
||||||
|
};
|
||||||
|
#endif // INTERPRETER_H
|
19
3rdparty/python-console/LICENSE
vendored
Normal file
19
3rdparty/python-console/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright 2018 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
174
3rdparty/python-console/ParseHelper.BlockParseState.cpp
vendored
Normal file
174
3rdparty/python-console/ParseHelper.BlockParseState.cpp
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
|
||||||
|
ParseHelper::BlockParseState::
|
||||||
|
BlockParseState( ParseHelper& parent ):
|
||||||
|
ParseState( parent )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ParseHelper::BlockParseState::
|
||||||
|
BlockParseState( ParseHelper& parent, const std::string& indent_ ):
|
||||||
|
ParseState( parent ),
|
||||||
|
indent( indent_ )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool ParseHelper::BlockParseState::
|
||||||
|
process(const std::string& str)
|
||||||
|
{
|
||||||
|
bool ok = initializeIndent(str);
|
||||||
|
if ( ! ok )
|
||||||
|
{
|
||||||
|
// finish processing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Indent ind;
|
||||||
|
bool isIndented = PeekIndent( str, &ind );
|
||||||
|
if ( isIndented )
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "current line indent: ";
|
||||||
|
print( ind );
|
||||||
|
#endif
|
||||||
|
// check if indent matches
|
||||||
|
if ( ind.Token != indent.Token )
|
||||||
|
{
|
||||||
|
// dedent until we match or empty the stack
|
||||||
|
bool found = false;
|
||||||
|
while ( !found )
|
||||||
|
{
|
||||||
|
parent.stateStack.pop_back( );
|
||||||
|
if ( !parent.stateStack.size( ) )
|
||||||
|
break;
|
||||||
|
boost::shared_ptr<BlockParseState> parseState =
|
||||||
|
boost::dynamic_pointer_cast<BlockParseState>(
|
||||||
|
parent.stateStack.back( ));
|
||||||
|
found = ( ind.Token == parseState->indent.Token );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! found )
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "indent mismatch\n";
|
||||||
|
#endif
|
||||||
|
parent.reset( );
|
||||||
|
ParseMessage msg( 1, "IndentationError: unexpected indent");
|
||||||
|
parent.broadcast( msg );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// process command
|
||||||
|
|
||||||
|
// enter indented block state
|
||||||
|
if ( str[str.size()-1] == ':' )
|
||||||
|
{
|
||||||
|
parent.commandBuffer.push_back( str );
|
||||||
|
//parent.inBlock = (boost::dynamic_pointer_cast<BlockParseState>(
|
||||||
|
// parent.stateStack.back()));
|
||||||
|
|
||||||
|
//expectingIndent = true;
|
||||||
|
boost::shared_ptr<ParseState> parseState(
|
||||||
|
new BlockParseState( parent ) );
|
||||||
|
parent.stateStack.push_back( parseState );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( str[str.size()-1] == '\\' )
|
||||||
|
{
|
||||||
|
parent.commandBuffer.push_back( str );
|
||||||
|
boost::shared_ptr<ParseState> parseState(
|
||||||
|
new ContinuationParseState( parent ) );
|
||||||
|
parent.stateStack.push_back( parseState );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BracketParseState::HasOpenBrackets( str ))
|
||||||
|
{
|
||||||
|
// FIXME: Every parse state should have its own local buffer
|
||||||
|
boost::shared_ptr<ParseState> parseState(
|
||||||
|
new BracketParseState( parent, str ) );
|
||||||
|
parent.stateStack.push_back( parseState );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.commandBuffer.push_back( str );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( str.size() )
|
||||||
|
{
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "Expected indented block\n";
|
||||||
|
#endif
|
||||||
|
parent.reset( );
|
||||||
|
ParseMessage msg( 1, "IndentationError: expected an indented block" );
|
||||||
|
parent.broadcast( msg );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "Leaving block\n";
|
||||||
|
#endif
|
||||||
|
parent.stateStack.pop_back();
|
||||||
|
parent.flush( );
|
||||||
|
parent.reset( );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseHelper::BlockParseState::
|
||||||
|
initializeIndent(const std::string& str)
|
||||||
|
{
|
||||||
|
bool expectingIndent = (indent.Token == "");
|
||||||
|
if ( !expectingIndent )
|
||||||
|
{
|
||||||
|
std::cout << "already initialized indent: ";
|
||||||
|
print( indent );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Indent ind;
|
||||||
|
bool isIndented = parent.PeekIndent( str, &ind );
|
||||||
|
if ( !isIndented )
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "Expected indented block\n";
|
||||||
|
#endif
|
||||||
|
parent.reset( );
|
||||||
|
ParseMessage msg( 1, "IndentationError: expected an indented block" );
|
||||||
|
parent.broadcast( msg );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
indent = ind;
|
||||||
|
//parent.currentIndent = ind;
|
||||||
|
//parent.indentStack.push_back( parent.currentIndent );
|
||||||
|
//parent.expectingIndent = false;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "initializing indent: ";
|
||||||
|
print( ind );
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
127
3rdparty/python-console/ParseHelper.BracketParseState.cpp
vendored
Normal file
127
3rdparty/python-console/ParseHelper.BracketParseState.cpp
vendored
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
const std::string ParseHelper::BracketParseState::OpeningBrackets = "[({";
|
||||||
|
const std::string ParseHelper::BracketParseState::ClosingBrackets = "])}";
|
||||||
|
|
||||||
|
bool ParseHelper::BracketParseState::HasOpenBrackets(const std::string& str)
|
||||||
|
{
|
||||||
|
std::list<char> brackets;
|
||||||
|
bool hasOpenBrackets = LoadBrackets(str, &brackets);
|
||||||
|
return hasOpenBrackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseHelper::BracketParseState::LoadBrackets(const std::string& str,
|
||||||
|
std::list<char>* stack)
|
||||||
|
{
|
||||||
|
if ( !stack )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
stack->clear();
|
||||||
|
for (int i = 0; i < str.size(); ++i)
|
||||||
|
{
|
||||||
|
if (OpeningBrackets.find_first_of(str[i]) != std::string::npos)
|
||||||
|
{
|
||||||
|
stack->push_back(str[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t t = ClosingBrackets.find_first_of(str[i]);
|
||||||
|
if (t != std::string::npos)
|
||||||
|
{
|
||||||
|
if (t != OpeningBrackets.find_first_of(stack->back()))
|
||||||
|
return false;
|
||||||
|
stack->pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseHelper::BracketParseState::BracketParseState( ParseHelper& parent, const std::string& firstLine ):
|
||||||
|
ParseState( parent )
|
||||||
|
{
|
||||||
|
bool hasOpenBrackets = LoadBrackets( firstLine, &brackets );
|
||||||
|
assert( hasOpenBrackets );
|
||||||
|
m_buffer.push_back( firstLine );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseHelper::BracketParseState::process(const std::string& str)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "(BracketParseState) processing " << str << "\n";
|
||||||
|
#endif
|
||||||
|
// update brackets stack
|
||||||
|
for (int i = 0; i < str.size(); ++i)
|
||||||
|
{
|
||||||
|
if (OpeningBrackets.find_first_of(str[i]) != std::string::npos)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "push " << str[i] << "\n";
|
||||||
|
#endif
|
||||||
|
brackets.push_back(str[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t t = ClosingBrackets.find_first_of(str[i]);
|
||||||
|
if (t != std::string::npos)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "pop " << str[i] << "\n";
|
||||||
|
#endif
|
||||||
|
// reset state if unmatched brackets seen
|
||||||
|
if (t != OpeningBrackets.find_first_of(brackets.back()))
|
||||||
|
{
|
||||||
|
parent.reset( );
|
||||||
|
ParseMessage msg(1, "Invalid syntax");
|
||||||
|
parent.broadcast( msg );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
brackets.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've cleared the stack, we've finished accepting input here
|
||||||
|
if (!brackets.size())
|
||||||
|
{
|
||||||
|
// squash buffered lines and place it on parent::commandBuffer
|
||||||
|
std::stringstream ss;
|
||||||
|
for (std::list<std::string>::const_iterator it = m_buffer.begin();
|
||||||
|
it != m_buffer.end(); ++it )
|
||||||
|
{
|
||||||
|
ss << *it << "\n";
|
||||||
|
}
|
||||||
|
ss << str;
|
||||||
|
parent.commandBuffer.push_back(ss.str());
|
||||||
|
parent.stateStack.pop_back( );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// buffer and expect more lines
|
||||||
|
m_buffer.push_back( str );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
61
3rdparty/python-console/ParseHelper.ContinuationParseState.cpp
vendored
Normal file
61
3rdparty/python-console/ParseHelper.ContinuationParseState.cpp
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
#include <list>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
ParseHelper::ContinuationParseState::
|
||||||
|
ContinuationParseState( ParseHelper& parent_ ):
|
||||||
|
ParseState( parent_ )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool ParseHelper::ContinuationParseState::
|
||||||
|
process( const std::string& str )
|
||||||
|
{
|
||||||
|
if ( str.size() && str[str.size()-1] == '\\' )
|
||||||
|
{
|
||||||
|
parent.commandBuffer.push_back( str );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::list<std::string> tmp_list;
|
||||||
|
tmp_list.push_back(str);
|
||||||
|
while (parent.commandBuffer.size() && parent.commandBuffer.back()[
|
||||||
|
parent.commandBuffer.back().size()-1] == '\\')
|
||||||
|
{
|
||||||
|
tmp_list.push_back(parent.commandBuffer.back());
|
||||||
|
parent.commandBuffer.pop_back();
|
||||||
|
}
|
||||||
|
std::stringstream ss;
|
||||||
|
while (tmp_list.size())
|
||||||
|
{
|
||||||
|
ss << tmp_list.back();
|
||||||
|
tmp_list.pop_back();
|
||||||
|
if (tmp_list.size())
|
||||||
|
ss << "\n";
|
||||||
|
}
|
||||||
|
parent.commandBuffer.push_back(ss.str());
|
||||||
|
parent.stateStack.pop_back();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
225
3rdparty/python-console/ParseHelper.cpp
vendored
Normal file
225
3rdparty/python-console/ParseHelper.cpp
vendored
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "ParseListener.h"
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void print(const ParseHelper::Indent& indent)
|
||||||
|
{
|
||||||
|
std::string str = indent.Token;
|
||||||
|
for (int i = 0; i < str.size(); ++i)
|
||||||
|
{
|
||||||
|
switch (str.at(i))
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
str[i] = 's';
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
str[i] = 't';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << str << "\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ParseHelper::Indent::
|
||||||
|
Indent( )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ParseHelper::Indent::
|
||||||
|
Indent( const std::string& indent ):
|
||||||
|
Token( indent )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ParseHelper::ParseState::
|
||||||
|
ParseState( ParseHelper& parent_ ): parent( parent_ )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ParseHelper::ParseState::
|
||||||
|
~ParseState( )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool ParseHelper::PeekIndent( const std::string& str, Indent* indent )
|
||||||
|
{
|
||||||
|
if ( !str.size() || ! isspace(str[0]) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int nonwhitespaceIndex = -1;
|
||||||
|
for (int i = 0; i < str.size(); ++i)
|
||||||
|
{
|
||||||
|
if (!isspace(str[i]))
|
||||||
|
{
|
||||||
|
nonwhitespaceIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nonwhitespaceIndex == -1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string indentToken = str.substr(0, nonwhitespaceIndex);
|
||||||
|
indent->Token = indentToken;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseHelper::ParseHelper( )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void ParseHelper::process( const std::string& str )
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "processing: (" << str << ")\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string top;
|
||||||
|
commandBuffer.push_back(str);
|
||||||
|
//std::string top = commandBuffer.back();
|
||||||
|
//commandBuffer.pop_back();
|
||||||
|
boost::shared_ptr<ParseState> blockStatePtr;
|
||||||
|
while (stateStack.size())
|
||||||
|
{
|
||||||
|
top = commandBuffer.back();
|
||||||
|
commandBuffer.pop_back();
|
||||||
|
blockStatePtr = stateStack.back();
|
||||||
|
if (blockStatePtr->process(top))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! commandBuffer.size() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// standard state
|
||||||
|
top = commandBuffer.back();
|
||||||
|
if ( !top.size() )
|
||||||
|
{
|
||||||
|
reset( );
|
||||||
|
broadcast( std::string() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "now processing: (" << top << ")\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ // check for unexpected indent
|
||||||
|
Indent ind;
|
||||||
|
bool isIndented = PeekIndent( top, &ind );
|
||||||
|
if ( isIndented &&
|
||||||
|
! isInContinuation( ) )
|
||||||
|
{
|
||||||
|
reset( );
|
||||||
|
ParseMessage msg( 1, "IndentationError: unexpected indent");
|
||||||
|
broadcast( msg );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// enter indented block state
|
||||||
|
if ( top[top.size()-1] == ':' )
|
||||||
|
{
|
||||||
|
boost::shared_ptr<ParseState> parseState(
|
||||||
|
new BlockParseState( *this ) );
|
||||||
|
stateStack.push_back( parseState );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( top[top.size()-1] == '\\' )
|
||||||
|
{
|
||||||
|
boost::shared_ptr<ParseState> parseState(
|
||||||
|
new ContinuationParseState( *this ) );
|
||||||
|
stateStack.push_back( parseState );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BracketParseState::HasOpenBrackets( top ))
|
||||||
|
{
|
||||||
|
// FIXME: Every parse state should have its own local buffer
|
||||||
|
commandBuffer.pop_back( );
|
||||||
|
boost::shared_ptr<ParseState> parseState(
|
||||||
|
new BracketParseState( *this, top ) );
|
||||||
|
stateStack.push_back( parseState );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle single-line statement
|
||||||
|
flush( );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseHelper::buffered( ) const
|
||||||
|
{
|
||||||
|
return commandBuffer.size( ) || stateStack.size( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseHelper::flush( )
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
for (int i = 0; i < commandBuffer.size(); ++i )
|
||||||
|
{
|
||||||
|
ss << commandBuffer[i] << "\n";
|
||||||
|
}
|
||||||
|
commandBuffer.clear();
|
||||||
|
|
||||||
|
broadcast( ss.str() );
|
||||||
|
// TODO: feed string to interpreter
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseHelper::reset( )
|
||||||
|
{
|
||||||
|
// inContinuation = false;
|
||||||
|
stateStack.clear( );
|
||||||
|
commandBuffer.clear( );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseHelper::isInContinuation( ) const
|
||||||
|
{
|
||||||
|
return (stateStack.size()
|
||||||
|
&& (boost::dynamic_pointer_cast<ContinuationParseState>(
|
||||||
|
stateStack.back())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseHelper::subscribe( ParseListener* listener )
|
||||||
|
{
|
||||||
|
listeners.push_back( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseHelper::unsubscribeAll( )
|
||||||
|
{
|
||||||
|
listeners.clear( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseHelper::broadcast( const ParseMessage& msg )
|
||||||
|
{
|
||||||
|
// broadcast signal
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
if (listeners[i])
|
||||||
|
{
|
||||||
|
listeners[i]->parseEvent(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
169
3rdparty/python-console/ParseHelper.h
vendored
Normal file
169
3rdparty/python-console/ParseHelper.h
vendored
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PARSE_HELPER_H
|
||||||
|
#define PARSE_HELPER_H
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include "ParseMessage.h"
|
||||||
|
|
||||||
|
class ParseListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helps chunk lines of Python code into compilable statements.
|
||||||
|
*/
|
||||||
|
class ParseHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Indent
|
||||||
|
{
|
||||||
|
std::string Token;
|
||||||
|
Indent( );
|
||||||
|
Indent( const std::string& indent );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Handle different states of parsing. Subclasses override
|
||||||
|
process(const std::string&) to handle different types of multiline
|
||||||
|
statements.
|
||||||
|
*/
|
||||||
|
struct ParseState
|
||||||
|
{
|
||||||
|
ParseHelper& parent;
|
||||||
|
ParseState( ParseHelper& parent_ );
|
||||||
|
virtual ~ParseState( );
|
||||||
|
|
||||||
|
/**
|
||||||
|
Processes a single line of user input.
|
||||||
|
|
||||||
|
Subclasses should return false if further processing should be done. In
|
||||||
|
this case, the command buffer should be topped by the next statement to
|
||||||
|
parse.
|
||||||
|
|
||||||
|
\return whether processing of the line is done.
|
||||||
|
*/
|
||||||
|
virtual bool process(const std::string& str) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContinuationParseState : public ParseState
|
||||||
|
{
|
||||||
|
using ParseState::parent;
|
||||||
|
ContinuationParseState( ParseHelper& parent_ );
|
||||||
|
virtual bool process( const std::string& str);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Handle parsing a multiline indented block. Example of such a block:
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
print i
|
||||||
|
print i*i
|
||||||
|
|
||||||
|
*/
|
||||||
|
struct BlockParseState : public ParseState
|
||||||
|
{
|
||||||
|
Indent indent;
|
||||||
|
|
||||||
|
BlockParseState( ParseHelper& parent );
|
||||||
|
BlockParseState( ParseHelper& parent, const std::string& indent_ );
|
||||||
|
|
||||||
|
// return whether processing is finished
|
||||||
|
virtual bool process(const std::string& str);
|
||||||
|
|
||||||
|
// return if there was an error
|
||||||
|
bool initializeIndent(const std::string& str);
|
||||||
|
};
|
||||||
|
friend class BlockParseState;
|
||||||
|
|
||||||
|
struct BracketParseState : public ParseState
|
||||||
|
{
|
||||||
|
static const std::string OpeningBrackets;
|
||||||
|
static const std::string ClosingBrackets;
|
||||||
|
|
||||||
|
std::list<char> brackets;
|
||||||
|
std::list<std::string> m_buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return whether open brackets remain unclosed in \a str.
|
||||||
|
*/
|
||||||
|
static bool HasOpenBrackets(const std::string& str);
|
||||||
|
static bool LoadBrackets(const std::string& str,
|
||||||
|
std::list<char>* stack);
|
||||||
|
|
||||||
|
BracketParseState( ParseHelper& parent, const std::string& firstLine );
|
||||||
|
|
||||||
|
virtual bool process(const std::string& str);
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// TODO: Create a ContinuationParseState to handle this
|
||||||
|
bool inContinuation;
|
||||||
|
std::vector< ParseListener* > listeners;
|
||||||
|
std::vector< boost::shared_ptr< ParseState > > stateStack;
|
||||||
|
std::vector< std::string > commandBuffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool PeekIndent( const std::string& str, Indent* indent );
|
||||||
|
|
||||||
|
public:
|
||||||
|
ParseHelper( );
|
||||||
|
|
||||||
|
public:
|
||||||
|
void process( const std::string& str );
|
||||||
|
|
||||||
|
bool buffered( ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Generate a parse event from the current command buffer.
|
||||||
|
*/
|
||||||
|
void flush( );
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the state of the helper.
|
||||||
|
*/
|
||||||
|
void reset( );
|
||||||
|
|
||||||
|
bool isInContinuation( ) const;
|
||||||
|
|
||||||
|
void subscribe( ParseListener* listener );
|
||||||
|
void unsubscribeAll( );
|
||||||
|
void broadcast( const ParseMessage& msg );
|
||||||
|
|
||||||
|
}; // class ParseHelper
|
||||||
|
|
||||||
|
inline bool operator== ( const ParseHelper::Indent& a, const ParseHelper::Indent& b )
|
||||||
|
{
|
||||||
|
return a.Token == b.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!= ( const ParseHelper::Indent& a, const ParseHelper::Indent& b )
|
||||||
|
{
|
||||||
|
return a.Token != b.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void print(const ParseHelper::Indent& indent);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // PARSE_HELPER_H
|
29
3rdparty/python-console/ParseListener.cpp
vendored
Normal file
29
3rdparty/python-console/ParseListener.cpp
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ParseListener.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void EchoListener::parseEvent( const ParseMessage& msg )
|
||||||
|
{
|
||||||
|
std::cout << "echo(" << msg.errorCode << "): " << msg.message << "\n";
|
||||||
|
}
|
||||||
|
|
42
3rdparty/python-console/ParseListener.h
vendored
Normal file
42
3rdparty/python-console/ParseListener.h
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef PARSE_LISTENER_H
|
||||||
|
#define PARSE_LISTENER_H
|
||||||
|
#include "ParseMessage.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Interface to implement to receive parse events.
|
||||||
|
*/
|
||||||
|
struct ParseListener
|
||||||
|
{
|
||||||
|
virtual void parseEvent( const ParseMessage& msg ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sample implementation of ParseListener that echoes messages.
|
||||||
|
*/
|
||||||
|
struct EchoListener : public ParseListener
|
||||||
|
{
|
||||||
|
virtual void parseEvent( const ParseMessage& msg );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PARSE_LISTENER_H
|
31
3rdparty/python-console/ParseMessage.cpp
vendored
Normal file
31
3rdparty/python-console/ParseMessage.cpp
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ParseMessage.h"
|
||||||
|
|
||||||
|
ParseMessage::ParseMessage( const std::string& msg ):
|
||||||
|
errorCode( 0 ), message( msg )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ParseMessage::ParseMessage( int code, const std::string& msg ):
|
||||||
|
errorCode( code ), message( msg )
|
||||||
|
{ }
|
||||||
|
|
38
3rdparty/python-console/ParseMessage.h
vendored
Normal file
38
3rdparty/python-console/ParseMessage.h
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef PARSE_MESSAGE_H
|
||||||
|
#define PARSE_MESSAGE_H
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Basically a string + error code pair. Generated from ParseHelper so error-free
|
||||||
|
codeblocks can be sent to the Interpreter.
|
||||||
|
*/
|
||||||
|
struct ParseMessage
|
||||||
|
{
|
||||||
|
int errorCode;
|
||||||
|
std::string message;
|
||||||
|
|
||||||
|
ParseMessage( const std::string& msg );
|
||||||
|
ParseMessage( int code, const std::string& msg );
|
||||||
|
};
|
||||||
|
#endif //PARSE_MESSAGE_H
|
17
3rdparty/python-console/README.md
vendored
Normal file
17
3rdparty/python-console/README.md
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
python-console
|
||||||
|
=====
|
||||||
|
This is the result of a small side project to write a Qt widget that
|
||||||
|
encapsulates an interactive Python shell.
|
||||||
|
|
||||||
|
Quickstart
|
||||||
|
-----
|
||||||
|
You should have Qt4 and Python libraries. You will need CMake to build this
|
||||||
|
project as follows:
|
||||||
|
|
||||||
|
1. mkdir build
|
||||||
|
2. cmake ..
|
||||||
|
3. make
|
||||||
|
|
||||||
|
License
|
||||||
|
-----
|
||||||
|
This project is licensed under the [MIT](http://opensource.org/licenses/MIT) license.
|
33
3rdparty/python-console/Utils.h
vendored
Normal file
33
3rdparty/python-console/Utils.h
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef PYTHON_CONSOLE_UTILS_H
|
||||||
|
#define PYTHON_CONSOLE_UTILS_H
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
InputIterator has value type of std::string.
|
||||||
|
*/
|
||||||
|
template < class InputIterator >
|
||||||
|
std::string LongestCommonPrefix( InputIterator begin, InputIterator end )
|
||||||
|
{
|
||||||
|
if ( begin == end )
|
||||||
|
return "";
|
||||||
|
|
||||||
|
const std::string& str0 = *begin;
|
||||||
|
if ( ! str0.size() )
|
||||||
|
return "";
|
||||||
|
|
||||||
|
int endIndex = str0.size() - 1;
|
||||||
|
InputIterator it = begin; ++it;
|
||||||
|
for (; it != end; ++it)
|
||||||
|
{
|
||||||
|
const std::string& str = *it;
|
||||||
|
for (int j = 0; j <= endIndex; ++j)
|
||||||
|
{
|
||||||
|
if (j >= str.size() || str[j] != str0[j])
|
||||||
|
endIndex = j - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (endIndex > 0)? str0.substr(0, endIndex + 1) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PYTHON_CONSOLE_UTILS_H
|
2
3rdparty/python-console/data/test.py
vendored
Normal file
2
3rdparty/python-console/data/test.py
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
for i in range(1, 10):
|
||||||
|
print i
|
6
3rdparty/python-console/data/test2.py
vendored
Normal file
6
3rdparty/python-console/data/test2.py
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
for i in range(1, 10):
|
||||||
|
print i
|
||||||
|
|
||||||
|
for i in range(1, 10):
|
||||||
|
print i
|
||||||
|
print i
|
4
3rdparty/python-console/data/test3.py
vendored
Normal file
4
3rdparty/python-console/data/test3.py
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
for i in range(1, 10):
|
||||||
|
print i
|
||||||
|
for i in range(1, 10):
|
||||||
|
print i
|
4
3rdparty/python-console/data/test4.py
vendored
Normal file
4
3rdparty/python-console/data/test4.py
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
for i in range(2):
|
||||||
|
for j in range(3):
|
||||||
|
print j
|
||||||
|
print i
|
3
3rdparty/python-console/data/test5.py
vendored
Normal file
3
3rdparty/python-console/data/test5.py
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
for i in range(2):
|
||||||
|
for j in range(3):
|
||||||
|
print i, j
|
63
3rdparty/python-console/test_cli.cpp
vendored
Normal file
63
3rdparty/python-console/test_cli.cpp
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
#include "ParseListener.h"
|
||||||
|
#include "Interpreter.h"
|
||||||
|
|
||||||
|
const std::string STD_PROMPT = ">>> ";
|
||||||
|
const std::string MULTILINE_PROMPT = "... ";
|
||||||
|
|
||||||
|
struct InterpreterRelay : public ParseListener
|
||||||
|
{
|
||||||
|
Interpreter* m_interpreter;
|
||||||
|
|
||||||
|
InterpreterRelay( ):
|
||||||
|
m_interpreter( new Interpreter )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void parseEvent( const ParseMessage& msg )
|
||||||
|
{
|
||||||
|
if ( msg.errorCode )
|
||||||
|
{
|
||||||
|
std::cout << "(" << msg.errorCode << ") " << msg.message << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
std::string res = m_interpreter->interpret( msg.message, &err );
|
||||||
|
std::cout << "(" << msg.errorCode << ") " << res << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
Interpreter::Initialize( );
|
||||||
|
const std::string* prompt = &STD_PROMPT;
|
||||||
|
ParseHelper helper;
|
||||||
|
ParseListener* listener = new InterpreterRelay;
|
||||||
|
helper.subscribe( listener );
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
std::cout << *prompt;
|
||||||
|
std::getline( std::cin, str );
|
||||||
|
while ( str != "quit" )
|
||||||
|
{
|
||||||
|
std::cout << str << "\n";
|
||||||
|
helper.process( str );
|
||||||
|
if ( helper.buffered( ) )
|
||||||
|
{
|
||||||
|
prompt = &MULTILINE_PROMPT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prompt = &STD_PROMPT;
|
||||||
|
}
|
||||||
|
std::cout << *prompt;
|
||||||
|
std::getline( std::cin, str );
|
||||||
|
}
|
||||||
|
|
||||||
|
Interpreter::Finalize( );
|
||||||
|
return 0;
|
||||||
|
}
|
36
3rdparty/python-console/test_console.cpp
vendored
Normal file
36
3rdparty/python-console/test_console.cpp
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Interpreter.h"
|
||||||
|
|
||||||
|
Console* console;
|
||||||
|
|
||||||
|
void SetupWindow( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
QMainWindow* window = new QMainWindow;
|
||||||
|
window->resize( 800, 600 );
|
||||||
|
QWidget* centralWidget = new QWidget(window);
|
||||||
|
QGridLayout* layout = new QGridLayout(centralWidget);
|
||||||
|
console = new Console;
|
||||||
|
layout->addWidget(console, 0, 0, 1, 1);
|
||||||
|
window->setCentralWidget(centralWidget);
|
||||||
|
window->show( );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
QApplication app( argc, argv );
|
||||||
|
Interpreter::Initialize( );
|
||||||
|
|
||||||
|
SetupWindow( argc, argv );
|
||||||
|
|
||||||
|
bool res = app.exec( );
|
||||||
|
delete console;
|
||||||
|
Interpreter::Finalize( );
|
||||||
|
return res;
|
||||||
|
}
|
51
3rdparty/python-console/test_parse_helper.cpp
vendored
Normal file
51
3rdparty/python-console/test_parse_helper.cpp
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
Copyright (c) 2014 Alex Tsui
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
#include "ParseListener.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Demonstrates the ParseHelper.
|
||||||
|
|
||||||
|
Call it with some of the python files in data/.
|
||||||
|
*/
|
||||||
|
int main( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
if ( argc < 2 )
|
||||||
|
{
|
||||||
|
std::cout << "Usage: " << argv[0] << " file\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ParseHelper helper;
|
||||||
|
helper.subscribe( new EchoListener );
|
||||||
|
|
||||||
|
std::ifstream ifs( argv[1] );
|
||||||
|
while ( ! ifs.eof( ) )
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
std::getline( ifs, str );
|
||||||
|
helper.process( str );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
22
3rdparty/python-console/test_python_interpreter.cpp
vendored
Normal file
22
3rdparty/python-console/test_python_interpreter.cpp
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "Interpreter.h"
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
std::string commands[] = {
|
||||||
|
"from time import time,ctime\n",
|
||||||
|
"print 'Today is',ctime(time())\n"
|
||||||
|
};
|
||||||
|
Interpreter::Initialize( );
|
||||||
|
Interpreter* interpreter = new Interpreter;
|
||||||
|
for ( int i = 0; i < 2; ++i )
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
std::string res = interpreter->interpret( commands[i], &err );
|
||||||
|
std::cout << res;
|
||||||
|
}
|
||||||
|
delete interpreter;
|
||||||
|
|
||||||
|
Interpreter::Finalize( );
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user