Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static remapping with url scheme #227

Merged
merged 38 commits into from
Apr 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a76cb62
DIRTY lexer with bugs rosservice: and rostopic:
sloretz Apr 6, 2018
7d01c3c
Fix bug with partial url schemes
sloretz Apr 6, 2018
974b44f
Style fixes
sloretz Apr 6, 2018
cb5210b
Moved lexer.h to satisfy cpplint
sloretz Apr 6, 2018
2324f88
moved terminals to their own array to reduce code size
sloretz Apr 6, 2018
673cf31
Shrink lexer by using char, add error checking
sloretz Apr 6, 2018
7b22079
Comment/whitespace
sloretz Apr 6, 2018
e9ac9bf
comment
sloretz Apr 6, 2018
c28589e
terminal -> lexeme where appropriate
sloretz Apr 6, 2018
975f270
Static const global
sloretz Apr 6, 2018
4b9cb4f
Documentation and argument order
sloretz Apr 6, 2018
20a0457
Add rcl_lexer_lookahead2_t
sloretz Apr 6, 2018
6a82306
Allow ignoring lexeme text
sloretz Apr 7, 2018
4423f03
Beginnings of recursive descent parser
sloretz Apr 7, 2018
884e286
Add method to get current position in text
sloretz Apr 9, 2018
e60841f
new remap parsing passes unit tests
sloretz Apr 9, 2018
12c0812
Test rosservice:// and rostopic://
sloretz Apr 9, 2018
537e224
fix movement formula comment
sloretz Apr 9, 2018
a54e669
doxygent comment
sloretz Apr 9, 2018
d712f3f
move code to make pr diff easier to read
sloretz Apr 9, 2018
d6c6313
Comments
sloretz Apr 9, 2018
cf2b328
Comment
sloretz Apr 9, 2018
2867c74
Comment about impossibilities
sloretz Apr 9, 2018
a9ee9be
Set error message
sloretz Apr 9, 2018
227743a
unsigned literals
sloretz Apr 9, 2018
23232ec
Add a couple more url scheme tests
sloretz Apr 9, 2018
4ce994f
remove out of date comment
sloretz Apr 9, 2018
413b720
end_pos -> length
sloretz Apr 9, 2018
19b64a1
another token text
sloretz Apr 9, 2018
593133e
Whitespace
sloretz Apr 9, 2018
fb5e149
call accept -> accept
sloretz Apr 9, 2018
05cd295
use array instead of number suffix
sloretz Apr 9, 2018
591c35f
Missing return; wrong comment
sloretz Apr 9, 2018
a4ffdc2
test methods at end of input
sloretz Apr 9, 2018
69f1f2a
Test not zero-initialized init
sloretz Apr 12, 2018
b408d2b
Test lexing remapping rules
sloretz Apr 12, 2018
811e129
Windows warning
sloretz Apr 16, 2018
3752a23
Remove const to avoid discarding during cast
sloretz Apr 16, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions rcl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ set(${PROJECT_NAME}_sources
src/rcl/expand_topic_name.c
src/rcl/graph.c
src/rcl/guard_condition.c
src/rcl/lexer.c
src/rcl/lexer_lookahead.c
src/rcl/node.c
src/rcl/publisher.c
src/rcl/rcl.c
Expand Down
118 changes: 118 additions & 0 deletions rcl/include/rcl/lexer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RCL__LEXER_H_
#define RCL__LEXER_H_

#include <stddef.h>

#include "rcl/allocator.h"
#include "rcl/macros.h"
#include "rcl/types.h"
#include "rcl/visibility_control.h"

#if __cplusplus
extern "C"
{
#endif

/// Type of lexeme found by lexical analysis.
typedef enum rcl_lexeme_t
{
/// Indicates no valid lexeme was found
RCL_LEXEME_NONE = 0,
/// Indicates end of input has been reached
RCL_LEXEME_EOF = 1,
/// ~/
RCL_LEXEME_TILDE_SLASH = 2,
/// rosservice://
RCL_LEXEME_URL_SERVICE = 3,
/// rostopic://
RCL_LEXEME_URL_TOPIC = 4,
/// :
RCL_LEXEME_COLON = 5,
/// __node
RCL_LEXEME_NODE = 6,
/// __ns
RCL_LEXEME_NS = 7,
/// :=
RCL_LEXEME_SEPARATOR = 8,
/// \1
RCL_LEXEME_BR1 = 9,
/// \2
RCL_LEXEME_BR2 = 10,
/// \3
RCL_LEXEME_BR3 = 11,
/// \4
RCL_LEXEME_BR4 = 12,
/// \5
RCL_LEXEME_BR5 = 13,
/// \6
RCL_LEXEME_BR6 = 14,
/// \7
RCL_LEXEME_BR7 = 15,
/// \8
RCL_LEXEME_BR8 = 16,
/// \9
RCL_LEXEME_BR9 = 17,
/// a name between slashes, must match (([a-zA-Z](_)?)|_)([0-9a-zA-Z](_)?)*
RCL_LEXEME_TOKEN = 18,
/// /
RCL_LEXEME_FORWARD_SLASH = 19,
/// *
RCL_LEXEME_WILD_ONE = 20,
/// **
RCL_LEXEME_WILD_MULTI = 21
} rcl_lexeme_t;


/// Do lexical analysis on a string.
/**
* This function analyzes a string to see if it starts with a valid lexeme.
* If the string does not begin with a valid lexeme then lexeme will be RCL_LEXEME_NONE, and the
* length will be set to include the character that made it impossible.
* If the first character is '\0' then lexeme will be RCL_LEXEME_EOF.
*
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes [1]
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
* <i>[1] Only allocates if an argument is invalid or an internal bug is detected.</i>
*
* \param[in] text The string to analyze.
* \param[in] allocator An allocator to use if an error occurs.
* \param[out] lexeme The type of lexeme found in the string.
* \param[out] length The length of text in the string that constitutes the found lexeme.
* \return `RCL_RET_OK` if analysis is successful regardless whether a valid lexeme is found, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an internal bug is detected.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_lexer_analyze(
const char * text,
rcl_allocator_t allocator,
rcl_lexeme_t * lexeme,
size_t * length);

#if __cplusplus
}
#endif

#endif // RCL__LEXER_H_
261 changes: 261 additions & 0 deletions rcl/include/rcl/lexer_lookahead.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RCL__LEXER_LOOKAHEAD_H_
#define RCL__LEXER_LOOKAHEAD_H_

#include <stddef.h>

#include "rcl/allocator.h"
#include "rcl/lexer.h"
#include "rcl/macros.h"
#include "rcl/types.h"
#include "rcl/visibility_control.h"

#if __cplusplus
extern "C"
{
#endif

// Forward declaration
struct rcl_lexer_lookahead2_impl_t;

/// Track lexical analysis and allow looking ahead 2 lexemes.
typedef struct rcl_lexer_lookahead2_t
{
struct rcl_lexer_lookahead2_impl_t * impl;
} rcl_lexer_lookahead2_t;

/// Get a zero initialized rcl_lexer_lookahead2_t instance.
/**
* \sa rcl_lexer_lookahead2_init()
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | No
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \return zero initialized lookahead2 buffer.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_lexer_lookahead2_t
rcl_get_zero_initialized_lexer_lookahead2();

/// Initialize an rcl_lexer_lookahead2_t instance.
/**
* The lookahead2 buffer borrows a reference to the provided text.
* The text must not be freed before the buffer is finalized.
* The lookahead2 buffer only needs to be finalized if this function does not return RCL_RET_OK.
* \sa rcl_lexer_lookahead2_fini()
*
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] buffer A buffer that is zero initialized.
* \sa rcl_get_zero_initialized_lexer_lookahead2()
* \param[in] text The string to analyze.
* \param[in] allocator An allocator to use if an error occurs.
* \return `RCL_RET_OK` if the buffer is successfully initialized, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurrs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_lexer_lookahead2_init(
rcl_lexer_lookahead2_t * buffer,
const char * text,
rcl_allocator_t allocator);

/// Finalize an instance of an rcl_lexer_lookahead2_t structure.
/**
* \sa rcl_lexer_lookahead2_init()
*
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes [1]
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
* <i>[1] Only allocates if an argument is invalid.</i>
*
* \param[in] buffer The structure to be deallocated.
* \return `RCL_RET_OK` if the structure was successfully finalized, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_lexer_lookahead2_fini(
rcl_lexer_lookahead2_t * buffer);

/// Look ahead at the next lexeme in the string.
/**
* Repeated calls to peek will return the same lexeme.
* A parser that deems the next lexeme as valid must accept it to advance lexing.
* \sa rcl_lexer_lookahead2_accept()
*
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes [1]
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
* <i>[1] Only allocates if an argument is invalid or an internal bug is detected.</i>
*
* \param[in] buffer the lookahead2 buffer being used to analyze a string.
* \param[out] next_type an output variable for the next lexeme in the string.
* \return `RCL_RET_OK` if peeking was successfull, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_lexer_lookahead2_peek(
rcl_lexer_lookahead2_t * buffer,
rcl_lexeme_t * next_type);

/// Look ahead at the next two lexemes in the string.
/**
* Repeated calls to peek2 will return the same two lexemes.
* A parser that deems the next two lexemes as valid must accept twice to advance lexing.
* \sa rcl_lexer_lookahead2_accept()
*
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes [1]
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
* <i>[1] Only allocates if an argument is invalid or an internal bug is detected.</i>
*
* \param[in] buffer the lookahead2 buffer being used to analyze a string.
* \param[out] next_type1 an output variable for the next lexeme in the string.
* \param[out] next_type2 an output variable for the lexeme after the next lexeme in the string.
* \return `RCL_RET_OK` if peeking was successfull, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_lexer_lookahead2_peek2(
rcl_lexer_lookahead2_t * buffer,
rcl_lexeme_t * next_type1,
rcl_lexeme_t * next_type2);

/// Accept a lexeme and advance analysis.
/**
* A token must have been peeked before it can be accepted.
* \sa rcl_lexer_lookahead2_peek()
* \sa rcl_lexer_lookahead2_peek2()
*
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes [1]
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
* <i>[1] Only allocates if an argument is invalid or an error occurs.</i>
*
* \param[in] buffer the lookahead2 buffer being used to analyze a string.
* \param[out] lexeme_text pointer to where lexeme begins in string.
* \param[out] lexeme_text_length length of lexeme_text.
* \return `RCL_RET_OK` if peeking was successfull, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_lexer_lookahead2_accept(
rcl_lexer_lookahead2_t * buffer,
const char ** lexeme_text,
size_t * lexeme_text_length);

/// Require the next lexeme to be a certain type and advance analysis.
/**
* This method is a shortcut to peeking and accepting a lexeme.
* It should be used by a parser when there is only one valid lexeme that could come next.
* \sa rcl_lexer_lookahead2_peek()
* \sa rcl_lexer_lookahead2_accept()
*
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes [1]
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
* <i>[1] Only allocates if an argument is invalid or an error occurs.</i>
*
* \param[in] buffer the lookahead2 buffer being used to analyze a string.
* \param[in] type the type the next lexeme must be.
* \param[out] lexeme_text pointer to where lexeme begins in string.
* \param[out] lexeme_text_length length of lexeme_text.
* \return `RCL_RET_OK` if the next lexeme was the expected one, or
* \return `RCL_RET_WRONG_LEXEME` if the next lexeme was not the expected one, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_lexer_lookahead2_expect(
rcl_lexer_lookahead2_t * buffer,
rcl_lexeme_t type,
const char ** lexeme_text,
size_t * lexeme_text_length);

/// Get the text at the point where it is currently being analyzed.
/**
* <hr>
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | No
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] buffer the lookahead2 buffer being used to analyze a string.
* \return a pointer inside the original text at the position being analyzed, or
* \return `NULL` if buffer is itself `NULL` or zero initialized, or
* \return an undefined value if buffer is not initialized or has been finalized.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
const char *
rcl_lexer_lookahead2_get_text(
const rcl_lexer_lookahead2_t * buffer);

#if __cplusplus
}
#endif

#endif // RCL__LEXER_LOOKAHEAD_H_
2 changes: 2 additions & 0 deletions rcl/include/rcl/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,7 @@ typedef rmw_ret_t rcl_ret_t;
// rcl argument parsing specific ret codes in 1XXX
/// Argument is not a valid remap rule
#define RCL_RET_INVALID_REMAP_RULE 1001
/// Expected one type of lexeme but got another
#define RCL_RET_WRONG_LEXEME 1002

#endif // RCL__TYPES_H_
Loading