Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,8 @@ classDiagram
TableRow "0..*" --* "1" Examples: rows
Background "1" *-- "0..*" Step: steps
Step "0..*" --* "1" ScenarioDefinition: steps
StepArgument "0..1" --* "1" Step: stepArgument
DataTable --|> StepArgument
StepArgument <|-- DocString
DataTable "0..1" --* "1" Step: dataTable
DocString "0..1" --* "1" Step: docString
TableRow "0..*" --* "1" DataTable: rows
TableRow "1" *-- "0..*" TableCell: cells
class ScenarioDefinition {
Expand Down Expand Up @@ -305,6 +304,7 @@ Every class represents a node in the AST. Every node has a `Location` that descr
the line number and column number in the input file. These numbers are 1-indexed.

All fields on nodes are strings (except for `Location.line` and `Location.column`).
A step may have at most one `DataTable` and at most one `DocString`.

The implementation is simple objects without behaviour, only data. It's up to
the implementation to decide whether to use classes or just basic collections,
Expand Down
4 changes: 3 additions & 1 deletion c/gherkin.berp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ Examples! := #ExamplesLine DescriptionHelper ExamplesTable?
ExamplesTable! := #TableRow #TableRow*

Step! := #StepLine StepArg?
StepArg := (DataTable | DocString)
StepArg := (DataTableAndMaybeDocString | DocStringAndMaybeDataTable)
DataTableAndMaybeDocString := DataTable DocString?
DocStringAndMaybeDataTable := DocString DataTable?

DataTable! := #TableRow+
DocString! := #DocStringSeparator #Other* #DocStringSeparator
Expand Down
6 changes: 6 additions & 0 deletions c/include/pickle_step.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "pickle_ast_node_id.h"
#include "pickle_argument.h"
#include "pickle_string.h"
#include "pickle_table.h"
#include "id_generator.h"

#ifdef __cplusplus
Expand All @@ -24,6 +26,8 @@ typedef struct PickleStep {
wchar_t* text;
PickleStepType pickle_step_type;
const PickleArgument* argument;
const PickleString* doc_string;
const PickleTable* data_table;
} PickleStep;

typedef struct PickleSteps {
Expand All @@ -33,6 +37,8 @@ typedef struct PickleSteps {

const PickleStep* PickleStep_new(const PickleAstNodeIds* ast_node_ids, IdGenerator* id_generator, const wchar_t* text, const PickleStepType pickle_step_type, const PickleArgument* argument);

const PickleStep* PickleStep_new_with_arguments(const PickleAstNodeIds* ast_node_ids, IdGenerator* id_generator, const wchar_t* text, const PickleStepType pickle_step_type, const PickleTable* data_table, const PickleString* doc_string);

void PickleStep_delete(const PickleStep* pickle_step);

void PickleStep_transfer(PickleStep* to_pickle_step, PickleStep* from_pickle_step);
Expand Down
4 changes: 3 additions & 1 deletion c/include/rule_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ typedef enum RuleType {
Rule_Examples, /* Examples! := #ExamplesLine DescriptionHelper ExamplesTable? */
Rule_ExamplesTable, /* ExamplesTable! := #TableRow #TableRow* */
Rule_Step, /* Step! := #StepLine StepArg? */
Rule_StepArg, /* StepArg := (DataTable | DocString) */
Rule_StepArg, /* StepArg := (DataTableAndMaybeDocString | DocStringAndMaybeDataTable) */
Rule_DataTableAndMaybeDocString, /* DataTableAndMaybeDocString := DataTable DocString? */
Rule_DocStringAndMaybeDataTable, /* DocStringAndMaybeDataTable := DocString DataTable? */
Rule_DataTable, /* DataTable! := #TableRow+ */
Rule_DocString, /* DocString! := #DocStringSeparator #Other* #DocStringSeparator */
Rule_Tags, /* Tags! := #TagLine+ */
Expand Down
7 changes: 7 additions & 0 deletions c/include/step.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ typedef struct StepArgument {
GherkinAstType type;
} StepArgument;

typedef struct DataTable DataTable;
typedef struct DocString DocString;

typedef struct Step {
item_delete_function step_delete;
GherkinAstType type;
Expand All @@ -26,6 +29,8 @@ typedef struct Step {
KeywordType keyword_type;
wchar_t* text;
const StepArgument* argument;
const DataTable* data_table;
const DocString* doc_string;
} Step;

typedef struct Steps {
Expand All @@ -35,6 +40,8 @@ typedef struct Steps {

const Step* Step_new(Location location, IdGenerator* id_generator, const wchar_t* keyword, const KeywordType keyword_type, const wchar_t* text, const StepArgument* argument);

const Step* Step_new_with_arguments(Location location, IdGenerator* id_generator, const wchar_t* keyword, const KeywordType keyword_type, const wchar_t* text, const DataTable* data_table, const DocString* doc_string);

void Step_delete(const Step* step);

void Step_transfer(Step* to_step, Step* from_step);
Expand Down
17 changes: 9 additions & 8 deletions c/src/ast_builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ static const ChildDefinitions* get_child_definitions(AstNode* ast_node);

static const Steps* get_steps(AstNode* ast_node);

static const StepArgument* get_step_argument(AstNode* ast_node);
static const DataTable* get_step_data_table(AstNode* ast_node);
static const DocString* get_step_doc_string(AstNode* ast_node);

static const Examples* get_examples(AstNode* ast_node);

Expand Down Expand Up @@ -157,7 +158,7 @@ static void* transform_node(AstNode* ast_node, AstBuilder* ast_builder) {
switch (ast_node->rule_type) {
case Rule_Step: {
token = AstNode_get_token(ast_node, Token_StepLine);
const Step* step = Step_new(token->location, ast_builder->id_generator, token->matched_keyword, token->matched_keyword_type, token->matched_text, get_step_argument(ast_node));
const Step* step = Step_new_with_arguments(token->location, ast_builder->id_generator, token->matched_keyword, token->matched_keyword_type, token->matched_text, get_step_data_table(ast_node), get_step_doc_string(ast_node));
Token_delete(token);
AstNode_delete(ast_node);
return (void*)step;
Expand Down Expand Up @@ -303,12 +304,12 @@ static const Steps* get_steps(AstNode* ast_node) {
return steps;
}

static const StepArgument* get_step_argument(AstNode* ast_node) {
StepArgument* argument = AstNode_get_single(ast_node, Rule_DataTable);
if (!argument) {
argument = AstNode_get_single(ast_node, Rule_DocString);
}
return argument;
static const DataTable* get_step_data_table(AstNode* ast_node) {
return AstNode_get_single(ast_node, Rule_DataTable);
}

static const DocString* get_step_doc_string(AstNode* ast_node) {
return AstNode_get_single(ast_node, Rule_DocString);
}

static const Examples* get_examples(AstNode* ast_node) {
Expand Down
16 changes: 7 additions & 9 deletions c/src/ast_printer.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,13 @@ static void print_step(FILE* file, const Step* step) {
print_keyword_type(file, step->keyword_type);
print_text(file, step->text);
print_location(file, &step->location);
if (step->argument) {
if (step->argument->type == Gherkin_DataTable) {
fprintf(file, ",\"dataTable\":");
print_data_table(file, (DataTable*)step->argument);
}
else if (step->argument->type == Gherkin_DocString) {
fprintf(file, ",\"docString\":");
print_doc_string(file, (DocString*)step->argument);
}
if (step->data_table) {
fprintf(file, ",\"dataTable\":");
print_data_table(file, step->data_table);
}
if (step->doc_string) {
fprintf(file, ",\"docString\":");
print_doc_string(file, step->doc_string);
}
fprintf(file, "}");
}
Expand Down
57 changes: 28 additions & 29 deletions c/src/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ typedef struct ReplacementItem {

static void compile_scenario_container(Compiler* compiler, const ChildDefinitions* child_definitions, const Tags* feature_tags, const Tags* rule_tags, const wchar_t* uri, const wchar_t* language, int context_background_step_count, const Steps* context_background_steps);

static const PickleArgument* create_pickle_argument(const StepArgument* step_argument, const TableRow* example_header, const TableRow* body_row);
static const PickleString* create_pickle_string(const DocString* doc_string, const TableRow* example_header, const TableRow* body_row);

static const PickleTable* create_pickle_table(DataTable* data_table, const TableRow* example_header, const TableRow* body_row);

Expand Down Expand Up @@ -190,35 +190,31 @@ static void compile_scenario_container(Compiler* compiler, const ChildDefinition
}
}

static const PickleArgument* create_pickle_argument(const StepArgument* step_argument, const TableRow* example_header, const TableRow* body_row) {
const PickleArgument* argument = 0;
if (step_argument) {
if (step_argument->type == Gherkin_DataTable) {
argument = (const PickleArgument*)create_pickle_table((DataTable*)step_argument, example_header, body_row);
}
else if (step_argument->type == Gherkin_DocString) {
const DocString* doc_string = (DocString*)step_argument;
if (!example_header) {
argument = (const PickleArgument*)PickleString_new(doc_string->content, doc_string->media_type);
}
else {
const wchar_t* expanded_text = create_expanded_text(doc_string->content, example_header, body_row);
const wchar_t* expanded_media_type = 0;
if(doc_string->media_type){
expanded_media_type = create_expanded_text(doc_string->media_type, example_header, body_row);
}
argument = (const PickleArgument*)PickleString_new(expanded_text, expanded_media_type);
free((void*)expanded_text);
if(expanded_media_type != 0){
free((void*)expanded_media_type);
}
}
}
static const PickleString* create_pickle_string(const DocString* doc_string, const TableRow* example_header, const TableRow* body_row) {
if (!doc_string) {
return 0;
}
if (!example_header) {
return PickleString_new(doc_string->content, doc_string->media_type);
}

const wchar_t* expanded_text = create_expanded_text(doc_string->content, example_header, body_row);
const wchar_t* expanded_media_type = 0;
if(doc_string->media_type){
expanded_media_type = create_expanded_text(doc_string->media_type, example_header, body_row);
}
return argument;
const PickleString* pickle_string = PickleString_new(expanded_text, expanded_media_type);
free((void*)expanded_text);
if(expanded_media_type != 0){
free((void*)expanded_media_type);
}
return pickle_string;
}

static const PickleTable* create_pickle_table(DataTable* data_table, const TableRow* example_header, const TableRow* body_row) {
if (!data_table) {
return 0;
}
PickleRows* rows = (PickleRows*)malloc(sizeof(PickleRows));
rows->row_count = data_table->rows->row_count;
rows->pickle_rows = 0;
Expand Down Expand Up @@ -302,15 +298,18 @@ static void copy_tags(PickleTag* destination_array, const Tags* source) {
static void copy_step(IdGenerator* id_generator, KeywordType keyword_type, PickleStep* destination_array, const Step* source_step) {
PickleStepType pickle_step_type = convert_to_pickle_step_type(keyword_type);
const PickleAstNodeIds* step_ast_node_ids = PickleAstNodeIds_new_single(source_step->id);
const PickleArgument* argument = create_pickle_argument(source_step->argument, 0, 0);
const PickleStep* step = PickleStep_new(step_ast_node_ids, id_generator, source_step->text, pickle_step_type, argument);
const PickleTable* data_table = create_pickle_table((DataTable*)source_step->data_table, 0, 0);
const PickleString* doc_string = create_pickle_string(source_step->doc_string, 0, 0);
const PickleStep* step = PickleStep_new_with_arguments(step_ast_node_ids, id_generator, source_step->text, pickle_step_type, data_table, doc_string);
PickleStep_transfer(destination_array, (PickleStep*)step);
}

static const PickleStep* expand_outline_step(IdGenerator* id_generator, const Step* outline_step, const TableRow* example_header, const TableRow* body_row, const PickleAstNodeIds* ast_node_ids, KeywordType keyword_type) {
PickleStepType pickle_step_type = convert_to_pickle_step_type(keyword_type);
const wchar_t* expanded_step_text = create_expanded_text(outline_step->text, example_header, body_row);
const PickleStep* expanded_step = PickleStep_new(ast_node_ids, id_generator, expanded_step_text, pickle_step_type, create_pickle_argument(outline_step->argument, example_header, body_row));
const PickleTable* data_table = create_pickle_table((DataTable*)outline_step->data_table, example_header, body_row);
const PickleString* doc_string = create_pickle_string(outline_step->doc_string, example_header, body_row);
const PickleStep* expanded_step = PickleStep_new_with_arguments(ast_node_ids, id_generator, expanded_step_text, pickle_step_type, data_table, doc_string);
free((void*)expanded_step_text);
return expanded_step;
}
Expand Down
Loading