:- use_module(library(dcg/basics)). :- set_prolog_flag(double_quotes, chars). /* Stroustroup, B. The C++ Programming Language 2nd Ed. 1993. Appendix A: Grammar Summary (p. 614) */ % 1 or more whitespace characters, including newline. ws --> blank, blanks. % Because it just looks weird having a lot of quoted commas in a % comma-separated list. comma --> ",". /* Symbols that are operators: */ % Equality greater --> ">". greater_or_equal --> ">=". less --> "<". less_or_equal --> "<=". equal --> "==". not_equal --> "!=". % Bit shift shift_left --> "<<". shift_right --> ">>". % Arithmetic addition --> "+". subtraction --> "-". mulitplication --> "*". division --> "/". exponentiation --> "^". modulo --> "%". /* r.17.1 Keywords */ class_name(N) --> identifier(N). enum_name(N) --> identifier(N). typedef_name(N) --> identifier(N). keyword(K) --> blank, string(K). % TODO: "Note that a typedef-name naming a class is also a class-name" % (p. 615). /* r.17.2 Expressions */ expression([E|Exps]) --> blanks, assignment_expression([E|Exps]), blanks. expression([E1, E2]) --> expression(E1), blanks, comma, blanks, assignment_expression(E2), blanks. assignment_expression([E|Exps]) --> conditional_expression([E|Exps]). assignment_expression([E1, Operator, E2]) --> unary_expression(E1), assignment_operator(Operator), assignment_expression(E2). conditional_expression([E|Exps]) --> logical_or_expression([E|Exps]). conditional_expression([E1, E2, E3]) --> logical_or_expression(E1), expression(E2), conditional_expression(E3). % DCG rules given here for logical/inclusive and/or expressions from % p. 615 are more literal than what's in the book. logical_and_expression([E1, E2]) --> expression(E1), "&&", expression(E2). logical_or_expression([E1, E2]) --> expression(E1), "||", expression(E2). inclusive_or_expression([E1, E2]) --> expression(E1), "|", expression(E2). inclusive_and_expression([E1, E2]) --> expression(E1), "&", expression(E2). equality_expression([E|Exps]) --> relational_expression([E|Exps]). equality_expression([E1, E2]) --> equality_expression(E1), ("==" | "!="), relational_expression(E2). relational_expression([E|Exps]) --> shift_expression([E|Exps]). relational_expression([E1, E2]) --> relational_expression(E1), ("<" | ">" | "<=" | ">=" ), shift_expression. shift_expression([E|Exps]) --> additive_expression([E|Exps]). shift_expression([E1, E2]) --> shift_expression(E1), ("<<" | ">>"), additive_expression(E2). additive_expression([E|Exps]) --> multiplicative_expression([E|Exps]). additive_expression([E1, E2]) --> additive_expression(E1), ("+" | "-"), multiplicative_expression(E2). multiplicative_expression([E|Exps]) --> pm_expression([E|Exps]). multiplicative_expression([E1, E2]) --> multiplicative_expression(E1), ("*" | "/" | "%"), pm_expression(E2). % What the fudge is a "pm_expression"? (p. 616). The 'm' probably % stands for "member". pm_expression([E|Exps]) --> cast_expression([E|Exps]). pm_expression([E1, E2]) --> pm_expression(E1), (".*" | "->*"), cast_expression(E2). cast_expression([E|Exps]) --> unary_expression([E|Exps]). cast_expression([E1, E2]) --> type_name(E1), cast_expression(E2). sizeof([E|Exps]) --> "sizeof", ws, unary_expression([E|Exps]). sizeof([E|Exps]) --> "sizeof", blanks, "(", type_name([E|Exps]), ")". unary_expression([E|Exps]) --> postfix_expression([E|Exps]). unary_expression([E|Exps]) --> ("++" | "--"), unary_expression([E|Exps]). unary_expression([E|Exps]) --> "sizeof", unary_expression([E|Exps]). unary_expression([E|Exps]) --> sizeof([E|Exps]). unary_expression([E1, E2]) --> unary_operator(E1), cast_expression(E2). unary_expression([E|Exps]) --> ( allocation_expression([E|Exps]) | deallocation_expression([E|Exps]) ). unary_operator --> ("*" | "&" | "+" | "-" | "!" | "~"). allocation_expression_([E1,E2,E3]) --> "new", ws, placement(E1), new_type_name(E2), new_initializer(E3). allocation_expression_([E1,E2,E3]) -->"new", ws, placement(E1), blanks, "(" blanks, type_name(E2), blanks, ")" blanks, new_initializer(E3). allocation_expression_([E1,E2]) --> "new", ws, new_type_name(E1), new_initializer(E2). allocation_expression_([E1,E2,E3]) --> "new", ws, "(", type_name(E1), ")". new_initializer(E2). allocation_expression([E|Exps]) --> "::", allocation_expression_([E|Exps]). allocation_expression([E|Exps]) --> allocation_expression_([E|Exps]). placement([E|Exps]) --> blanks, "(", expression_list([E|Exps]), ")". % TODO: new_declarator (was skipped). new_initializer([E|Exps]) --> blanks, "(", initializer_list([E|Exps]), ")". new_initializer([E|Exps]) --> blanks, "(", blanks, ")". deallocation_expression_([E|Exps]) --> ws, "delete", ws, cast_expression([E|Exps]). deallocation_expression_([E|Exps]) --> ws, "delete", blanks, "[", blanks, "]", ws, cast_expression([E|Exps]). deallocation_expression([E|Exps]) --> deallocation_expression_([E|Exps]). deallocation_expression([E|Exps]) --> "::", deallocation_expression_([E|Exps]). postfix_expression([E|Exps]) --> primary_expression([E|Exps]). postfix_expression([E|Exps]) --> postfix_expression([E|Exps]), ("++" | "--"). postfix_expression([E1, E2]) --> postfix_expression(E1), blanks, "[", expression(E2), "]". postfix_expression([E1, E2]) --> postfix_expression(E1), blanks, "(", expression_list(E2), ")". postfix_expression([E1, E2]) --> simple_type_name(E1), blanks, "(", expression_list(E2), ")". postfix_expression([E1, E2]) --> postfix_expression(E1), ("." | "->"), name(E2). expression_list([E|Exps]) --> assignment_expression([E|Exps]). expression_list([E1, E2]) --> expression_list(E1), blanks, comma, blanks, assignment_expression(E2). primary_expression([]) --> "this". primary_expression([E]) --> literal([E]). primary_expression([E|Exps]) --> "::", identifier([E|Exps]). primary_expression([E|Exps]) --> "::", operator_function_name([E|Exps]). primary_expression([E|Exps]) --> "::", qualified_name([E|Exps]). primary_expression([E|Exps]) --> "(", blanks, expression([E|Exps]), blanks, ")". primary_expression([E|Exps]) --> name([E|Exps]). name([E|Exps]) --> identifier([E|Exps]). name([E|Exps]) --> operator_function_name([E|Exps]). name([E|Exps]) --> conversion_function_name([E|Exps]). name([E|Exps]) --> "~", class_name([E|Exps]). name([E|Exps]) --> qualified_name([E|Exps]). qualified_name([E1, E2]) --> qualified_class_name(E1), "::", name(E2). literal([X]) --> integer_constant([X]). literal([X]) --> character_constant([X]). literal([X]) --> floating_constant([X]). literal([X]) --> string_literal([X]). /* r.17.3 Declarations (p. 618) */ declaration([E|Exps]) --> decl_specifiers([E|Exps]), blanks, ";". declaration([E|Exps]) --> declarator_list([E|Exps]), blanks, ";". declaration([E1, E2]) --> decl_specifiers(E1), blanks, declarator_list(E2), blanks, ";". declaration([E|Exps]) --> asm_declaration([E|Exps]). declaration([E|Exps]) --> template_declaration([E|Exps]). declaration([E|Exps]) --> linkage_declaration([E|Exps]). auto --> "auto", ws. register --> "register", ws. static --> "static", ws. extern --> "extern", ws. friend --> "friend", ws. typedef --> "typedef", ws. inline --> "inline", ws. virtual --> "virtual", ws. const --> "const", ws. volatile --> "volatile", ws. decl_specifier([E|Exps]) --> storage_class_specifier([E|Exps]). decl_specifier([E|Exps]) --> type_specifier([E|Exps]). decl_specifier([E|Exps]) --> fct_specifier([E|Exps]). decl_specifier(["friend"]) --> friend decl_specifier(["typedef"]) --> typedef. decl_specifiers([E|Exps]) --> decl_specifier([E|Exps]). storage_class_specifier(["auto"]) --> auto. storage_class_specifier(["register"]) --> register. storage_class_specifier(["static"]) --> static storage_class_specifier(["extern"]) --> extern fct_specifier(["inline"]) --> inline. fct_specifier(["virtual"]) --> virtual. type_specifier([E|Exps]) --> simple_type_name([E|Exps]). type_specifier([E|Exps]) --> class_specifier([E|Exps]). type_specifier([E|Exps]) --> enum_specifier([E|Exps]). type_specifier([E|Exps]) --> elaborated_type_specifier([E|Exps]). type_specifier(["const"]) --> const. type_specifier(["volatile"]) --> volatile. simple_type_name --> [].