8d0254e407595db30c65fde9bd7bd4cdd7d94ed4
SCC
Simple Compiler-Compiler. This program is designed to generate a parser that builds a syntax tree using a rule file with slex lexer.
Currently, this project aims on supporting following target platform/languages:
| Language | Version | Platform |
|---|---|---|
| C | 99 | Win32, POSIX, ESP32 |
| C# | 9.0 | .netstandard2.1(all possible target platform, including Unity) |
SCC Rule format
syntax_ids:
<id0>
<id1>
...
rules:
node_type
: [node_type/slex_id/slex_tag/direct_string] [node_type/slex_id/slex_tag/direct_string] ...
=> [operation] $0 $1 ...
: [node_type/slex_id/slex_tag/direct_string] [node_type/slex_id/slex_tag/direct_string] ...
=> [operation] $0 $1 ...
;
#
# $0 and $1 here means selected node/segment from matching element list.
#
Operations
new_node <syntax-id>: create a new node and attach to parent nodeappend_as_child: append selectedskip: do nothing
Sample:
syntax_ids:
binary_expr
function_call_expr
argument_list
variable
rules:
expr
: expr binary_operator expr
=> new_node binary_expr $0 $1 $2
: name "(" argument_list ")"
=> new_node function_call_expr $0
| name
=> new_node variable $0
;
argument_list
:argument_list "," expr
=> append_as_child $2
:expr
=> new_node argument_list $0
;
Usage
scc [options] <input_file> [options]
input file usually ends with `.scc`
Options:
-o <output> output file/output folder
-l <language> specify target language, e.g: c, c#, csharp
-h <header> output header file (will separate output implementation and definitions when language is c or c++. Note: c++ is currently not supported.)
-ns <namespace> specify namespace (supported languages only). Default is `scc_generated`, `SCCGenerated`, `io.creeperlv.scc.generated` for applicable language.
-class <class_name> specify class name (supported languages only). Default is `scc`, `SCC`.
-prefix <function_prefix> specify prefix for functions. Default is `scc_` for languages does not support namespace/class, `` (empty string) for languages support namespace/class.
-data_type <data_type_name> specify the name of the syntax node data type.
-slex-ns <namespace> specify namespace used in slex.
-slex-class <class_name> specify class name used in slex.
-slex-prefix <function_prefix> specify function prefix used in slex.
-slex-data_type <data_type_name> specify segment data type used in slex.
Data Type Name Table
| Language | Type Name |
|---|---|
| C | scc_syntax_node |
| C# | SyntaxNode |
Generated parser
All usages here uses default settings
C99
Usage sample:
void scc_sample(FILE* f, char* file_name){
struct slex_segment* head;
const char* str="<some_inputs>";
if(slex_file(f, file_name, &head)){
//Success
struct scc_syntax_node* root;
if(scc_parse(head,&root)){
//Success
}
}
slex_free(head);
}
API and defined data types:
typedef struct scc_syntax_node_enclosure{
enum scc_syntax_node_type;
void* data;
}scc_syntax_node_enclosure;
typedef enum scc_syntax_node_type{
scc_node, scc_segment
}scc_syntax_node_type;
typedef struct scc_syntax_node{
enum scc_syntax_id;
char* syntax_name;
scc_syntax_node_enclosure* children;
uint64_t child_count;
scc_syntax_node* parent;
} scc_syntax_node;
typedef enum scc_syntax_id{
default,<generated from rule file>
}scc_syntax_id;
char scc_parse(slex_segment* head, scc_syntax_node** output);
char scc_free(scc_syntax_node* root);
C#
APIs:
using SLexGenerated;
namesapce SCCGenerated{
public class SCC{
public bool Parse(Segment head, out SyntaxNode Root);
}
public enum SyntaxId{
Default,<Generated-from-rule-file>
}
public class SyntaxNodeEnclosure{
public SyntaxNode? Node;
public Segment? Segment;
public EnclosureType EnclosureType;
}
public enum EnclosureType{
Node, Segment
}
public class SyntaxNode{
public SyntaxNode? Parent;
public string SyntaxName;
public SyntaxId Id;
public List<SyntaxNodeEnclosure> Children;
}
}
Description
Languages
C
93.3%
C#
6.4%
Shell
0.3%