mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* Squash only prettify changes from escript_formating_try
* support of "format-off" / "format-on" comments to mark areas without
formatting
* fix typo
* added FormatterIdentLevel, FormatterMergeEmptyLines cfg entry
better line splits for dicts/arrays
* added several spacing options. the current setting list is now:
//LineWidth
FormatterLineWidth 80
// keep original keyword spelling
FormatterKeepKeywords 0
// number of spaces for ident
FormatterIdentLevel 2
// multiple newlines get merged to a single
FormatterMergeEmptyLines 1
// space between emtpy parenthesis eg foo() vs foo( )
FormatterEmptyParenthesisSpacing 0
// space between emtpy brackets eg struct{} vs struct{ }
FormatterEmptyBracketSpacing 0
// space after/before parenthesis in conditionals
// eg if ( true ) vs if (true)
FormatterConditionalParenthesisSpacing 1
// space after/before parenthesis
// eg foo( true ) vs foo(true)
FormatterParenthesisSpacing 1
// space after/before brackets
// eg array{ true } vs array{true}
FormatterBracketSpacing 1
// add space after delimiter comma or semi in for loops
// eg {1, 2, 3} vs {1,2,3}
FormatterDelimiterSpacing 1
// add space around assignment
// eg a := 1; vs a:=1;
FormatterAssignmentSpacing 1
// add space around comparison
// eg a == 1 vs a==1
FormatterComparisonSpacing 1
// add space around operations
// eg a + 1 vs a+1
FormatterOperatorSpacing 1
// use \r\n as newline instead of \n
FormatterWindowsLineEndings 0
* added tab support
// use tabs instead of spaces
FormatterUseTabs 0
// tab width
FormatterTabWidth 4
* extended example ecompile.cfg with formatter settings
* cleanup
* program args comma is optional...
fixed line comments in group splitting
* since tokenids are now correct no more guessing for linecomments needed
* comments use as start tokenid the whitespace token if its on the same
line
* splitted processing from linebuilding
* renamed TokenPart to FmtToken better matches the purpose.
Comments get directly stored as FmtToken
started with a context enum
* better(?) formatting for groups
* fix eof rawlines
added check that all comments/rawlines got parsed
* const correctness
* datatype adapted to antlr
* fixed warnings
* added InsertNewlineAtEOF
* add newline at the end if the original file had one
dont strip comment whitespace if its somejind of "header block"
use the defined lineending for /* */ comments
* docs
* \r\n is default on windows \n otherwise
* fixed warning
---------
Co-authored-by: Kevin Eady <8634912+KevinEady@users.noreply.github.com>
175 lines
5 KiB
C++
175 lines
5 KiB
C++
#include "SourceLocation.h"
|
|
|
|
#include "bscript/compiler/Antlr4Inc.h"
|
|
|
|
#include "bscript/compiler/file/SourceFileIdentifier.h"
|
|
#include "clib/logfacility.h"
|
|
|
|
#include <iterator>
|
|
|
|
#include <climits>
|
|
|
|
namespace Pol::Bscript::Compiler
|
|
{
|
|
Position calculate_end_position( const antlr4::Token* symbol )
|
|
{
|
|
if ( !symbol )
|
|
{
|
|
return Position{ 0, 0, 0 };
|
|
}
|
|
auto line = symbol->getLine();
|
|
auto character = symbol->getCharPositionInLine() + 1;
|
|
const auto& str = symbol->getText();
|
|
const auto size = str.size();
|
|
|
|
for ( size_t i = 0; i < size; i++ )
|
|
{
|
|
if ( str[i] == '\r' && i + 1 < size && str[i + 1] == '\n' )
|
|
{
|
|
++line;
|
|
character = 1;
|
|
}
|
|
else if ( str[i] == '\r' )
|
|
{
|
|
++line;
|
|
character = 1;
|
|
}
|
|
else if ( str[i] == '\n' )
|
|
{
|
|
++line;
|
|
character = 1;
|
|
}
|
|
else
|
|
++character;
|
|
}
|
|
|
|
return Position{ line, character, symbol->getTokenIndex() };
|
|
}
|
|
|
|
Range::Range( Position start, Position end ) : start( std::move( start ) ), end( std::move( end ) )
|
|
{
|
|
}
|
|
|
|
Range::Range( const antlr4::ParserRuleContext& ctx )
|
|
: start( Position{ ctx.getStart()->getLine(), ctx.getStart()->getCharPositionInLine() + 1,
|
|
ctx.getStart()->getTokenIndex() } ),
|
|
end( calculate_end_position( ctx.getStop() ) )
|
|
{
|
|
}
|
|
|
|
Range::Range( const antlr4::tree::TerminalNode& ctx )
|
|
: start( Position{ ctx.getSymbol()->getLine(), ctx.getSymbol()->getCharPositionInLine() + 1,
|
|
ctx.getSymbol()->getTokenIndex() } ),
|
|
end( calculate_end_position( ctx.getSymbol() ) )
|
|
{
|
|
}
|
|
|
|
Range::Range( const antlr4::Token* token )
|
|
: start( Position{ token->getLine(), token->getCharPositionInLine() + 1,
|
|
token->getTokenIndex() } ),
|
|
end( calculate_end_position( token ) )
|
|
{
|
|
}
|
|
|
|
SourceLocation::SourceLocation( const SourceFileIdentifier* source_file_identifier,
|
|
size_t line_number, size_t character_column )
|
|
: source_file_identifier( source_file_identifier ),
|
|
range( Position{ line_number, character_column, 0 },
|
|
Position{ std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max(),
|
|
std::numeric_limits<size_t>::max() } )
|
|
{
|
|
}
|
|
|
|
SourceLocation::SourceLocation( const SourceFileIdentifier* source_file_identifier,
|
|
const Range& range )
|
|
: source_file_identifier( source_file_identifier ), range( range )
|
|
{
|
|
}
|
|
|
|
SourceLocation::SourceLocation( const SourceFileIdentifier* source_file_identifier,
|
|
const antlr4::ParserRuleContext& ctx )
|
|
: source_file_identifier( source_file_identifier ), range( ctx )
|
|
{
|
|
}
|
|
|
|
SourceLocation::SourceLocation( const SourceFileIdentifier* source_file_identifier,
|
|
const antlr4::tree::TerminalNode& ctx )
|
|
: source_file_identifier( source_file_identifier ), range( ctx )
|
|
{
|
|
}
|
|
|
|
bool Range::contains( const Position& position ) const
|
|
{
|
|
return contains( position.line_number, position.character_column );
|
|
}
|
|
|
|
bool Range::contains( size_t line_number, size_t character_column ) const
|
|
{
|
|
if ( line_number < start.line_number || line_number > end.line_number )
|
|
{
|
|
return false;
|
|
}
|
|
if ( line_number == start.line_number && character_column < start.character_column )
|
|
{
|
|
return false;
|
|
}
|
|
if ( line_number == end.line_number && character_column > end.character_column )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Range::contains( const Range& otherRange ) const
|
|
{
|
|
if ( otherRange.start.line_number < start.line_number ||
|
|
otherRange.end.line_number < start.line_number )
|
|
{
|
|
return false;
|
|
}
|
|
if ( otherRange.start.line_number > end.line_number ||
|
|
otherRange.end.line_number > end.line_number )
|
|
{
|
|
return false;
|
|
}
|
|
if ( otherRange.start.line_number == start.line_number &&
|
|
otherRange.start.character_column < start.character_column )
|
|
{
|
|
return false;
|
|
}
|
|
if ( otherRange.end.line_number == end.line_number &&
|
|
otherRange.end.character_column > end.character_column )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SourceLocation::debug( const std::string& msg ) const
|
|
{
|
|
ERROR_PRINTLN( "{}: {}", ( *this ), msg );
|
|
}
|
|
|
|
void SourceLocation::internal_error( const std::string& msg ) const
|
|
{
|
|
ERROR_PRINTLN( "{}: {}", ( *this ), msg );
|
|
throw std::runtime_error( msg );
|
|
}
|
|
|
|
void SourceLocation::internal_error( const std::string& msg, const SourceLocation& related ) const
|
|
{
|
|
ERROR_PRINTLN( "{}: {}\n See also: {}", ( *this ), msg, related );
|
|
throw std::runtime_error( msg );
|
|
}
|
|
|
|
} // namespace Pol::Bscript::Compiler
|
|
|
|
fmt::format_context::iterator fmt::formatter<Pol::Bscript::Compiler::SourceLocation>::format(
|
|
const Pol::Bscript::Compiler::SourceLocation& l, fmt::format_context& ctx ) const
|
|
{
|
|
std::string tmp = l.source_file_identifier->pathname;
|
|
if ( l.range.start.line_number || l.range.start.character_column )
|
|
fmt::format_to( std::back_inserter( tmp ), ":{}:{}", l.range.start.line_number,
|
|
l.range.start.character_column );
|
|
return fmt::formatter<std::string>::format( tmp, ctx );
|
|
}
|