mirror of https://github.com/KLayout/klayout.git
475 lines
12 KiB
Plaintext
475 lines
12 KiB
Plaintext
#
|
|
# Copyright (C) 2006-2024 Matthias Koefferlein
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
#
|
|
|
|
require "cpp_classes.rb"
|
|
require "cpp_parser_classes.rb"
|
|
|
|
grammar CPP
|
|
|
|
rule s
|
|
[ \t\n\r]*
|
|
end
|
|
|
|
rule sp
|
|
[ \t\n\r]+
|
|
end
|
|
|
|
rule string_const
|
|
'"' ( [^\\"] / "\\" . )* '"'
|
|
end
|
|
|
|
rule char_const
|
|
"'" ( [^\\'] / "\\" . )* "'"
|
|
end
|
|
|
|
rule numeric_const
|
|
"-"? ( [0-9]+ ( "." [0-9]* )? / "." [0-9]+ ) ( [eE] "-"? [0-9]+ )?
|
|
end
|
|
|
|
rule hex_const
|
|
"0x" [0-9a-fA-F]+
|
|
end
|
|
|
|
rule attribute_value
|
|
"(" ( s ( "," s )? attribute_value )* s ")" / numeric_const / string_const / id
|
|
end
|
|
|
|
rule ignored_attr
|
|
"__attribute__" s attribute_value /
|
|
"__asm" s attribute_value /
|
|
"constexpr" ![a-zA-Z0-9_] /
|
|
"__extension__" /
|
|
"__inline" /
|
|
"__m64" /
|
|
"__m128" /
|
|
"__m128d" /
|
|
"__m128i" /
|
|
"__m256" /
|
|
"__m256d" /
|
|
"__m256i" /
|
|
"__m512" /
|
|
"__m512d" /
|
|
"__m512i" /
|
|
"__mmask8" /
|
|
"__mmask16" /
|
|
"__v8df" /
|
|
"__v8di" /
|
|
"__v16sf" /
|
|
"__v16si" /
|
|
"decltype" s attribute_value /
|
|
"alignas" s "(" s block s ")" /
|
|
"[[" s block s "]]"
|
|
end
|
|
|
|
rule a
|
|
s ( ignored_attr s )*
|
|
end
|
|
|
|
rule unary_op
|
|
"~" / "!" / "-" / "*" / "&"
|
|
end
|
|
|
|
rule bin_op_wo_gt
|
|
"+=" / "++" / "+" / "->" / "-=" / "--" / "-" / "()" / "[]" / "&&" / "&=" / "&" / "||" / "|=" / "|" /
|
|
"==" / "=" / "!=" / "*=" / "*" / "/=" / "/" / "%=" / "%" / "<=" / "<<=" / "<<" / "<" /
|
|
"~=" / "^=" / "^" / "~=" / ">=" / ">>="
|
|
end
|
|
|
|
rule bin_op
|
|
bin_op_wo_gt / ">>" / ">"
|
|
end
|
|
|
|
rule id
|
|
"operator" s "," /
|
|
"operator" s ( bin_op / unary_op / "," ) /
|
|
"operator" sp [a-zA-Z_0-9\*\& \t\n\r]+ &( s "(" ) /
|
|
"~"? [a-zA-Z_] [a-zA-Z_0-9]*
|
|
end
|
|
|
|
rule template_arg_part_any
|
|
block_wo_gt <PConst>
|
|
end
|
|
|
|
rule template_arg_part
|
|
qualified_id &( ( s ">" / "," ) ) / template_arg_part_any
|
|
end
|
|
|
|
rule template_args
|
|
template_arg_part ( s "," s template_arg_part )* <PTemplateArgs>
|
|
end
|
|
|
|
rule id_with_template_args
|
|
id:id taspec:( s "<" s ta:template_args s ">" )? <PId>
|
|
end
|
|
|
|
rule qualified_id
|
|
globalspec:( "::" s )? id_with_template_args ( s "::" id_with_template_args )* <PQualifiedId>
|
|
end
|
|
|
|
rule int_type_attr
|
|
"signed" ![a-zA-Z0-9_] / "unsigned" ![a-zA-Z0-9_] / "long" ( sp "long" )? ![a-zA-Z0-9_] / "short" ![a-zA-Z0-9_]
|
|
end
|
|
|
|
rule int_type
|
|
(
|
|
( int_type_attr s )* "int" ![a-zA-Z0-9_] /
|
|
int_type_attr ( s int_type_attr )* !"char" ( s "int" ![a-zA-Z0-9_] )?
|
|
) <PIntType>
|
|
end
|
|
|
|
rule char_type
|
|
( "signed" sp / "unsigned" sp )? s !"int" "char" ![a-zA-Z0-9_] <PCharType>
|
|
end
|
|
|
|
rule bool_type
|
|
"bool" ![a-zA-Z0-9_] <PBoolType>
|
|
end
|
|
|
|
rule void_type
|
|
"void" ![a-zA-Z0-9_] <PVoidType>
|
|
end
|
|
|
|
rule float_type
|
|
( "long" sp )? ( "double" / "float" ) ![a-zA-Z0-9_] <PFloatType>
|
|
end
|
|
|
|
rule enum_spec
|
|
a id:id a initspec:( s "=" s init:block_wo_comma )? <PEnumSpec>
|
|
end
|
|
|
|
rule enum_body
|
|
enum_spec ( s "," s enum_spec )* ","?
|
|
end
|
|
|
|
rule enum_type
|
|
"enum" ![a-zA-Z0-9_] a is_class:(s "class" )? s id:id? ( s ":" s type )? bodyspec:( s "{" s body:enum_body s "}" )? <PEnumType>
|
|
end
|
|
|
|
rule virtual_spec
|
|
"virtual" ![a-zA-Z0-9_] <PVirtual>
|
|
end
|
|
|
|
rule explicit_key
|
|
"explicit" ![a-zA-Z0-9_]
|
|
end
|
|
|
|
rule mutable_key
|
|
"mutable" ![a-zA-Z0-9_]
|
|
end
|
|
|
|
rule member_declaration_wo_semicolon
|
|
template:( d:template_decl s )?
|
|
attr:( ( explicit_key / mutable_key / storage_class / inline_spec / virtual_spec / ignored_attr ) s )*
|
|
t:type
|
|
# type declaration ends with a } .. does not need a semicolon
|
|
# (i.e. nested struct or enum)
|
|
&{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
|
s
|
|
( ":" s block_wo_curly_braces s )?
|
|
( trailing_return_type )?
|
|
a
|
|
(
|
|
"{" s block s "}" /
|
|
";"?
|
|
) <PDeclaration>
|
|
end
|
|
|
|
rule member_declaration_w_semicolon
|
|
template:( d:template_decl s )?
|
|
attr:( ( explicit_key / mutable_key / storage_class / inline_spec / virtual_spec / ignored_attr ) s )*
|
|
t:type
|
|
# opposite case (member_see declaration_wo_semicolon)
|
|
# (i.e. nested struct or enum)
|
|
!{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
|
s
|
|
( ":" s block_wo_curly_braces s )?
|
|
( trailing_return_type )?
|
|
a
|
|
(
|
|
"{" s block s "}" /
|
|
";"
|
|
) <PDeclaration>
|
|
end
|
|
|
|
rule member_declaration
|
|
a ( member_declaration_wo_semicolon / member_declaration_w_semicolon )
|
|
end
|
|
|
|
rule friend_decl
|
|
a template:( d:template_decl s )? "friend" ![a-zA-Z0-9_] s t:member_declaration <PFriendDecl>
|
|
end
|
|
|
|
rule class_struct_body_declarations
|
|
( s ";" / s static_assert / s friend_decl / s using / s typedef / s !( "public" / "private" / "protected" ) member_declaration )*
|
|
end
|
|
|
|
rule class_struct_body
|
|
class_struct_body_declarations
|
|
(
|
|
s "public" s ":" d:class_struct_body_declarations <PPublicClassStructBodyDeclarations> /
|
|
s "private" s ":" d:class_struct_body_declarations <PPrivateClassStructBodyDeclarations> /
|
|
s "protected" s ":" d:class_struct_body_declarations <PProtectedClassStructBodyDeclarations>
|
|
)*
|
|
end
|
|
|
|
rule class_id
|
|
# In order to easily distinguish between constructor methods without
|
|
# a return type and class or typedef names we assume that all "name("
|
|
# constructs are considered constructor names but "name (*func_ptr) ()" or "name (class::*method_ptr) ()" is not.
|
|
qualified_id s ( "..." s )? !( "(" !( s "*" / s qualified_id s "::*" ) )
|
|
end
|
|
|
|
rule typeof
|
|
"__typeof" s "(" s qid:qualified_id s ")" <PTypeOf>
|
|
end
|
|
|
|
rule base_class
|
|
attr:( "public" ![a-zA-Z0-9_] s / "private" ![a-zA-Z0-9_] s / "protected" ![a-zA-Z0-9_] s / "virtual" ![a-zA-Z0-9_] s )* a cid:class_id <PBaseClass>
|
|
end
|
|
|
|
rule base_classes
|
|
base_class ( s "," s base_classes )?
|
|
end
|
|
|
|
rule class_or_struct_type
|
|
stype:( "union" ![a-zA-Z0-9_] / "struct" ![a-zA-Z0-9_] / "class" ![a-zA-Z0-9_] ) a idspec:( s id:class_id )? bcspec:( s ":" s bc:base_classes )? bodyspec:( s "{" s body:class_struct_body s "}" )? <PStructOrClassType>
|
|
end
|
|
|
|
rule concrete_type
|
|
( class_or_struct_type / enum_type / float_type / char_type / int_type / bool_type / void_type / typeof / class_id )?
|
|
end
|
|
|
|
rule cv
|
|
( "const" ![a-zA-Z0-9_] / "__const" ![a-zA-Z0-9_] / "volatile" ![a-zA-Z0-9_] / "__volatile" ![a-zA-Z0-9_] ) <PCV>
|
|
end
|
|
|
|
rule pointer
|
|
cvspec:( cv:cv s )? "*" itspec:( s it:inner_type )? <PPointer>
|
|
end
|
|
|
|
rule reference
|
|
cvspec:( cv:cv s )? "&" itspec:( s it:inner_type )? <PReference>
|
|
end
|
|
|
|
rule array_spec
|
|
"[" s block_wo_comma s "]" <PArraySpec>
|
|
end
|
|
|
|
rule func_arg_part
|
|
t:type_wo_comma !"..." <PFuncArgPart>
|
|
end
|
|
|
|
rule ellipsis
|
|
"..." <PEllipsis>
|
|
end
|
|
|
|
rule func_args
|
|
&")" /
|
|
func_arg_part ( s "," s func_arg_part )* ( s "," s ellipsis )? /
|
|
ellipsis
|
|
end
|
|
|
|
rule noexcept_spec
|
|
"noexcept" ( s "(" s block s ")" )?
|
|
end
|
|
|
|
rule func_spec
|
|
"(" s fa:( a:func_args )? s ")" cvspec:( s cv:cv )? refspec:( s ref:( "&" !"&" / "&&" ) )? ( s "throw" s "(" s ( type_wo_comma s )? ")" / s noexcept_spec / s override_key )* a <PFuncSpec>
|
|
end
|
|
|
|
rule member_pointer
|
|
cspec:( qid:qualified_id s "::*" s ) itspec:( it:inner_type )? cvspec:( s cv:cv )? refspec:( s ref:( "&" !"&" / "&&" ) )? <PMemberPointer>
|
|
end
|
|
|
|
rule inner_type_with_cv
|
|
cvspec:cv s it:inner_type <PInnerTypeWithCV>
|
|
end
|
|
|
|
rule inner_type
|
|
it:(
|
|
"(" s inner_type s ")" /
|
|
inner_type_with_cv /
|
|
pointer /
|
|
reference /
|
|
member_pointer /
|
|
( "__restrict" ![a-zA-Z0-9_] s / "..." s )* qualified_id
|
|
)
|
|
pfx:( s spec:( array_spec / func_spec ) )*
|
|
<PInnerType>
|
|
end
|
|
|
|
rule init_spec
|
|
block_wo_comma / "default" / "delete" / "0"
|
|
end
|
|
|
|
rule type
|
|
cvspec:( cv:cv s )?
|
|
a
|
|
( "typename" ![a-zA-Z0-9_] s )?
|
|
ct:concrete_type
|
|
a
|
|
il:( s t1:inner_type i1:(s "=" s is1:init_spec)? tt:( s "," s t2:inner_type i2:(s "=" s is2:init_spec)? )* )?
|
|
# alternative initialization if only a concrete type is given:
|
|
pi:( s "=" s is:init_spec )?
|
|
<PType>
|
|
end
|
|
|
|
rule type_wo_comma
|
|
cvspec:( cv:cv s )?
|
|
a
|
|
( "typename" ![a-zA-Z0-9_] s )?
|
|
ct:concrete_type
|
|
il:( s t:inner_type i:(s "=" s is:init_spec)? )?
|
|
# alternative initialization if only a concrete type is given:
|
|
pi:( s "=" s is:init_spec )?
|
|
<PTypeWoComma>
|
|
end
|
|
|
|
rule type_for_template
|
|
cvspec:( cv:cv s )?
|
|
a
|
|
( ( "typename" / "class" ) ![a-zA-Z0-9_] s ( "..." s )? )?
|
|
ct:concrete_type
|
|
il:( s t:inner_type )?
|
|
<PTypeForTemplate>
|
|
end
|
|
|
|
rule storage_class
|
|
( "static" ![a-zA-Z0-9_] / "extern" ![a-zA-Z0-9_] ( s '"C"' / s '"C++"' / s '"Pascal"' )? ) <PStorageClass>
|
|
end
|
|
|
|
rule override_key
|
|
"override" ![a-zA-Z0-9_]
|
|
end
|
|
|
|
rule inline_spec
|
|
"inline" ![a-zA-Z0-9_] <PInline>
|
|
end
|
|
|
|
# parse over blocks as gracefully as possible ...
|
|
rule block_atom_wo_gt
|
|
"(" s block s ")" / "[" s block s "]" / "<" !"=" s block_wo_gt ( s "," s block_wo_gt )* s ">" /
|
|
numeric_const / hex_const / string_const / char_const /
|
|
id ( s "{" s block s "}" )? / unary_op / bin_op_wo_gt / "?" / "::" / "." / ":" / ";"
|
|
end
|
|
|
|
rule block_wo_gt
|
|
( s block_atom_wo_gt / s "{" s block s "}" )*
|
|
end
|
|
|
|
# parse over blocks as gracefully as possible ...
|
|
rule block_atom
|
|
"(" s block s ")" / "[" s block s "]" / "<" s block_wo_gt ( s "," s block_wo_gt )* s ">" /
|
|
numeric_const / hex_const / string_const / char_const /
|
|
id ( s "{" s block s "}" )? / unary_op / bin_op / "?" / "::" / "." / ":"
|
|
end
|
|
|
|
rule block
|
|
( s block_atom / s ";" / s "," / s "{" s block s "}" )*
|
|
end
|
|
|
|
rule block_wo_curly_braces
|
|
( s block_atom / s "," )*
|
|
end
|
|
|
|
rule block_wo_comma
|
|
( s block_atom / s "{" s block s "}" )*
|
|
end
|
|
|
|
rule using
|
|
"using" ![a-zA-Z0-9_] ( s "namespace" )? ![a-zA-Z0-9_] s id:qualified_id a ";" <PUsing>
|
|
end
|
|
|
|
rule static_assert
|
|
"static_assert" s "(" s block s ")"
|
|
end
|
|
|
|
rule typedef
|
|
a "typedef" ![a-zA-Z0-9_] s t:type a ";" <PTypedef>
|
|
end
|
|
|
|
rule template_decl_arg
|
|
t:type_for_template dtspec:( s "=" s dt:block_wo_gt )? <PClassTemplateArg>
|
|
end
|
|
|
|
rule template_decl
|
|
"template" s "<" s ( !">" template_decl_arg s ( "," s template_decl_arg )* )? s ">" <PTemplateDecl>
|
|
end
|
|
|
|
rule trailing_return_type
|
|
"->" s ( "decltype" s "(" s block s ")" / type )
|
|
end
|
|
|
|
rule declaration_w_semicolon
|
|
template:( d:template_decl s )?
|
|
template_member:( d_member:template_decl s )?
|
|
attr:( ( storage_class / inline_spec / ignored_attr ) s )*
|
|
t:type
|
|
# type declaration ends with a } .. does not need a semicolon
|
|
# (i.e. nested struct or enum)
|
|
!{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
|
s ( ":" s block_wo_curly_braces s )?
|
|
( trailing_return_type )?
|
|
a
|
|
(
|
|
"{" s block s "}" /
|
|
";"
|
|
) <PDeclaration>
|
|
end
|
|
|
|
rule declaration_wo_semicolon
|
|
template:( d:template_decl s )?
|
|
attr:( ( storage_class / inline_spec / ignored_attr ) s )*
|
|
t:type
|
|
# opposite case (see declaration_wo_semicolon)
|
|
# (i.e. nested struct or enum)
|
|
&{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
|
s ( ":" s block_wo_curly_braces s )?
|
|
( trailing_return_type )?
|
|
a
|
|
(
|
|
"{" s block s "}" /
|
|
";"?
|
|
) <PDeclaration>
|
|
end
|
|
|
|
rule declaration
|
|
declaration_w_semicolon / declaration_wo_semicolon
|
|
end
|
|
|
|
rule namespace
|
|
"namespace" ![a-zA-Z0-9_] s n:id
|
|
a "{" decls:( a ( ";" / static_assert / using / typedef / namespace / declaration ) )* s "}" <PNamespace>
|
|
end
|
|
|
|
rule extern_decl
|
|
"extern" s n:( '"C"' / '"C++"' / '"Pascal"' ) s
|
|
a "{" decls:( a ( ";" / typedef / namespace / extern_decl / declaration ) )* s "}" <PExternBlock>
|
|
end
|
|
|
|
rule asm
|
|
"asm" s "(" s block s ")"
|
|
end
|
|
|
|
rule module
|
|
( a ( ";" / static_assert / using / typedef / namespace / extern_decl / declaration / asm ) )* s <PModule>
|
|
end
|
|
|
|
end
|
|
|