|
/*=============================================================================
C Grammar checker
Requires Spirit v1.6.0 or later
Copyright (c) 2001-2004 Hartmut Kaiser
http://spirit.sourceforge.net/
Adapted from:
http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
///////////////////////////////////////////////////////////////////////////////
// version history
//
// TODO: Handling typedef's, without that we can't correctly parse
// auxilliary valid C sources. But hey it's a sample.
//
// Modified: 20.09.2002 21:58:45
// Ported to Spirit V1.5
//
// Modified: 18.10.2001 16:36:07
// Corrected: String literals may be splitted in several strings: "abc" "def"
// Corrected: String literals may have length 0 ("")
//
// Modified: 17.10.2001 10:56:57
// Rewritten: *_CONSTANT rules
// Introduced: operator '||' where possible
// Corrected: IDENTIFIER can start with '_' and can contain '$'
// Added: Skipping of '#line' and '#pragma' directives, which contained
// in preprocessed files of the Intel V5.0.1 compiler
//
// Modified: 16.10.2001 21:12:05
// Corrected: missing lexeme_d[] statements for *_CONSTANT
// Corrected: missing longest_d[] for CONSTANT
#include <iostream>
#include <fstream>
#include <vector>
#if defined(_DEBUG)
#define BOOST_SPIRIT_DEBUG
#endif // defined(_DEBUG)
#include <boost/spirit/core.hpp>
#include <boost/spirit/utility.hpp>
#include <boost/spirit/symbols.hpp>
// There is a g++ (3.1 and 3.2) bug on MINGW that prohibits
// the use of the identifiers below. The following is a workaround.
#if ((__GNUC__ == 3) && (__GNUC_MINOR__ == 1 || __GNUC_MINOR__ == 2) \
&& defined(_WINNT_H))
# ifdef CONST
# undef CONST
# endif
# ifdef VOID
# undef VOID
# endif
# define CHAR CHAR_RULE
# define CONST CONST_RULE
# define FLOAT FLOAT_RULE
# define INT INT_RULE
# define VOID VOID_RULE
#endif
///////////////////////////////////////////////////////////////////////////////
// used namespaces
using namespace boost::spirit;
using namespace std;
///////////////////////////////////////////////////////////////////////////////
// parsing helper function
// Here's our comment rule
struct skip_grammar : public grammar<skip_grammar>
{
template <typename ScannerT>
struct definition
{
definition(skip_grammar const& /*self*/)
{
#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1200)
skip
= space_p
| "//" >> *(anychar_p - '\n') >> '\n' // C++ comment
| "/*" >> *(anychar_p - "*/") >> "*/" // C comment
| "#line" >> *(anychar_p - '\n') >> '\n' // added for correctly
// handling preprocessed
| "#pragma" >> *(anychar_p - '\n') >> '\n'// files from Intel V5.0.1
// on W2K
;
#else
skip
= space_p
| comment_p("//") // C++ comment
| comment_p("/*", "*/") // C comment
| comment_p("#line") // added for correctly
// handling preprocessed
| comment_p("#pragma") // files from Intel V5.0.1
// on W2K
;
#endif
}
rule<ScannerT> skip;
rule<ScannerT> const&
start() const { return skip; }
};
};
template<typename GrammarT>
void
parse(GrammarT const& g, char const* filename)
{
ifstream in(filename);
if (!in)
{
cerr << "Could not open input file: " << filename << endl;
return;
}
in.unsetf(ios::skipws); // Turn of white space skipping on the stream
vector<char> vec;
std::copy(
istream_iterator<char>(in),
istream_iterator<char>(),
std::back_inserter(vec));
vector<char>::const_iterator start = vec.begin();
vector<char>::const_iterator end = vec.end();
skip_grammar skip;
parse_info<vector<char>::const_iterator> result =
parse(start, end, g, skip);
if (result.full)
cerr << filename << " Parses OK" << endl;
else {
cerr << filename << " Fails Parsing" << endl;
for (int i = 0; i < 50; i++)
{
if (result.stop == end)
break;
cerr << *result.stop++;
}
cerr << endl;
}
}
struct c_grammar : public grammar<c_grammar>
{
template <typename ScannerT>
struct definition
{
definition(c_grammar const& /*self*/) :
ELLIPSIS("..."), RIGHT_ASSIGN(">>="), LEFT_ASSIGN("<<="),
ADD_ASSIGN("+="), SUB_ASSIGN("-="), MUL_ASSIGN("*="),
DIV_ASSIGN("/="), MOD_ASSIGN("%="), AND_ASSIGN("&="),
XOR_ASSIGN("^="), OR_ASSIGN("|="), RIGHT_OP(">>"), LEFT_OP("<<"),
INC_OP("++"), DEC_OP("--"), PTR_OP("->"), AND_OP("&&"),
OR_OP("||"), LE_OP("<="), GE_OP(">="), EQ_OP("=="), NE_OP("!="),
SEMICOLON(';'),
COMMA(','), COLON(':'), ASSIGN('='), LEFT_PAREN('('),
RIGHT_PAREN(')'), DOT('.'), ADDROF('&'), BANG('!'), TILDE('~'),
MINUS('-'), PLUS('+'), STAR('*'), SLASH('/'), PERCENT('%'),
LT_OP('<'), GT_OP('>'), XOR('^'), OR('|'), QUEST('?')
{
// C keywords
keywords =
"auto", "break", "case", "char", "const", "continue", "default",
"do", "double", "else", "enum", "extern", "float", "for",
"goto", "if", "int", "long", "register", "return", "short",
"signed", "sizeof", "static", "struct", "switch", "typedef",
"union", "unsigned", "void", "volatile", "while";
// C operators
LEFT_BRACE = chlit<>('{') | strlit<>("<%");
RIGHT_BRACE = chlit<>('}') | strlit<>("%>");
LEFT_BRACKET = chlit<>('[') | strlit<>("<:");
RIGHT_BRACKET = chlit<>(']') | strlit<>(":>");
// Tokens
AUTO = strlit<>("auto");
BREAK = strlit<>("break");
CASE = strlit<>("case");
CHAR = strlit<>("char");
CONST = strlit<>("const");
CONTINUE = strlit<>("continue");
DEFAULT = strlit<>("default");
DO = strlit<>("do");
DOUBLE = strlit<>("double");
ELSE = strlit<>("else");
ENUM = strlit<>("enum");
EXTERN = strlit<>("extern");
FOR = strlit<>("for");
FLOAT = strlit<>("float");
GOTO = strlit<>("goto");
IF = strlit<>("if");
INT = strlit<>("int");
LONG = strlit<>("long");
REGISTER = strlit<>("register");
RETURN = strlit<>("return");
SHORT = strlit<>("short");
SIGNED = strlit<>("signed");
SIZEOF = strlit<>("sizeof");
STATIC = strlit<>("static");
STRUCT = strlit<>("struct");
SWITCH = strlit<>("switch");
TYPEDEF = strlit<>("typedef");
UNION = strlit<>("union");
UNSIGNED = strlit<>("unsigned");
VOID = strlit<>("void");
VOLATILE = strlit<>("volatile");
WHILE = strlit<>("while");
// C identifiers
IDENTIFIER =
lexeme_d[
((alpha_p | '_' | '$') >> *(alnum_p | '_' | '$'))
- (keywords >> anychar_p - (alnum_p | '_' | '$'))
]
;
// string literals
STRING_LITERAL_PART =
lexeme_d[
!chlit<>('L') >> chlit<>('\"') >>
*( strlit<>("\\\"") | anychar_p - chlit<>('\"') ) >>
chlit<>('\"')
]
;
STRING_LITERAL = +STRING_LITERAL_PART;
// integer constants
INT_CONSTANT_HEX
= lexeme_d[
chlit<>('0')
>> as_lower_d[chlit<>('x')]
>> +xdigit_p
>> !as_lower_d[chlit<>('l') | chlit<>('u')]
]
;
INT_CONSTANT_OCT
= lexeme_d[
chlit<>('0')
>> +range<>('0', '7')
>> !as_lower_d[chlit<>('l') | chlit<>('u')]
]
;
INT_CONSTANT_DEC
= lexeme_d[
+digit_p
>> !as_lower_d[chlit<>('l') | chlit<>('u')]
]
;
INT_CONSTANT_CHAR
= lexeme_d[
!chlit<>('L') >> chlit<>('\'') >>
longest_d[
anychar_p
| ( chlit<>('\\')
>> chlit<>('0')
>> repeat_p(0, 2)[range<>('0', '7')]
)
| (chlit<>('\\') >> anychar_p)
] >>
chlit<>('\'')
]
;
INT_CONSTANT =
INT_CONSTANT_HEX
| INT_CONSTANT_OCT
| INT_CONSTANT_DEC
| INT_CONSTANT_CHAR
;
// float constants
FLOAT_CONSTANT_1 // 12345[eE][+-]123[lLfF]?
= lexeme_d[
+digit_p
>> (chlit<>('e') | chlit<>('E'))
>> !(chlit<>('+') | chlit<>('-'))
>> +digit_p
>> !as_lower_d[chlit<>('l') | chlit<>('f')]
]
;
FLOAT_CONSTANT_2 // .123([[eE][+-]123)?[lLfF]?
= lexeme_d[
*digit_p
>> chlit<>('.')
>> +digit_p
>> !( (chlit<>('e') | chlit<>('E'))
>> !(chlit<>('+') | chlit<>('-'))
>> +digit_p
)
>> !as_lower_d[chlit<>('l') | chlit<>('f')]
]
;
FLOAT_CONSTANT_3 // 12345.([[eE][+-]123)?[lLfF]?
= lexeme_d[
+digit_p
>> chlit<>('.')
>> *digit_p
>> !( (chlit<>('e') | chlit<>('E'))
>> !(chlit<>('+') | chlit<>('-'))
>> +digit_p
)
>> !as_lower_d[chlit<>('l') | chlit<>('f')]
]
;
FLOAT_CONSTANT =
FLOAT_CONSTANT_1
| FLOAT_CONSTANT_2
| FLOAT_CONSTANT_3
;
CONSTANT = longest_d[FLOAT_CONSTANT | INT_CONSTANT];
// debug support for terminals
BOOST_SPIRIT_DEBUG_RULE(AUTO);
BOOST_SPIRIT_DEBUG_RULE(BREAK);
BOOST_SPIRIT_DEBUG_RULE(CASE);
BOOST_SPIRIT_DEBUG_RULE(CHAR);
BOOST_SPIRIT_DEBUG_RULE(CONST);
BOOST_SPIRIT_DEBUG_RULE(CONTINUE);
BOOST_SPIRIT_DEBUG_RULE(DEFAULT);
BOOST_SPIRIT_DEBUG_RULE(DO);
BOOST_SPIRIT_DEBUG_RULE(DOUBLE);
BOOST_SPIRIT_DEBUG_RULE(ELSE);
BOOST_SPIRIT_DEBUG_RULE(ENUM);
BOOST_SPIRIT_DEBUG_RULE(EXTERN);
BOOST_SPIRIT_DEBUG_RULE(FOR);
BOOST_SPIRIT_DEBUG_RULE(FLOAT);
BOOST_SPIRIT_DEBUG_RULE(GOTO);
BOOST_SPIRIT_DEBUG_RULE(IF);
BOOST_SPIRIT_DEBUG_RULE(INT);
BOOST_SPIRIT_DEBUG_RULE(LONG);
BOOST_SPIRIT_DEBUG_RULE(REGISTER);
BOOST_SPIRIT_DEBUG_RULE(RETURN);
BOOST_SPIRIT_DEBUG_RULE(SHORT);
BOOST_SPIRIT_DEBUG_RULE(SIGNED);
BOOST_SPIRIT_DEBUG_RULE(SIZEOF);
BOOST_SPIRIT_DEBUG_RULE(STATIC);
BOOST_SPIRIT_DEBUG_RULE(STRUCT);
BOOST_SPIRIT_DEBUG_RULE(SWITCH);
BOOST_SPIRIT_DEBUG_RULE(TYPEDEF);
BOOST_SPIRIT_DEBUG_RULE(UNION);
BOOST_SPIRIT_DEBUG_RULE(UNSIGNED);
BOOST_SPIRIT_DEBUG_RULE(VOID);
BOOST_SPIRIT_DEBUG_RULE(VOLATILE);
BOOST_SPIRIT_DEBUG_RULE(WHILE);
BOOST_SPIRIT_DEBUG_RULE(IDENTIFIER);
BOOST_SPIRIT_DEBUG_RULE(STRING_LITERAL);
BOOST_SPIRIT_DEBUG_RULE(INT_CONSTANT_HEX);
BOOST_SPIRIT_DEBUG_RULE(INT_CONSTANT_OCT);
BOOST_SPIRIT_DEBUG_RULE(INT_CONSTANT_DEC);
BOOST_SPIRIT_DEBUG_RULE(INT_CONSTANT_CHAR);
BOOST_SPIRIT_DEBUG_RULE(INT_CONSTANT);
BOOST_SPIRIT_DEBUG_RULE(FLOAT_CONSTANT_1);
BOOST_SPIRIT_DEBUG_RULE(FLOAT_CONSTANT_2);
BOOST_SPIRIT_DEBUG_RULE(FLOAT_CONSTANT_3);
BOOST_SPIRIT_DEBUG_RULE(FLOAT_CONSTANT);
BOOST_SPIRIT_DEBUG_RULE(CONSTANT);
// debug support for non terminals
BOOST_SPIRIT_DEBUG_RULE(primary_expression);
BOOST_SPIRIT_DEBUG_RULE(postfix_expression);
BOOST_SPIRIT_DEBUG_RULE(postfix_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(argument_expression_list);
BOOST_SPIRIT_DEBUG_RULE(unary_expression);
BOOST_SPIRIT_DEBUG_RULE(unary_operator);
BOOST_SPIRIT_DEBUG_RULE(cast_expression);
BOOST_SPIRIT_DEBUG_RULE(multiplicative_expression);
BOOST_SPIRIT_DEBUG_RULE(multiplicative_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(additive_expression);
BOOST_SPIRIT_DEBUG_RULE(additive_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(shift_expression);
BOOST_SPIRIT_DEBUG_RULE(shift_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(relational_expression);
BOOST_SPIRIT_DEBUG_RULE(relational_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(equality_expression);
BOOST_SPIRIT_DEBUG_RULE(equality_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(and_expression);
BOOST_SPIRIT_DEBUG_RULE(and_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(exclusive_or_expression);
BOOST_SPIRIT_DEBUG_RULE(exclusive_or_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(inclusive_or_expression);
BOOST_SPIRIT_DEBUG_RULE(inclusive_or_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(logical_and_expression);
BOOST_SPIRIT_DEBUG_RULE(logical_and_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(logical_or_expression);
BOOST_SPIRIT_DEBUG_RULE(logical_or_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(conditional_expression);
BOOST_SPIRIT_DEBUG_RULE(conditional_expression_helper);
BOOST_SPIRIT_DEBUG_RULE(assignment_expression);
BOOST_SPIRIT_DEBUG_RULE(assignment_operator);
BOOST_SPIRIT_DEBUG_RULE(expression);
BOOST_SPIRIT_DEBUG_RULE(constant_expression);
BOOST_SPIRIT_DEBUG_RULE(declaration);
BOOST_SPIRIT_DEBUG_RULE(declaration_specifiers);
BOOST_SPIRIT_DEBUG_RULE(init_declarator_list);
BOOST_SPIRIT_DEBUG_RULE(init_declarator);
BOOST_SPIRIT_DEBUG_RULE(storage_class_specifier);
BOOST_SPIRIT_DEBUG_RULE(type_specifier);
BOOST_SPIRIT_DEBUG_RULE(struct_or_union_specifier);
BOOST_SPIRIT_DEBUG_RULE(struct_or_union);
BOOST_SPIRIT_DEBUG_RULE(struct_declaration_list);
BOOST_SPIRIT_DEBUG_RULE(struct_declaration);
BOOST_SPIRIT_DEBUG_RULE(specifier_qualifier_list);
BOOST_SPIRIT_DEBUG_RULE(struct_declarator_list);
BOOST_SPIRIT_DEBUG_RULE(struct_declarator);
BOOST_SPIRIT_DEBUG_RULE(enum_specifier);
BOOST_SPIRIT_DEBUG_RULE(enumerator_list);
BOOST_SPIRIT_DEBUG_RULE(enumerator);
BOOST_SPIRIT_DEBUG_RULE(type_qualifier);
BOOST_SPIRIT_DEBUG_RULE(declarator);
BOOST_SPIRIT_DEBUG_RULE(direct_declarator);
BOOST_SPIRIT_DEBUG_RULE(direct_declarator_helper);
BOOST_SPIRIT_DEBUG_RULE(pointer);
BOOST_SPIRIT_DEBUG_RULE(type_qualifier_list);
BOOST_SPIRIT_DEBUG_RULE(parameter_type_list);
BOOST_SPIRIT_DEBUG_RULE(parameter_list);
BOOST_SPIRIT_DEBUG_RULE(parameter_declaration);
BOOST_SPIRIT_DEBUG_RULE(identifier_list);
BOOST_SPIRIT_DEBUG_RULE(type_name);
BOOST_SPIRIT_DEBUG_RULE(abstract_declarator);
BOOST_SPIRIT_DEBUG_RULE(direct_abstract_declarator);
BOOST_SPIRIT_DEBUG_RULE(direct_abstract_declarator_helper);
BOOST_SPIRIT_DEBUG_RULE(initializer);
BOOST_SPIRIT_DEBUG_RULE(initializer_list);
BOOST_SPIRIT_DEBUG_RULE(statement);
BOOST_SPIRIT_DEBUG_RULE(labeled_statement);
BOOST_SPIRIT_DEBUG_RULE(compound_statement);
BOOST_SPIRIT_DEBUG_RULE(declaration_list);
BOOST_SPIRIT_DEBUG_RULE(statement_list);
BOOST_SPIRIT_DEBUG_RULE(expression_statement);
BOOST_SPIRIT_DEBUG_RULE(selection_statement);
BOOST_SPIRIT_DEBUG_RULE(iteration_statement);
BOOST_SPIRIT_DEBUG_RULE(jump_statement);
BOOST_SPIRIT_DEBUG_RULE(translation_unit);
BOOST_SPIRIT_DEBUG_RULE(external_declaration);
BOOST_SPIRIT_DEBUG_RULE(function_definition);
// Rules
primary_expression
= IDENTIFIER
| CONSTANT
| STRING_LITERAL
| LEFT_PAREN >> expression >> RIGHT_PAREN
;
// left recursion --> right recursion
// postfix_expression
// = primary_expression
// | postfix_expression >>
// (
// LEFT_BRACKET >> expression >> RIGHT_BRACKET
// | LEFT_PAREN >> !argument_expression_list >> RIGHT_PAREN
// | DOT >> IDENTIFIER
// | PTR_OP >> IDENTIFIER
// | INC_OP
// | DEC_OP
// )
// ;
postfix_expression
= primary_expression >> postfix_expression_helper
;
postfix_expression_helper
= (
LEFT_BRACKET >> expression >> RIGHT_BRACKET
| LEFT_PAREN >> !argument_expression_list >> RIGHT_PAREN
| DOT >> IDENTIFIER
| PTR_OP >> IDENTIFIER
| INC_OP
| DEC_OP
) >>
postfix_expression_helper
| epsilon_p
;
argument_expression_list
= assignment_expression >> *(COMMA >> assignment_expression)
;
unary_expression
= postfix_expression
| INC_OP >> unary_expression
| DEC_OP >> unary_expression
| unary_operator >> cast_expression
| SIZEOF >>
(
unary_expression
| LEFT_PAREN >> type_name >> RIGHT_PAREN
)
;
unary_operator
= ADDROF
| STAR
| PLUS
| MINUS
| TILDE
| BANG
;
cast_expression
= LEFT_PAREN >> type_name >> RIGHT_PAREN >> cast_expression
| unary_expression
;
// left recursion --> right recursion
// multiplicative_expression
// = cast_expression
// | multiplicative_expression >>
// (
// STAR >> cast_expression
// | SLASH >> cast_expression
// | PERCENT >> cast_expression
// )
// ;
multiplicative_expression
= cast_expression >> multiplicative_expression_helper
;
multiplicative_expression_helper
= (
STAR >> cast_expression
| SLASH >> cast_expression
| PERCENT >> cast_expression
) >>
multiplicative_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// additive_expression
// = multiplicative_expression
// | additive_expression >>
// (
// PLUS >> multiplicative_expression
// | MINUS >> multiplicative_expression
// )
// ;
additive_expression
= multiplicative_expression >> additive_expression_helper
;
additive_expression_helper
= (
PLUS >> multiplicative_expression
| MINUS >> multiplicative_expression
) >>
additive_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// shift_expression
// = additive_expression
// | shift_expression >>
// (
// LEFT_OP >> additive_expression
// | RIGHT_OP >> additive_expression
// )
// ;
shift_expression
= additive_expression >> shift_expression_helper
;
shift_expression_helper
= (
LEFT_OP >> additive_expression
| RIGHT_OP >> additive_expression
) >>
shift_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// relational_expression
// = shift_expression
// | relational_expression >>
// (
// LT_OP >> shift_expression
// | GT_OP >> shift_expression
// | LE_OP >> shift_expression
// | GE_OP >> shift_expression
// )
// ;
relational_expression
= shift_expression >> relational_expression_helper
;
relational_expression_helper
= (
LT_OP >> shift_expression
| GT_OP >> shift_expression
| LE_OP >> shift_expression
| GE_OP >> shift_expression
) >>
relational_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// equality_expression
// = relational_expression
// | equality_expression >>
// (
// EQ_OP >> relational_expression
// | NE_OP >> relational_expression
// )
// ;
equality_expression
= relational_expression >> equality_expression_helper
;
equality_expression_helper
= (
EQ_OP >> relational_expression
| NE_OP >> relational_expression
) >>
equality_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// and_expression
// = equality_expression
// | and_expression >> ADDROF >> equality_expression
// ;
and_expression
= equality_expression >> and_expression_helper
;
and_expression_helper
= ADDROF >> equality_expression >> and_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// exclusive_or_expression
// = and_expression
// | exclusive_or_expression >> XOR >> and_expression
// ;
exclusive_or_expression
= and_expression >> exclusive_or_expression_helper
;
exclusive_or_expression_helper
= XOR >> and_expression >> exclusive_or_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// inclusive_or_expression
// = exclusive_or_expression
// | inclusive_or_expression >> OR >> exclusive_or_expression
// ;
inclusive_or_expression
= exclusive_or_expression >> inclusive_or_expression_helper
;
inclusive_or_expression_helper
= OR >> exclusive_or_expression >> inclusive_or_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// logical_and_expression
// = inclusive_or_expression
// | logical_and_expression >> AND_OP >> inclusive_or_expression
// ;
logical_and_expression
= inclusive_or_expression >> logical_and_expression_helper
;
logical_and_expression_helper
= AND_OP >> inclusive_or_expression >> logical_and_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// logical_or_expression
// = logical_and_expression
// | logical_or_expression >> OR_OP >> logical_and_expression
// ;
logical_or_expression
= logical_and_expression >> logical_or_expression_helper
;
logical_or_expression_helper
= OR_OP >> logical_and_expression >> logical_or_expression_helper
| epsilon_p
;
// left recursion --> right recursion
// conditional_expression
// = logical_or_expression
// | logical_or_expression >> QUEST >> expression >> COLON >>
// conditional_expression
// ;
conditional_expression
= logical_or_expression >> conditional_expression_helper
;
conditional_expression_helper
= QUEST >> expression >> COLON
>> conditional_expression >> conditional_expression_helper
| epsilon_p
;
assignment_expression
= unary_expression >> assignment_operator >> assignment_expression
| conditional_expression
;
assignment_operator
= ASSIGN
| MUL_ASSIGN
| DIV_ASSIGN
| MOD_ASSIGN
| ADD_ASSIGN
| SUB_ASSIGN
| LEFT_ASSIGN
| RIGHT_ASSIGN
| AND_ASSIGN
| XOR_ASSIGN
| OR_ASSIGN
;
// left recursion --> right recursion
// expression
// = assignment_expression
// | expression >> COMMA >> assignment_expression
// ;
expression
= assignment_expression >> expression_helper
;
expression_helper
= COMMA >> assignment_expression >> expression_helper
| epsilon_p
;
constant_expression
= conditional_expression
;
declaration
= declaration_specifiers >> !init_declarator_list >> SEMICOLON
;
declaration_specifiers
= (
storage_class_specifier
| type_specifier
| type_qualifier
) >>
!declaration_specifiers
;
init_declarator_list
= init_declarator >> *(COMMA >> init_declarator)
;
init_declarator
= declarator >> !(ASSIGN >> initializer)
;
storage_class_specifier
= TYPEDEF
| EXTERN
| STATIC
| AUTO
| REGISTER
;
type_specifier
= VOID
| CHAR
| SHORT
| INT
| LONG
| FLOAT
| DOUBLE
| SIGNED
| UNSIGNED
| struct_or_union_specifier
| enum_specifier
// | TYPE_NAME
;
struct_or_union_specifier
= struct_or_union >>
(
IDENTIFIER >> !(LEFT_BRACE >> struct_declaration_list
>> RIGHT_BRACE)
| LEFT_BRACE >> struct_declaration_list >> RIGHT_BRACE
)
;
struct_or_union
= STRUCT
| UNION
;
struct_declaration_list
= +struct_declaration
;
struct_declaration
= specifier_qualifier_list >> struct_declarator_list >> SEMICOLON
;
specifier_qualifier_list
= (
type_specifier
| type_qualifier
) >>
!specifier_qualifier_list
;
struct_declarator_list
= struct_declarator >> *(COMMA >> struct_declarator)
;
struct_declarator
= declarator || (COLON >> constant_expression)
;
enum_specifier
= ENUM >> !IDENTIFIER >> LEFT_BRACE >> enumerator_list >> RIGHT_BRACE
;
enumerator_list
= enumerator >> *(COMMA >> enumerator)
;
enumerator
= IDENTIFIER >> !(ASSIGN >> constant_expression)
;
type_qualifier
= CONST
| VOLATILE
;
declarator
= !pointer >> direct_declarator
;
// left recursion --> right recursion
// direct_declarator
// = IDENTIFIER
// | LEFT_PAREN >> declarator >> RIGHT_PAREN
// | direct_declarator >>
// (
// LEFT_BRACKET >> !constant_expression >> RIGHT_BRACKET
// | LEFT_PAREN >>
// (
// parameter_type_list >> RIGHT_PAREN
// | identifier_list >> RIGHT_PAREN
// | RIGHT_PAREN
// )
// )
// ;
direct_declarator
= (
IDENTIFIER
| LEFT_PAREN >> declarator >> RIGHT_PAREN
) >>
direct_declarator_helper
;
direct_declarator_helper
= (
LEFT_BRACKET >> !constant_expression >> RIGHT_BRACKET
| LEFT_PAREN >>
! (
parameter_type_list
| identifier_list
) >> RIGHT_PAREN
) >> direct_declarator_helper
| epsilon_p
;
pointer
= STAR >> !(type_qualifier_list || pointer)
;
type_qualifier_list
= +type_qualifier
;
parameter_type_list
= parameter_list >> !(COMMA >> ELLIPSIS)
;
parameter_list
= parameter_declaration >> *(COMMA >> parameter_declaration)
;
parameter_declaration
= declaration_specifiers >>
!(
declarator
| abstract_declarator
)
;
identifier_list
= IDENTIFIER >> *(COMMA >> IDENTIFIER)
;
type_name
= specifier_qualifier_list >> !abstract_declarator
;
abstract_declarator
= pointer || direct_abstract_declarator
;
// left recursion --> right recursion
// direct_abstract_declarator
// = LEFT_PAREN >>
// (
// abstract_declarator >> RIGHT_PAREN
// | !parameter_type_list >> RIGHT_PAREN
// )
// | LEFT_BRACKET >> !constant_expression >> RIGHT_BRACKET
// | direct_abstract_declarator >>
// (
// LEFT_BRACKET >> !constant_expression >> RIGHT_BRACKET
// | LEFT_PAREN >> !parameter_type_list >> RIGHT_PAREN
// )
// ;
direct_abstract_declarator
= (
LEFT_PAREN >>
(
abstract_declarator >> RIGHT_PAREN
| !parameter_type_list >> RIGHT_PAREN
)
| LEFT_BRACKET >> !constant_expression >> RIGHT_BRACKET
) >>
direct_abstract_declarator_helper
;
direct_abstract_declarator_helper
= (
LEFT_BRACKET >> !constant_expression >> RIGHT_BRACKET
| LEFT_PAREN >> !parameter_type_list >> RIGHT_PAREN
) >>
direct_abstract_declarator_helper
| epsilon_p
;
initializer
= assignment_expression
| LEFT_BRACE >> initializer_list >> !COMMA >> RIGHT_BRACE
;
initializer_list
= initializer >> *(COMMA >> initializer)
;
statement
= labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
;
labeled_statement
= IDENTIFIER >> COLON >> statement
| CASE >> constant_expression >> COLON >> statement
| DEFAULT >> COLON >> statement
;
compound_statement
= LEFT_BRACE >> !(declaration_list || statement_list) >> RIGHT_BRACE
;
declaration_list
= +declaration
;
statement_list
= +statement
;
expression_statement
= !expression >> SEMICOLON
;
selection_statement
= IF >> LEFT_PAREN >> expression >> RIGHT_PAREN >> statement
>> !(ELSE >> statement)
| SWITCH >> LEFT_PAREN >> expression >> RIGHT_PAREN >> statement
;
iteration_statement
= WHILE >> LEFT_PAREN >> expression >> RIGHT_PAREN >> statement
| DO >> statement >> WHILE >> LEFT_PAREN >> expression
>> RIGHT_PAREN >> SEMICOLON
| FOR >> LEFT_PAREN >> expression_statement >> expression_statement
>> !expression >> RIGHT_PAREN >> statement
;
jump_statement
= GOTO >> IDENTIFIER >> SEMICOLON
| CONTINUE >> SEMICOLON
| BREAK >> SEMICOLON
| RETURN >> !expression >> SEMICOLON
;
function_definition
= !declaration_specifiers
>> declarator
>> !declaration_list
>> compound_statement
;
external_declaration
= function_definition
| declaration
;
// parser start symbol
translation_unit
= *external_declaration
;
}
// keywords
symbols<> keywords;
// operators
strlit<>
ELLIPSIS, RIGHT_ASSIGN, LEFT_ASSIGN, ADD_ASSIGN, SUB_ASSIGN,
MUL_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, AND_ASSIGN, XOR_ASSIGN,
OR_ASSIGN, RIGHT_OP, LEFT_OP, INC_OP, DEC_OP, PTR_OP, AND_OP,
OR_OP, LE_OP, GE_OP, EQ_OP, NE_OP;
chlit<>
SEMICOLON, COMMA, COLON, ASSIGN, LEFT_PAREN, RIGHT_PAREN,
DOT, ADDROF, BANG, TILDE, MINUS, PLUS, STAR, SLASH, PERCENT,
LT_OP, GT_OP, XOR, OR, QUEST;
rule<ScannerT>
LEFT_BRACE, RIGHT_BRACE, LEFT_BRACKET, RIGHT_BRACKET;
// terminals
rule<ScannerT>
AUTO, BREAK, CASE, CHAR, CONST, CONTINUE, DEFAULT, DO, DOUBLE,
ELSE, ENUM, EXTERN, FOR, FLOAT, GOTO, IF, INT, LONG, REGISTER,
RETURN, SHORT, SIGNED, SIZEOF, STATIC, STRUCT, SWITCH, TYPEDEF,
UNION, UNSIGNED, VOID, VOLATILE, WHILE, IDENTIFIER,
STRING_LITERAL_PART, STRING_LITERAL, INT_CONSTANT_HEX, INT_CONSTANT,
INT_CONSTANT_OCT, INT_CONSTANT_DEC, INT_CONSTANT_CHAR,
FLOAT_CONSTANT,FLOAT_CONSTANT_1, FLOAT_CONSTANT_2, FLOAT_CONSTANT_3,
CONSTANT;
// nonterminals
rule<ScannerT>
primary_expression, postfix_expression, postfix_expression_helper,
argument_expression_list, unary_expression, unary_operator,
cast_expression,
multiplicative_expression, multiplicative_expression_helper,
additive_expression, additive_expression_helper,
shift_expression, shift_expression_helper,
relational_expression, relational_expression_helper,
equality_expression, equality_expression_helper,
and_expression, and_expression_helper,
exclusive_or_expression, exclusive_or_expression_helper,
inclusive_or_expression, inclusive_or_expression_helper,
logical_and_expression, logical_and_expression_helper,
logical_or_expression, logical_or_expression_helper,
conditional_expression, conditional_expression_helper,
assignment_expression, assignment_operator,
expression, expression_helper, constant_expression, declaration,
declaration_specifiers, init_declarator_list, init_declarator,
storage_class_specifier, type_specifier, struct_or_union_specifier,
struct_or_union, struct_declaration_list, struct_declaration,
specifier_qualifier_list, struct_declarator_list,
struct_declarator, enum_specifier, enumerator_list, enumerator,
type_qualifier, declarator,
direct_declarator, direct_declarator_helper, pointer,
type_qualifier_list, parameter_type_list, parameter_list,
parameter_declaration, identifier_list, type_name,
abstract_declarator,
direct_abstract_declarator, direct_abstract_declarator_helper,
initializer, initializer_list, statement, labeled_statement,
compound_statement, declaration_list, statement_list,
expression_statement, selection_statement, iteration_statement,
jump_statement, translation_unit, external_declaration,
function_definition;
rule<ScannerT> const&
start() const { return translation_unit; }
};
};
///////////////////////////////////////////////////////////////////////////////
// main entrypoint
int
main(int argc, char* argv[])
{
// Start grammar definition
cerr << "C Grammar checker implemented with Spirit ..." << endl;
// main driver code
c_grammar g;
if (2 == argc)
parse(g, argv[1]);
else
cerr << "No filename given" << endl;
return 0;
} |
|