home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lifeos2.zip / LIFE-1.02 / EXAMPLES / SUPERLIN / C_PARSER.LF < prev    next >
Text File  |  1996-06-04  |  48KB  |  1,979 lines

  1. %
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %
  4. %
  5. %                            PARSER FOR C CODE
  6. %                            -----------------
  7. %
  8. %  
  9. %
  10. %
  11. %  AUTHOR : Arnaud Venet                     CREATION : August 9th 1993
  12. %  ------                                    --------
  13. %
  14. %
  15. %                             ---------------                        
  16. %
  17. %                    
  18. %                   Last modification : March 3rd 1994
  19. %
  20. %
  21. %                             ---------------
  22. %
  23. %
  24. %                (C) Digital Equipment Corporation 1993 - 1994
  25. %
  26. %
  27. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  28. %
  29. %
  30. %  USE : c_parse(file1, file2, ..., fileN,
  31. %                parse_mode => {light; heavy}, %% light mode not yet implemented
  32. %                error_mode => {talkie; mute}, %% mute : don't write error messages
  33. %                error_log => ErrorLog, %% the errors occured
  34. %                error => bool, %% true if a major parse error occured
  35. %                tree => Tree)
  36. %
  37. %
  38. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  39. %
  40.  
  41.  
  42.  
  43. module("c_parser") ?
  44.  
  45.  
  46. public(c_parse, light, heavy, talkie, mute, 
  47.        error, warning) ?
  48.  
  49.  
  50. %
  51. % ------------------------------------------------------------------------------
  52. %
  53. %  The symbols of the nodes and features of the syntactic tree. It is necessary
  54. %  because of the currently flat structure of modules to avoid symbols clashes.
  55. %
  56. % ------------------------------------------------------------------------------
  57. %
  58.  
  59.  
  60. load("c_public_terms") ?
  61.  
  62.  
  63. open("c_public_terms") ?
  64.  
  65.  
  66. %
  67. % ------------------------------------------------------------------------------
  68. %
  69.  
  70.  
  71. import("accumulators") ?
  72.  
  73. acc_info(dcg,Term, Xs, Ys, acc_pred => 'C'(Term,false,Xs,Ys),
  74.      in_name => 0, out_name => rest) ?
  75.  
  76. expand_load(true) ?
  77.  
  78. load("c_utils") ?
  79.  
  80. load("c_tokenizer") ?
  81.  
  82. load("c_builders") ?
  83.  
  84.  
  85. %
  86. % ------------------------------------------------------------------------------
  87. %
  88. %  The accumulators for the collection of the arithmetic expressions
  89. %
  90. % ------------------------------------------------------------------------------
  91. %
  92.  
  93.  
  94. acc_info(left_expression, Expression, OldLeftExpression, NewLeftExpression,
  95.          acc_pred => (NewLeftExpression = Expression)) ?
  96.  
  97.  
  98. acc_info(left_assignment_expression, Expression, OldLeftExpression, 
  99.          NewLeftExpression,
  100.          acc_pred => (NewLeftExpression = Expression)) ?
  101.  
  102.  
  103. %
  104. % ------------------------------------------------------------------------------
  105. %
  106.  
  107.  
  108. pred_info(expression_tail,
  109.           [left_assignment_expression]) ?
  110.  
  111.  
  112. pred_info([conditional_expression,
  113.            arithmetic_expression,
  114.            collect_arithmetic_expression,
  115.            postfix_expression,
  116.            postfix_expression_tail,
  117.            constant_expression],
  118.           [left_expression]) ?
  119.  
  120.  
  121. %
  122. % ------------------------------------------------------------------------------
  123. %
  124.  
  125.  
  126. report_parse_error(Message) :-
  127.   parse_error <<- true,
  128.   current_token = @(line => Line, file => File),
  129.   error_number <<- error_number + 1,
  130.   Error = the_error_log.error_number,
  131.   Error.type <<- error, 
  132.   Error.message <<- Message, 
  133.   Error.cause <<- current_token, 
  134.   Error.file <<- File, 
  135.   Error.line <<- Line,
  136.   cond(the_error_mode :== talkie,
  137.     (
  138.       nl_err,
  139.       write_err(">>> parse error : ", root_sort(File), ", line ", Line, 
  140.                 " before '", display_token(current_token), "'"),
  141.       cond(Message :\== @,
  142.         write_err(Message)
  143.       ),
  144.       nl_err
  145.     )
  146.   ).
  147.  
  148.  
  149. %
  150. % ------------------------------------------------------------------------------
  151. %
  152. %  This predicate looks for a particular token. If the current token is not 
  153. %  the expected one it produces a warning and inserts a token
  154. %  with a special flag set.
  155. %
  156. % ------------------------------------------------------------------------------
  157. %
  158.  
  159.  
  160. recover_token(Token, What) :-
  161.   current_token :== What,
  162.   !,
  163.   Token = get_current_token,
  164.   get_next_token.
  165.  
  166.  
  167. recover_token(Token, What) :-
  168.   Token = What & @(inserted => true,
  169.                    next => current_token,
  170.                    previous => current_token.previous,
  171.                    line => current_token.line,
  172.                    column => current_token.column, 
  173.                    file => current_token.file,
  174.                    white_spaces => ""),
  175.   local_error(strcon(strcon("Missing '", strcon(psi2str(What), "' before ")), 
  176.                      psi2str(display_token(current_token))),
  177.                      Token).
  178.  
  179.  
  180. %
  181. % ------------------------------------------------------------------------------
  182. %
  183.  
  184.  
  185. Term : c_parse(tree => Tree, error_log => ErrorLog, 
  186.                parse_mode => ParseMode, error_mode => ErrorMode,
  187.                error => ParseError) :-
  188.   ParseMode = {light; heavy},
  189.   ErrorMode = {talkie; mute},
  190.   !,
  191.   the_parse_mode <<- ParseMode,
  192.   the_error_mode <<- ErrorMode,
  193.   error_number <<- 0,
  194.   ErrorLog = the_error_log,
  195.   clear_tree,
  196.   parse_error <<- false,
  197.   Tree = top_declarations,
  198.   F = features(Term),
  199.   (
  200.     iter_c_parse(F, Term, 1),
  201.     !
  202.   ;
  203.     parse_error <<- true
  204.   ),
  205.   ParseError = parse_error,
  206.   the_error_log.number_of_errors <<- error_number,
  207.   cond(the_error_mode :== talkie,
  208.     nl_err
  209.   ).
  210.  
  211.  
  212. %
  213. % ------------------------------------------------------------------------------
  214. %
  215.  
  216.  
  217. iter_c_parse([Feature | LFeatures], Term, FileNumber) :-
  218.   Feature :== {tree; error_log; parse_mode; error_mode; error},
  219.   !,
  220.   iter_c_parse(LFeatures, Term, FileNumber).
  221.  
  222.  
  223. iter_c_parse([Feature | LFeatures], Term, FileNumber) :-
  224.   !,
  225.   File = Term.Feature,
  226.   (
  227.     exists_file(File),
  228.     !,
  229.     top_declarations.files.FileNumber <<- file_info(name => File)
  230.   ;
  231.     write_err(">>> c_parse : file '", File, "' doesn't exist"),
  232.     nl_err,
  233.     write_err(">>> c_parse : abort"),
  234.     nl_err,
  235.     fail
  236.   ),
  237.   CPPFile = strcon(tmp_dir, strcon(basename(File), ".cpp")),
  238.   Command = 
  239.     strcon(strcon(strcon(strcon(cpp_name, " "), File), " "),
  240.            strcon(">", CPPFile)
  241.     ),
  242.   ReturnCode = system(Command),
  243.   (
  244.     exists_file(CPPFile),
  245.     !,
  246.     open_in(CPPFile, InStream),
  247.     tokenize(File),
  248.     translation_unit,
  249.     close(InStream),
  250.     @ = system(strcon("rm ", CPPFile)),
  251.     top_declarations.files.FileNumber.first_token <<- get_first_token
  252.   ;
  253.     write_err(">>> c_parse : problem with file '", File, "'"),
  254.     nl_err
  255.   ),
  256.   iter_c_parse(LFeatures, Term, FileNumber + 1).
  257.  
  258.  
  259. iter_c_parse([], Term, FileNumber) :-
  260.   cond(FileNumber :== 1,
  261.     (
  262.       write_err(">>> c_parse : error no file specified"),
  263.       nl_err,
  264.       write_err(">>> c_parse : abort"),
  265.       nl_err,
  266.       fail
  267.     ),
  268.     top_declarations.files.files_number <<- FileNumber - 1
  269.   ).
  270.  
  271.  
  272. %
  273. % ------------------------------------------------------------------------------
  274. %
  275.  
  276.  
  277. basename(Name) -> string_of(base_name_of(str2list(Name))).
  278.  
  279.  
  280. base_name_of([]) -> [].
  281.  
  282. base_name_of([47 | L]) -> BaseName  % 47 = asc("/")
  283.   | BaseNameList = zap2slash(L),
  284.     cond(BaseNameList :== [],
  285.       BaseName = L,
  286.       BaseName = base_name_of(BaseNameList)
  287.     ).
  288.  
  289. base_name_of(L) -> BaseName
  290.   | BaseNameList = zap2slash(L),
  291.     cond(BaseNameList :== [],
  292.       BaseName = L,
  293.       BaseName = base_name_of(BaseNameList)
  294.     ).
  295.  
  296.  
  297. zap2slash([]) -> [].
  298.  
  299. zap2slash(L:[47 | @]) -> L.
  300.  
  301. zap2slash([@ | L]) -> zap2slash(L).
  302.  
  303.  
  304. %
  305. % ------------------------------------------------------------------------------
  306. %
  307. %  The main predicate of the parser : it collects the external declarations.
  308. %
  309. % ------------------------------------------------------------------------------
  310. %
  311.  
  312.  
  313. persistent(error_occured) ?
  314.  
  315.  
  316. translation_unit :-
  317.   current_token :== nothing,
  318.   !,
  319.   check_struct_and_union_declarations,
  320.   end_declarations_chain,
  321.   Toplevel = top_declarations,
  322.   build_scope(Toplevel).
  323.  
  324.  
  325. translation_unit :-
  326.   (
  327.     external_declaration(ErrorOccured),
  328.     error_occured <<- ErrorOccured,
  329.     fail
  330.   ;
  331.     succeed
  332.   ),
  333.   (
  334.     error_occured :== true,
  335.     !,
  336.     report_parse_error,
  337.     end_declarations_chain,
  338.     Toplevel = top_declarations,
  339.     build_scope(Toplevel)
  340.   ;
  341.     translation_unit
  342.   ).
  343.  
  344.  
  345. %
  346. % ------------------------------------------------------------------------------
  347. %
  348.  
  349.  
  350. external_declaration(ErrorOccured) :-
  351.   declaration_specifiers(0 => DeclarationSpecifiers, rest => []),
  352.   scan_specifiers(DeclarationSpecifiers, Specifiers, 
  353.                   Qualification, StoreClass, toplevel),
  354.   Toplevel = top_declarations,
  355.   !,
  356.   (
  357.     Specifiers = [typedef],
  358.     !
  359.   ;
  360.     current_token :== ';',
  361.     !,
  362.     SemiColon = get_current_token,
  363.     get_next_token,
  364.     complete_definition(Specifiers, Qualification, StoreClass, SemiColon,
  365.                         Toplevel)
  366.   ;
  367.     cond(Specifiers :== [],
  368.       TheSpecifiers = [default_type],
  369.       TheSpecifiers = Specifiers
  370.     ),
  371.     BaseType = build_type(TheSpecifiers, Qualification, StoreClass),
  372.     (
  373.       init_declarators(BaseType, 0 => InitDeclarators, rest => []),
  374.       !,
  375.       (
  376.         is_a_function_definition(InitDeclarators, Name, Style),
  377.         !,
  378.         (
  379.           Style :== modern,
  380.           !,
  381.           (
  382.             current_token :== left_brace_symbol,
  383.             !,
  384.             (
  385.               set_function_local_declarations,
  386.               build_modern_local_declarations(InitDeclarators,
  387.                                               function_head(Name)),
  388.               compound_instruction(FunctionBody),
  389.               isolate_instruction(FunctionBody),
  390.               Declarations = current_declarations,
  391.               restore_function_local_declarations,
  392.               build_function(style => modern, InitDeclarators,
  393.                              Declarations, FunctionBody),
  394.               !
  395.             ;
  396.               ErrorOccured = true
  397.             )
  398.           ;
  399.             (
  400.               build_declaration(InitDeclarators, Toplevel, 
  401.                                 external_declarations),
  402.               !
  403.             ;
  404.               ErrorOccured = true
  405.             )
  406.           )
  407.         ;
  408.           base_declarations_list(0 => ArgumentsTypes, rest => []),
  409.           (
  410.             set_function_local_declarations,
  411.             set_previous_declaration(PreviousDeclaration),
  412.             build_local_declarations(ArgumentsTypes, 
  413.                                      function_head(Name)),
  414.             check_coherence(Name, InitDeclarators),
  415.             end_declarations_chain,
  416.             compound_instruction(FunctionBody),
  417.             isolate_instruction(FunctionBody),
  418.             Declarations = current_declarations,
  419.             restore_previous_declaration_from(PreviousDeclaration),
  420.             restore_function_local_declarations,
  421.             build_function(style => old, InitDeclarators, Declarations,
  422.                            FunctionBody),
  423.             !
  424.           ;
  425.             ErrorOccured = true
  426.           )
  427.         ;
  428.           (
  429.             build_declaration(InitDeclarators, Toplevel, external_declarations),
  430.             !
  431.           ;
  432.             ErrorOccured = true
  433.           )
  434.         )
  435.       ;
  436.         build_declaration(InitDeclarators, Toplevel, external_declarations),
  437.         !
  438.       ;
  439.         ErrorOccured = true
  440.       )
  441.     ;
  442.       ErrorOccured = true
  443.     )
  444.   ;
  445.     ErrorOccured = true
  446.   ).
  447.  
  448.  
  449. external_declaration(true).
  450.  
  451.  
  452. %
  453. % ------------------------------------------------------------------------------
  454. %
  455.  
  456.  
  457. type_beginning(Identifier) :-
  458.   Identifier :== identifier,
  459.   is_type_name(Identifier),
  460.   !.
  461.  
  462.  
  463. type_beginning(What) :-
  464.   What :== {store_class_specifier; type_qualifier; single_type_specifier;
  465.             struct; union; enum},
  466.   !.
  467.  
  468.  
  469. %
  470. % ------------------------------------------------------------------------------
  471. %
  472.  
  473.  
  474. base_declarations_list -->
  475.   {
  476.     declaration_specifiers(0 => DeclarationSpecifiers, rest => []),
  477.     scan_specifiers(DeclarationSpecifiers, Specifiers, 
  478.                     Qualification, StoreClass, function_head),
  479.     Specifiers :\== [] or Qualification :\== @ or StoreClass :\== @
  480.   },
  481.   !,
  482.   { 
  483.     cond(Specifiers :== [],
  484.       TheSpecifiers = [default_type],
  485.       TheSpecifiers = Specifiers
  486.     ),
  487.     BaseType = build_type(TheSpecifiers, Qualification, StoreClass)
  488.   },
  489.   init_declarators(BaseType),
  490.   base_declarations_list.
  491.  
  492.  
  493. base_declarations_list --> [].
  494.  
  495.  
  496. %
  497. % ------------------------------------------------------------------------------
  498. %
  499.  
  500.  
  501. get_local_declarations(Block) :-
  502.   declaration_specifiers(0 => DeclarationSpecifiers, rest => []),
  503.   scan_specifiers(DeclarationSpecifiers, Specifiers, 
  504.                   Qualification, StoreClass, block),
  505.   (
  506.     Specifiers = [typedef],
  507.     !,
  508.     get_local_declarations(Block)
  509.   ;
  510.     current_token :== ';',
  511.     !,
  512.     SemiColon = get_current_token,
  513.     get_next_token,
  514.     complete_definition(Specifiers, Qualification, StoreClass, SemiColon,
  515.                         Block),
  516.     get_local_declarations(Block)
  517.   ;
  518.     Specifiers :\== [] or Qualification :\== @ or StoreClass :\== @,
  519.     !,
  520.     cond(Specifiers :== [],
  521.       TheSpecifiers = [default_type],
  522.       TheSpecifiers = Specifiers
  523.     ),
  524.     BaseType = build_type(TheSpecifiers, Qualification, StoreClass),
  525.     init_declarators(BaseType, 0 => InitDeclarators, rest => []),
  526.     build_declaration(InitDeclarators, Block, local_declarations),
  527.     get_local_declarations(Block)
  528.   ;
  529.     succeed
  530.   ).
  531.  
  532.  
  533. %
  534. % ------------------------------------------------------------------------------
  535. %
  536.  
  537.  
  538. declaration_specifiers(type_specified => false, typedef => false) -->
  539.   {
  540.     current_token :== typedef,
  541.     !,
  542.     Typedef = get_current_token,
  543.     get_next_token,
  544.     declaration_specifiers(0 => DeclarationSpecifiers, rest => [],
  545.                            typedef => true),
  546.     scan_specifiers(DeclarationSpecifiers, Specifiers, Qualification, 
  547.                     StoreClass, typedef),
  548.     Specifiers :\== [],
  549.     BaseType = build_type(Specifiers, Qualification, StoreClass),
  550.     init_declarators(BaseType, 0 => TypeDeclarators, rest => []),
  551.     TypeDefinition = build_typedef(Typedef, TypeDeclarators)
  552.   },
  553.   [TypeDefinition].
  554.  
  555.  
  556. declaration_specifiers(type_specified => TypeSpecified, typedef => Typedef) -->
  557.   {
  558.     current_token :== single_type_specifier,
  559.     !,
  560.     Specifier = get_current_token,
  561.     get_next_token
  562.   },
  563.   [Specifier],
  564.   declaration_specifiers(type_specified => true, typedef => Typedef).
  565.  
  566.  
  567. declaration_specifiers(type_specified => TypeSpecified, typedef => Typedef) -->
  568.   {
  569.     current_token :== {store_class_specifier; type_qualifier},
  570.     !,
  571.     Specifier = get_current_token,
  572.     get_next_token
  573.   },
  574.   [Specifier],
  575.   declaration_specifiers(type_specified => TypeSpecified, typedef => Typedef).
  576.  
  577.  
  578. declaration_specifiers(type_specified => false, typedef => Typedef) -->
  579.   {
  580.     current_token :== {struct; union},
  581.     !,
  582.     Specifier = get_current_token,
  583.     get_next_token,
  584.     get_struct_or_union_specifier(Specifier, StructOrUnionSpecifier)      
  585.   },
  586.   [StructOrUnionSpecifier],
  587.   declaration_specifiers(type_specified => true, typedef => Typedef).
  588.  
  589.  
  590. declaration_specifiers(type_specified => false, typedef => Typedef) -->
  591.   {
  592.     current_token :== enum,
  593.     !,
  594.     Specifier = get_current_token,
  595.     get_next_token,
  596.     get_enum_specifier(Specifier, EnumSpecifier)
  597.   },
  598.   [EnumSpecifier],
  599.   declaration_specifiers(type_specified => true, typedef => Typedef).
  600.  
  601.  
  602. declaration_specifiers(type_specified => false, typedef => Typedef) -->
  603.   {
  604.     current_token :== identifier,
  605.     is_type_name(current_token),
  606.     !,
  607.     Identifier = get_current_token,
  608.     get_next_token
  609.   },
  610.   [build_type_name(Identifier)],
  611.   declaration_specifiers(type_specified => true, typedef => Typedef).
  612.  
  613.  
  614. declaration_specifiers --> [].
  615.  
  616.  
  617. %
  618. % ------------------------------------------------------------------------------
  619. %
  620.  
  621.  
  622. get_struct_or_union_specifier(Specifier, StructOrUnionSpecifier) :-
  623.   (
  624.     current_token :== identifier,
  625.     !,
  626.     TokenName = get_current_token & @(Name)
  627.   ;
  628.     Name = anonymous
  629.   ),
  630.   (
  631.     Name :== anonymous,
  632.     !,
  633.     get_struct_or_union_body(Specifier, StructOrUnionBody),
  634.     StructOrUnionSpecifier = 
  635.       build_struct_definition(Specifier, anonymous, StructOrUnionBody)
  636.   ;
  637.     next_token :== left_brace_symbol,
  638.     !,
  639.     get_next_token,
  640.     get_struct_or_union_body(Specifier, StructOrUnionBody),
  641.     StructOrUnionSpecifier = 
  642.       build_struct_definition(Specifier, TokenName, StructOrUnionBody)
  643.   ;
  644.     get_next_token,
  645.     StructOrUnionSpecifier = 
  646.       build_struct_name(Specifier, TokenName)
  647.   ).
  648.  
  649.  
  650. %
  651. % ------------------------------------------------------------------------------
  652. %
  653.  
  654.  
  655. get_struct_or_union_body(Specifier, StructOrUnionBody) :-
  656.   current_token :== left_brace_symbol,
  657.   !,
  658.   LeftBrace = get_current_token,
  659.   get_next_token,
  660.   tag_number <<- 1,
  661.   set_previous_declaration(PreviousDeclaration),
  662.   struct_declarations(StructDeclarations),
  663.   end_declarations_chain,
  664.   restore_previous_declaration_from(PreviousDeclaration),
  665.   recover_token(RightBrace, right_brace_symbol),
  666.   StructOrUnionBody = 
  667.     build_struct_or_union_body(Specifier, LeftBrace, StructDeclarations,
  668.                                RightBrace).
  669.  
  670.  
  671. %
  672. % ------------------------------------------------------------------------------
  673. %
  674.  
  675.  
  676. struct_declarations(StructDeclarations) :-
  677.   struct_declaration(StructDeclarations),
  678.   !,
  679.   struct_declarations(StructDeclarations).
  680.  
  681.  
  682. struct_declarations(StructDeclarations).
  683.  
  684.  
  685. %
  686. % ------------------------------------------------------------------------------
  687. %
  688.  
  689.  
  690. struct_declaration(StructDeclarations) :-
  691.   declaration_specifiers(0 => DeclarationSpecifiers, rest => []),
  692.   scan_specifiers(DeclarationSpecifiers, Specifiers,
  693.                   Qualification, StoreClass, struct),
  694.   Specifiers :\== [] or Qualification :\== @ or StoreClass :\== @,
  695.   cond(Specifiers :== [],
  696.     TheSpecifiers = [default_type],
  697.     TheSpecifiers = Specifiers
  698.   ),
  699.   BaseType = build_type(TheSpecifiers, Qualification, StoreClass),
  700.   struct_declarators(BaseType, 0 => StructDeclarators, rest => []),
  701.   build_struct_declaration(StructDeclarators, StructDeclarations).
  702.  
  703.  
  704. %
  705. % ------------------------------------------------------------------------------
  706. %
  707.  
  708.  
  709. struct_declarators(BaseType) -->
  710.   (
  711.     {
  712.       current_token :== ':',
  713.       !,
  714.       get_tag(BaseType, StructDeclarator)
  715.     }
  716.   ;
  717.     {
  718.       current_token :== identifier,
  719.       next_token :== ':',
  720.       !,
  721.       get_tag(BaseType, StructDeclarator)
  722.     }
  723.   ;
  724.     { 
  725.       declarator(BaseType, Type, Name),
  726.       !,
  727.       StructDeclarator = @(name => Name, type => Type)
  728.     }
  729.   ),
  730.   [StructDeclarator],
  731.   (
  732.     {
  733.       current_token :== ',',
  734.       !,
  735.       Comma = get_current_token,
  736.       get_next_token,
  737.       add_separator(Comma, StructDeclarator)
  738.     },
  739.     struct_declarators(BaseType)
  740.   ;
  741.     {
  742.       current_token :== ';',
  743.       !,
  744.       SemiColon = get_current_token,
  745.       get_next_token,
  746.       add_separator(SemiColon, StructDeclarator)
  747.     }
  748.   ;
  749.     {
  750.       recover_token(SemiColon, ';'),
  751.       add_separator(SemiColon, StructDeclarator)
  752.     }
  753.   ).
  754.  
  755.  
  756. %
  757. % ------------------------------------------------------------------------------
  758. %
  759.  
  760.  
  761. get_tag(BaseType, StructDeclarator) :-
  762.   current_token :== ':',
  763.   !,
  764.   recover_token(Colon, ':'),
  765.   constant_expression(Initialization),
  766.   Name = build_tag_name,
  767.   StructDeclarator = @(name => Name, 
  768.                        type => build_tag(type => BaseType),
  769.                        initialization => 
  770.                          build_tag_value(Initialization, Colon)).
  771.  
  772.  
  773. get_tag(BaseType, StructDeclarator) :-
  774.   current_token :== identifier,
  775.   next_token :== ':',
  776.   !,
  777.   recover_token(Name, identifier),
  778.   recover_token(Colon, ':'),
  779.   constant_expression(Initialization),
  780.   StructDeclarator = @(name => Name, 
  781.                        type => build_tag(type => BaseType),
  782.                        initialization => 
  783.                          build_tag_value(Initialization, Colon)).
  784.  
  785.  
  786. %
  787. % ------------------------------------------------------------------------------
  788. %
  789.  
  790.  
  791. init_declarators(BaseType) -->
  792.   { init_declarator(BaseType, InitDeclarator) },
  793.   !,
  794.   [InitDeclarator],
  795.   (
  796.     {
  797.       current_token :== ',',
  798.       !,
  799.       Comma = get_current_token,
  800.       get_next_token,
  801.       add_separator(Comma, InitDeclarator)
  802.     },
  803.     init_declarators(BaseType)
  804.   ;
  805.     {
  806.       current_token :== ';',
  807.       !,
  808.       SemiColon = get_current_token,
  809.       get_next_token,
  810.       add_separator(SemiColon, InitDeclarator)
  811.     }
  812.   ;
  813.     []
  814.   ).
  815.  
  816.  
  817. init_declarators(BaseType) --> [].
  818.  
  819.  
  820. %
  821. % ------------------------------------------------------------------------------
  822. %
  823.  
  824.  
  825. init_declarator(BaseType, InitDeclarator) :-
  826.   declarator(BaseType, Type, Name),
  827.   InitDeclarator = 
  828.     @(name => Name, type => Type),
  829.   (
  830.     current_token :== '=',
  831.     !,
  832.     Operator = get_current_token,
  833.     get_next_token,
  834.     initializer(InitializerBody),
  835.     InitDeclarator.initialization = 
  836.       build_initializer(Operator, InitializerBody)
  837.   ;
  838.     succeed
  839.   ).
  840.  
  841.  
  842. %
  843. % ------------------------------------------------------------------------------
  844. %
  845.  
  846.  
  847. initializer(Initializer) :-
  848.   current_token :== left_brace_symbol,
  849.   !,
  850.   LeftBrace = get_current_token,
  851.   get_next_token,
  852.   initializers_list(0 => Initializers, rest => []),
  853.   recover_token(RightBrace, right_brace_symbol),
  854.   Initializer = 
  855.     build_complex_initialization(LeftBrace, Initializers, RightBrace).
  856.  
  857.  
  858. initializer(Initializer) :-
  859.   assignment_expression(Initializer).
  860.  
  861.  
  862. %
  863. % ------------------------------------------------------------------------------
  864. %
  865.  
  866.  
  867. initializers_list -->
  868.   { initializer(Initializer) },
  869.   !,
  870.   [Initializer],
  871.   (
  872.     {
  873.       current_token :== ',',
  874.       !,
  875.       Comma = get_current_token,
  876.       get_next_token,
  877.       add_separator(Comma, Initializer)
  878.     },
  879.     initializers_list
  880.   ;
  881.     { add_separator(nothing, Initializer) }
  882.   ).
  883.  
  884.  
  885. initializers_list --> [].
  886.  
  887.  
  888. %
  889. % ------------------------------------------------------------------------------
  890. %
  891.  
  892.  
  893. type_name(TypeName) :-
  894.   declaration_specifiers(0 => DeclarationSpecifiers, rest => []),
  895.   scan_specifiers(DeclarationSpecifiers, Specifiers,
  896.                   Qualification, StoreClass, type_name),
  897.   BaseType = build_type(Specifiers, Qualification, StoreClass),
  898.   declarator(BaseType, TypeName, DeclaratorName),
  899.   check_for_type_name(DeclaratorName).
  900.  
  901.  
  902. %
  903. % ------------------------------------------------------------------------------
  904. %
  905.  
  906.  
  907. get_enum_specifier(Specifier, EnumSpecifier) :-
  908.   (
  909.     current_token :== identifier,
  910.     !,
  911.     TokenName = get_current_token & @(Name)
  912.   ;
  913.     Name = anonymous
  914.   ),
  915.   (
  916.     Name :== anonymous,
  917.     !,
  918.     get_enum_body(EnumBody),
  919.     EnumSpecifier = 
  920.       build_enum_definition(Specifier, anonymous, EnumBody)
  921.   ;
  922.     next_token :== left_brace_symbol,
  923.     !,
  924.     get_next_token,
  925.     get_enum_body(EnumBody),
  926.     EnumSpecifier = 
  927.       build_enum_definition(Specifier, TokenName, EnumBody)
  928.   ;
  929.     get_next_token,
  930.     EnumSpecifier = 
  931.       build_enum_name(Specifier, TokenName)
  932.   ).
  933.  
  934.  
  935. %
  936. % ------------------------------------------------------------------------------
  937. %
  938.  
  939.  
  940. get_enum_body(EnumBody) :-
  941.   current_token :== left_brace_symbol,
  942.   !,
  943.   LeftBrace = get_current_token,
  944.   get_next_token,
  945.   enumerators(0 => Enumerators, rest => []),
  946.   set_previous_declaration(PreviousDeclaration),
  947.   build_enum_declaration(Enumerators, Enumeration),
  948.   end_declarations_chain,
  949.   restore_previous_declaration_from(PreviousDeclaration),
  950.   recover_token(RightBrace, right_brace_symbol),
  951.   EnumBody = build_enum_body(LeftBrace, Enumeration, RightBrace).
  952.  
  953.  
  954. %
  955. % ------------------------------------------------------------------------------
  956. %
  957.  
  958.  
  959. enumerators -->
  960.   { enumerator(Enumerator) },
  961.   !,
  962.   [Enumerator],
  963.   (
  964.     {
  965.       current_token :== ',',
  966.       !,
  967.       Comma = get_current_token,
  968.       get_next_token,
  969.       add_separator(Comma, Enumerator)
  970.     }
  971.   ;
  972.     { add_separator(nothing, Enumerator) }
  973.   ),
  974.   enumerators.
  975.  
  976.  
  977. enumerators --> [].
  978.  
  979.  
  980. %
  981. % ------------------------------------------------------------------------------
  982. %
  983.  
  984.  
  985. enumerator(Enumerator) :-
  986.   current_token :== identifier,
  987.   !,
  988.   Name = get_current_token,
  989.   get_next_token,
  990.   (
  991.     current_token :== '=',
  992.     !,
  993.     Operator = get_current_token,
  994.     get_next_token,
  995.     constant_expression(Initializer),
  996.     Initialization = build_initializer(Operator, Initializer),
  997.     Enumerator = @(name => Name, type => enumerator, 
  998.                    initialization => Initialization)
  999.   ;
  1000.     Enumerator = @(name => Name, type => enumerator)
  1001.   ).
  1002.  
  1003.  
  1004. %
  1005. % ------------------------------------------------------------------------------
  1006. %
  1007.  
  1008.  
  1009. pointer(BaseType, Pointer) :-
  1010.   current_token :== '*',
  1011.   !,
  1012.   Star = get_current_token,
  1013.   get_next_token,
  1014.   type_qualifiers_list(0 => Qualifiers, rest => []),
  1015.   pointer(build_pointer(BaseType, Qualifiers, Star), Pointer).
  1016.  
  1017.  
  1018. pointer(Pointer, Pointer).
  1019.  
  1020.  
  1021. %
  1022. % ------------------------------------------------------------------------------
  1023. %
  1024.  
  1025.  
  1026. type_qualifiers_list -->
  1027.   { current_token :== type_qualifier },
  1028.   !,
  1029.   { 
  1030.     Qualifier = get_current_token,
  1031.     get_next_token
  1032.   },
  1033.   [Qualifier],
  1034.   type_qualifiers_list.
  1035.  
  1036.  
  1037. type_qualifiers_list --> [].
  1038.  
  1039.  
  1040. %
  1041. % ------------------------------------------------------------------------------
  1042. %
  1043.  
  1044.  
  1045. declarator(TypeSpecification, Type, Name) :-
  1046.   pointer(TypeSpecification, BaseType),
  1047.   (
  1048.     current_token :== identifier,
  1049.     !,
  1050.     Name = get_current_token,
  1051.     get_next_token,
  1052.     absolute_declarator(BaseType, Type)
  1053.   ;
  1054.     current_token :== left_parenthesis_symbol,
  1055.     !,
  1056.     LeftParenthesis = get_current_token,
  1057.     get_next_token,
  1058.     (
  1059.       current_token :== right_parenthesis_symbol,
  1060.       !,
  1061.       RightParenthesis = get_current_token,
  1062.       get_next_token,  
  1063.       Name = build_anonymous,
  1064.       Type = 
  1065.         build_function_declaration(Pointer, LeftParenthesis, 
  1066.                                    nothing, RightParenthesis)
  1067.     ;
  1068.       type_beginning(current_token),
  1069.       !,
  1070.       parameters_types_list(0 => Parameters, rest => []),
  1071.       recover_token(RightParenthesis, right_parenthesis_symbol),
  1072.       Name = build_anonymous,
  1073.       Type = 
  1074.         build_function_declaration(Pointer, LeftParenthesis, 
  1075.                                    Parameters, RightParenthesis)
  1076.     ;
  1077.       declarator(NewBaseType, InnerType, Name),
  1078.       recover_token(RightParenthesis, right_parenthesis_symbol),
  1079.       absolute_declarator(BaseType, NewBaseType),
  1080.       Type = 
  1081.         build_protected_type(InnerType, LeftParenthesis, RightParenthesis)
  1082.     )
  1083.   ;
  1084.     Name = build_anonymous,
  1085.     absolute_declarator(BaseType, Type)
  1086.   ).
  1087.  
  1088.  
  1089. %
  1090. % ------------------------------------------------------------------------------
  1091. %
  1092.  
  1093.  
  1094. absolute_declarator(BaseType, Type) :-
  1095.   current_token :== left_parenthesis_symbol,
  1096.   !,
  1097.   LeftParenthesis = get_current_token,
  1098.   get_next_token,
  1099.   (
  1100.     current_token :== right_parenthesis_symbol,
  1101.     !,
  1102.     Parameters = nothing,
  1103.     RightParenthesis = get_current_token,
  1104.     get_next_token
  1105.   ;
  1106.     type_beginning(current_token),
  1107.     !,
  1108.     parameters_types_list(0 => Parameters, rest => []),
  1109.     recover_token(RightParenthesis, right_parenthesis_symbol)    
  1110.   ;
  1111.     set_previous_declaration(PreviousDeclaration),
  1112.     identifiers_list(0 => Parameters, rest => []),
  1113.     end_declarations_chain,
  1114.     restore_previous_declaration_from(PreviousDeclaration),
  1115.     recover_token(RightParenthesis, right_parenthesis_symbol)
  1116.   ),
  1117.   Type = 
  1118.     build_function_declaration(BaseType, 
  1119.                                LeftParenthesis,
  1120.                                Parameters,
  1121.                                RightParenthesis).
  1122.  
  1123.  
  1124. absolute_declarator(BaseType, Type) :-
  1125.   current_token :== left_bracket_symbol,
  1126.   !,
  1127.   collect_array_declaration(Dimensions : dimensions, 1),
  1128.   Type = build_array(BaseType, Dimensions).
  1129.  
  1130.  
  1131. absolute_declarator(Type, Type).
  1132.  
  1133.  
  1134. %
  1135. % ------------------------------------------------------------------------------
  1136. %
  1137.  
  1138.  
  1139. collect_array_declaration(Array, DimensionNumber) :-
  1140.   current_token :== left_bracket_symbol,
  1141.   !,
  1142.   LeftBracket = get_current_token,
  1143.   get_next_token,
  1144.   (
  1145.     current_token :== right_bracket_symbol,
  1146.     !,
  1147.     Dimension = nothing
  1148.   ;
  1149.     constant_expression(Dimension)
  1150.   ),
  1151.   recover_token(RightBracket, right_bracket_symbol),
  1152.   Array.DimensionNumber = 
  1153.     build_dimension(Dimension, LeftBracket, RightBracket),
  1154.   collect_array_declaration(Array, DimensionNumber + 1).
  1155.  
  1156.  
  1157. collect_array_declaration(Array, DimensionNumber) :-
  1158.   Array.dimensions_number = DimensionNumber - 1.
  1159.  
  1160.  
  1161. %
  1162. % ------------------------------------------------------------------------------
  1163. %
  1164.  
  1165.  
  1166. parameters_types_list -->
  1167.   { current_token :== '...' },
  1168.   !,
  1169.   {
  1170.     SuspensionPoints = get_current_token,
  1171.     get_next_token
  1172.   },
  1173.   [build_vararg(SuspensionPoints)].
  1174.  
  1175.  
  1176. parameters_types_list -->
  1177.   {
  1178.     declaration_specifiers(0 => DeclarationSpecifiers, rest => []),
  1179.     scan_specifiers(DeclarationSpecifiers, Specifiers,
  1180.                     Qualification, StoreClass, function_head),
  1181.     BaseType = build_type(Specifiers, Qualification, StoreClass),
  1182.     declarator(BaseType, Type, Name)
  1183.   },
  1184.   (
  1185.     {
  1186.       current_token :== ',',
  1187.       !,
  1188.       Comma = get_current_token,
  1189.       get_next_token
  1190.     }
  1191.   ;
  1192.     []
  1193.   ),
  1194.   [build_parameter(Type, Name, Comma)],
  1195.   parameters_types_list.
  1196.  
  1197.  
  1198. parameters_types_list --> [].
  1199.  
  1200.  
  1201. %
  1202. % ------------------------------------------------------------------------------
  1203. %
  1204.  
  1205.  
  1206. identifiers_list -->
  1207.   { 
  1208.     current_token :== identifier,
  1209.     !,
  1210.     Identifier = get_current_token,
  1211.     get_next_token,
  1212.     Parameter = build_identifier_parameter(Identifier)
  1213.   },
  1214.   [Parameter],
  1215.   (
  1216.     {
  1217.       current_token :== ',',
  1218.       !,
  1219.       Comma = get_current_token,
  1220.       get_next_token,
  1221.       add_separator(Comma, Parameter)
  1222.     },
  1223.     identifiers_list
  1224.   ;
  1225.     { add_separator(nothing, Parameter) }
  1226.   ).
  1227.  
  1228.  
  1229. identifiers_list --> [].
  1230.  
  1231.  
  1232. %
  1233. % ------------------------------------------------------------------------------
  1234. %
  1235.  
  1236.  
  1237. instruction(Instruction) :-
  1238.   rough_instruction(Instruction),
  1239.   set_scope_for_instruction(Instruction).
  1240.  
  1241.  
  1242. %
  1243. % ------------------------------------------------------------------------------
  1244. %
  1245.  
  1246.  
  1247. rough_instruction(Instruction) :-
  1248.   compound_instruction(Instruction),
  1249.   !.
  1250.  
  1251.  
  1252. rough_instruction(Instruction) :-
  1253.   labeled_instruction(Instruction),
  1254.   !.
  1255.  
  1256.  
  1257. rough_instruction(Instruction) :-
  1258.   selection_instruction(Instruction),
  1259.   !.
  1260.  
  1261.  
  1262. rough_instruction(Instruction) :-
  1263.   iteration_instruction(Instruction),
  1264.   !.
  1265.  
  1266.  
  1267. rough_instruction(Instruction) :-
  1268.   jump_instruction(Instruction),
  1269.   !.
  1270.  
  1271.  
  1272. rough_instruction(Instruction) :-
  1273.   void_instruction(Instruction),
  1274.   !.
  1275.  
  1276.  
  1277. rough_instruction(Instruction) :-
  1278.   expression_instruction(Instruction).
  1279.  
  1280.  
  1281. %
  1282. % ------------------------------------------------------------------------------
  1283. %
  1284. %  Modified : 2 15 1994
  1285. %
  1286. % ------------------------------------------------------------------------------
  1287. %
  1288.  
  1289.  
  1290. labeled_instruction(Instruction) :-
  1291.   current_token :== identifier,
  1292.   next_token :== ':',
  1293.   !,
  1294.   recover_token(Label, identifier),
  1295.   recover_token(Colon, ':'),
  1296.   set_previous_instruction_scope(OuterInstruction),
  1297.   set_instruction_scope(Instruction),
  1298.   instruction(Body),
  1299.   restore_instruction_scope_from(OuterInstruction),
  1300.   Instruction <<- build_labeled_instruction(Label, Colon, Body). 
  1301.  
  1302.  
  1303. labeled_instruction(Instruction) :-
  1304.   current_token :== case,
  1305.   !,
  1306.   Case = get_current_token,
  1307.   get_next_token,
  1308.   constant_expression(Expression),
  1309.   recover_token(Colon, ':'),
  1310.   set_previous_instruction_scope(OuterInstruction),
  1311.   set_instruction_scope(Instruction),
  1312.   instruction(Body),
  1313.   restore_instruction_scope_from(OuterInstruction),
  1314.   Instruction <<- build_case(Case, Expression, Colon, Body).
  1315.  
  1316.  
  1317. labeled_instruction(Instruction) :-
  1318.   current_token :== default,
  1319.   Default = get_current_token,
  1320.   get_next_token,
  1321.   recover_token(Colon, ':'),
  1322.   set_previous_instruction_scope(OuterInstruction),
  1323.   set_instruction_scope(Instruction),
  1324.   instruction(Body),
  1325.   restore_instruction_scope_from(OuterInstruction),
  1326.   Instruction <<- build_default(Default, Colon, Body).
  1327.  
  1328.  
  1329. %
  1330. % ------------------------------------------------------------------------------
  1331. %
  1332.  
  1333.  
  1334. expression_instruction(Instruction) :-
  1335.   expression(Expression),
  1336.   recover_token(SemiColon, ';'),
  1337.   Instruction = build_expression_instruction(Expression, SemiColon).
  1338.  
  1339.  
  1340. %
  1341. % ------------------------------------------------------------------------------
  1342. %
  1343.  
  1344.  
  1345. compound_instruction(Block) :-
  1346.   current_token :== left_brace_symbol,
  1347.   LeftBrace = get_current_token,
  1348.   get_next_token,
  1349.   set_local_declarations(LocalDeclarations),
  1350.   init_complex_declaration(LocalDeclarations),
  1351.   set_previous_declaration(PreviousDeclaration),
  1352.   Block <<- block,
  1353.   get_local_declarations(Block),
  1354.   end_declarations_chain,
  1355.   restore_previous_declaration_from(PreviousDeclaration),
  1356.   set_previous_instruction(PreviousInstruction),
  1357.   set_previous_instruction_scope(TheBlock),
  1358.   set_instruction_scope(Block),
  1359.   instructions_list(0 => Body, rest => []),
  1360.   restore_instruction_scope_from(TheBlock),
  1361.   restore_previous_instruction_from(PreviousInstruction),
  1362.   recover_token(RightBrace, right_brace_symbol),
  1363.   Instruction =
  1364.     build_compound_instruction(LeftBrace, Body, RightBrace),
  1365.   Block <<- Instruction,
  1366.   build_scope(Block),
  1367.   chain_body(Body, Block),
  1368.   restore_declarations_from(LocalDeclarations).
  1369.  
  1370.  
  1371. %
  1372. % ------------------------------------------------------------------------------
  1373. %
  1374.  
  1375.  
  1376. instructions_list -->
  1377.   { current_token :== right_brace_symbol },
  1378.   !.
  1379.  
  1380.  
  1381. instructions_list -->
  1382.   { 
  1383.     instruction(Instruction),
  1384.     set_current_instruction(Instruction),
  1385.     chain_instructions(Instruction, NewInstruction)
  1386.   },
  1387.   [NewInstruction],
  1388.   instructions_list.
  1389.  
  1390.  
  1391. %
  1392. % ------------------------------------------------------------------------------
  1393. %
  1394.  
  1395.  
  1396. selection_instruction(Instruction) :-
  1397.   current_token :== if,
  1398.   !,
  1399.   If = get_current_token,
  1400.   get_next_token,
  1401.   recover_token(LeftParenthesis, left_parenthesis_symbol),
  1402.   expression(Condition),
  1403.   recover_token(RightParenthesis, right_parenthesis_symbol),
  1404.   Instruction <<- nothing,
  1405.   set_previous_instruction_scope(OuterInstruction),
  1406.   set_instruction_scope(then_body(instruction => Instruction)),
  1407.   instruction(ThenBody),
  1408.   (
  1409.     current_token :== else,
  1410.     !,
  1411.     Else = get_current_token,
  1412.     get_next_token,
  1413.     set_instruction_scope(else_body(instruction => Instruction)),
  1414.     instruction(ElseBody)
  1415.   ; 
  1416.     succeed
  1417.   ),
  1418.   restore_instruction_scope_from(OuterInstruction),
  1419.   Instruction <<- 
  1420.     build_if(If, LeftParenthesis, Condition, RightParenthesis,
  1421.              ThenBody, Else, ElseBody).
  1422.  
  1423.  
  1424. selection_instruction(Instruction) :-
  1425.   current_token :== switch,
  1426.   Switch = get_current_token,
  1427.   get_next_token,
  1428.   recover_token(LeftParenthesis, left_parenthesis_symbol),
  1429.   expression(Condition),
  1430.   recover_token(RightParenthesis, right_parenthesis_symbol),
  1431.   Instruction <<- nothing,
  1432.   set_previous_instruction_scope(OuterInstruction),
  1433.   set_instruction_scope(Instruction),
  1434.   instruction(Body),
  1435.   restore_instruction_scope_from(OuterInstruction),
  1436.   Instruction <<-
  1437.     build_switch(Switch, LeftParenthesis, Condition, RightParenthesis, Body).
  1438.  
  1439.  
  1440. %
  1441. % ------------------------------------------------------------------------------
  1442. %
  1443.  
  1444.  
  1445. iteration_instruction(Instruction) :-
  1446.   current_token :== while,
  1447.   !,
  1448.   While = get_current_token,
  1449.   get_next_token,
  1450.   recover_token(LeftParenthesis, left_parenthesis_symbol),
  1451.   expression(Condition),
  1452.   recover_token(RightParenthesis, right_parenthesis_symbol),
  1453.   Instruction <<- nothing,
  1454.   set_previous_instruction_scope(OuterInstruction),
  1455.   set_instruction_scope(Instruction),
  1456.   instruction(Body),
  1457.   restore_instruction_scope_from(OuterInstruction),
  1458.   Instruction <<-
  1459.     build_while(While, LeftParenthesis, Condition, RightParenthesis, Body).  
  1460.  
  1461.  
  1462. iteration_instruction(Instruction) :-
  1463.   current_token :== do,
  1464.   !,
  1465.   Do = get_current_token,
  1466.   get_next_token,
  1467.   Instruction <<- nothing,
  1468.   set_previous_instruction_scope(OuterInstruction),
  1469.   set_instruction_scope(Instruction),
  1470.   instruction(Body),
  1471.   restore_instruction_scope_from(OuterInstruction),
  1472.   recover_token(While, while),
  1473.   recover_token(LeftParenthesis, left_parenthesis_symbol),
  1474.   expression(Condition),
  1475.   recover_token(RightParenthesis, right_parenthesis_symbol),
  1476.   recover_token(SemiColon, ';'),
  1477.   Instruction <<-
  1478.     build_do_while(Do, Body, While, LeftParenthesis, Condition,
  1479.                    RightParenthesis, SemiColon).    
  1480.  
  1481.  
  1482. iteration_instruction(Instruction) :-
  1483.   current_token :== for,
  1484.   For = get_current_token,
  1485.   get_next_token,
  1486.   recover_token(LeftParenthesis, left_parenthesis_symbol),
  1487.   (
  1488.     current_token :== ';',
  1489.     !,
  1490.     Initialization = nothing
  1491.   ;
  1492.     expression(Initialization)
  1493.   ),
  1494.   recover_token(SemiColon1, ';'),
  1495.   (
  1496.     current_token :== ';',
  1497.     !,
  1498.     Condition = nothing
  1499.   ;
  1500.     expression(Condition)
  1501.   ),
  1502.   recover_token(SemiColon2, ';'),  
  1503.   (
  1504.     current_token :== right_parenthesis_symbol,
  1505.     !,
  1506.     Step = nothing
  1507.   ;
  1508.     expression(Step)
  1509.   ),
  1510.   recover_token(RightParenthesis, right_parenthesis_symbol),
  1511.   Instruction <<- nothing,
  1512.   set_previous_instruction_scope(OuterInstruction),
  1513.   set_instruction_scope(Instruction),
  1514.   instruction(Body),
  1515.   restore_instruction_scope_from(OuterInstruction),
  1516.   Instruction <<-
  1517.     build_for(For, LeftParenthesis, Initialization, SemiColon1,
  1518.               Condition, SemiColon2, Step, RightParenthesis, Body).
  1519.  
  1520.  
  1521. %
  1522. % ------------------------------------------------------------------------------
  1523. %
  1524.  
  1525.  
  1526. jump_instruction(Instruction) :-
  1527.   current_token :== {continue; break},
  1528.   !,
  1529.   Jump = get_current_token,
  1530.   get_next_token,
  1531.   recover_token(SemiColon, ';'),
  1532.   add_semi_colon(SemiColon, Instruction),
  1533.   Instruction = build_jump(Jump).
  1534.  
  1535.  
  1536. jump_instruction(Instruction) :-
  1537.   current_token :== goto,
  1538.   !,
  1539.   Goto = get_current_token,
  1540.   get_next_token,
  1541.   current_token :== identifier,
  1542.   Label = get_current_token,
  1543.   get_next_token,
  1544.   recover_token(SemiColon, ';'),
  1545.   add_semi_colon(SemiColon, Instruction),
  1546.   Instruction = build_goto(Goto, Label).
  1547.  
  1548.  
  1549. jump_instruction(Instruction) :-
  1550.   current_token :== return,
  1551.   !,
  1552.   Return = get_current_token,
  1553.   get_next_token,
  1554.   (
  1555.     current_token :== ';',
  1556.     !,
  1557.     Value = nothing
  1558.   ;
  1559.     expression(Value)
  1560.   ),
  1561.   recover_token(SemiColon, ';'),
  1562.   add_semi_colon(SemiColon, Instruction),
  1563.   Instruction = build_return(Return, Value).
  1564.  
  1565.  
  1566. %
  1567. % ------------------------------------------------------------------------------
  1568. %
  1569.  
  1570.  
  1571. void_instruction(Instruction) :-
  1572.   current_token :== ';',
  1573.   !,
  1574.   SemiColon = get_current_token,
  1575.   get_next_token,
  1576.   Instruction = build_void_instruction(SemiColon).
  1577.  
  1578.  
  1579. %
  1580. % ------------------------------------------------------------------------------
  1581. %
  1582.  
  1583.  
  1584. expression(Expression) :-
  1585.   assignment_expression(AssignmentExpression),
  1586.   expression_tail(in_left_assignment_expression => AssignmentExpression,
  1587.                   Expression).
  1588.  
  1589.  
  1590. %
  1591. % ------------------------------------------------------------------------------
  1592. %
  1593.  
  1594.  
  1595. expression_tail(Expression) :--
  1596.   LeftExpression is left_assignment_expression,
  1597.   (
  1598.     {
  1599.       current_token :== ',',
  1600.       !,
  1601.       Comma = get_current_token,
  1602.       get_next_token
  1603.     },
  1604.     { assignment_expression(AssignmentExpression) },
  1605.     build_sequence_expression(LeftExpression, AssignmentExpression, Comma)
  1606.       + left_assignment_expression,
  1607.     expression_tail(Expression)
  1608.   ;
  1609.     Expression is left_assignment_expression
  1610.   ).
  1611.  
  1612.  
  1613. %
  1614. % ------------------------------------------------------------------------------
  1615. %
  1616.  
  1617.  
  1618. assignment_expression(Expression) :-
  1619.   conversion_expression(LeftExpression),
  1620.   (
  1621.     is_assignment(current_token),
  1622.     !,
  1623.     Operator = get_current_token,
  1624.     get_next_token,
  1625.     assignment_expression(RightExpression),
  1626.     Expression = build_binary_expression(Operator, LeftExpression, 
  1627.                                          RightExpression)
  1628.   ;
  1629.     conditional_expression(in_left_expression => LeftExpression,
  1630.                            Expression)
  1631.   ).
  1632.  
  1633.  
  1634. %
  1635. % ------------------------------------------------------------------------------
  1636. %
  1637.  
  1638.  
  1639. conditional_expression(Expression) :--
  1640.   (
  1641.     { get_precedence(current_token) },
  1642.     !,
  1643.     arithmetic_expression(LeftExpression)
  1644.   ;
  1645.     LeftExpression is left_expression
  1646.   ),
  1647.   (
  1648.     {
  1649.       current_token :== '?',
  1650.       !,
  1651.       QuestionMark = get_current_token,
  1652.       get_next_token
  1653.     },
  1654.     expression(Then),
  1655.     { 
  1656.       recover_token(Colon, ':'),
  1657.       conversion_expression(ElseLeftExpression)
  1658.     },
  1659.     ElseLeftExpression + left_expression,
  1660.     conditional_expression(Else),
  1661.     { Expression = 
  1662.         build_conditional_expression(LeftExpression, QuestionMark, Then,
  1663.                                      Colon, Else) }
  1664.   ;
  1665.     { Expression = LeftExpression }
  1666.   ).
  1667.  
  1668.  
  1669. %
  1670. % ------------------------------------------------------------------------------
  1671. %
  1672.  
  1673.  
  1674. constant_expression(Expression) :-
  1675.   conversion_expression(LeftExpression),
  1676.   conditional_expression(in_left_expression => LeftExpression, Expression).
  1677.  
  1678.  
  1679. %
  1680. % ------------------------------------------------------------------------------
  1681. %
  1682.  
  1683.  
  1684. arithmetic_expression(Expression) :--
  1685.   { get_precedence(current_token, Precedence) },
  1686.   !,
  1687.   collect_arithmetic_expression(LeftExpression, Precedence),
  1688.   LeftExpression + left_expression,
  1689.   arithmetic_expression(Expression).
  1690.  
  1691.  
  1692. arithmetic_expression(Expression) :--
  1693.   Expression is left_expression.
  1694.  
  1695.  
  1696. %
  1697. % ------------------------------------------------------------------------------
  1698. %
  1699. %  The arithmetic expression is collected using a precedence analysis algorithm
  1700. %
  1701. % ------------------------------------------------------------------------------
  1702. %
  1703.  
  1704.  
  1705. collect_arithmetic_expression(Expression, Precedence) :--
  1706.   { 
  1707.     Token1 = get_current_token,
  1708.     get_next_token
  1709.   },
  1710.   LeftExpression is left_expression,
  1711.   { 
  1712.     conversion_expression(RightExpression),
  1713.     Token2 = current_token 
  1714.   },
  1715.   (
  1716.     { get_precedence(Token2, Precedence2) },
  1717.     !,
  1718.     (
  1719.       { Precedence2 :== Precedence },
  1720.       !,
  1721.       build_binary_expression(Token1, LeftExpression, RightExpression)
  1722.         + left_expression,
  1723.       collect_arithmetic_expression(Expression, Precedence)
  1724.     ;
  1725.       { Precedence2 > Precedence },
  1726.       !,
  1727.       RightExpression + left_expression,
  1728.       collect_arithmetic_expression(NewRightExpression, Precedence2),
  1729.       { Expression = 
  1730.           build_binary_expression(Token1, LeftExpression, NewRightExpression) }
  1731.     ;
  1732.       { Expression = 
  1733.           build_binary_expression(Token1, LeftExpression, RightExpression) }
  1734.     )
  1735.   ;
  1736.     { Expression = 
  1737.         build_binary_expression(Token1, LeftExpression, RightExpression) }    
  1738.   ).
  1739.  
  1740.  
  1741. %
  1742. % ------------------------------------------------------------------------------
  1743. %
  1744.  
  1745.  
  1746. strict_conversion_expression(Expression) :-
  1747.   current_token :== left_parenthesis_symbol,
  1748.   type_beginning(next_token),
  1749.   !,
  1750.   LeftParenthesis = get_current_token,
  1751.   get_next_token,
  1752.   type_name(TypeName),
  1753.   recover_token(RightParenthesis, right_parenthesis_symbol),
  1754.   (
  1755.     strict_conversion_expression(CastExpression),
  1756.     !
  1757.   ;
  1758.     unary_expression(CastExpression),
  1759.     !
  1760.   ;
  1761.     CastExpression = nothing
  1762.   ),
  1763.   { Expression = build_cast(LeftParenthesis, TypeName, CastExpression,
  1764.                             RightParenthesis) }.
  1765.  
  1766.  
  1767. %
  1768. % ------------------------------------------------------------------------------
  1769. %
  1770.  
  1771.  
  1772. conversion_expression(Expression) :-
  1773.   strict_conversion_expression(Expression),
  1774.   !.
  1775.  
  1776.  
  1777. conversion_expression(Expression) :-
  1778.   unary_expression(Expression).
  1779.  
  1780.  
  1781. %
  1782. % ------------------------------------------------------------------------------
  1783. %
  1784.  
  1785.  
  1786. unary_expression(Expression) :-
  1787.   is_incrementation_operation(current_token),
  1788.   !,
  1789.   Operator = get_current_token,
  1790.   get_next_token,
  1791.   unary_expression(InnerExpression),
  1792.   Expression = build_prefix_expression(Operator, InnerExpression).
  1793.  
  1794.  
  1795. unary_expression(Expression) :-
  1796.   is_unary_operation(current_token),
  1797.   !,
  1798.   Operator = get_current_token,
  1799.   get_next_token,
  1800.   conversion_expression(InnerExpression),
  1801.   Expression = build_prefix_expression(Operator, InnerExpression).
  1802.  
  1803.  
  1804. unary_expression(Expression) :-
  1805.   current_token :== sizeof,
  1806.   !,
  1807.   Operator = get_current_token,
  1808.   get_next_token,
  1809.   (
  1810.     current_token :== left_parenthesis_symbol,
  1811.     type_beginning(next_token),
  1812.     !,
  1813.     LeftParenthesis = get_current_token,
  1814.     get_next_token,
  1815.     type_name(TypeName),
  1816.     recover_token(RightParenthesis, right_parenthesis_symbol),
  1817.     InnerExpression = 
  1818.       build_protected_expression(TypeName, LeftParenthesis,
  1819.                                  RightParenthesis),
  1820.     Expression = 
  1821.       build_prefix_expression(Operator, InnerExpression)
  1822.   ;
  1823.     unary_expression(InnerExpression),
  1824.     Expression = 
  1825.       build_prefix_expression(Operator, InnerExpression)
  1826.   ).
  1827.  
  1828.  
  1829. unary_expression(Expression) :-
  1830.   postfix_expression(Expression).
  1831.  
  1832.  
  1833. %
  1834. % ------------------------------------------------------------------------------
  1835. %
  1836.  
  1837.  
  1838. postfix_expression(Expression) :-
  1839.   primary_expression(LeftExpression),
  1840.   postfix_expression_tail(in_left_expression => LeftExpression,
  1841.                           Expression).
  1842.  
  1843.  
  1844. %
  1845. % ------------------------------------------------------------------------------
  1846. %
  1847.  
  1848.  
  1849. postfix_expression_tail(Expression) :--
  1850.   { current_token :== left_parenthesis_symbol },
  1851.   !,
  1852.   {
  1853.     LeftParenthesis = get_current_token,
  1854.     get_next_token,
  1855.     expressions_list(0 => Arguments, rest => []),
  1856.     recover_token(RightParenthesis, right_parenthesis_symbol)
  1857.   },
  1858.   LeftExpression is left_expression,
  1859.   build_function_call(LeftExpression, LeftParenthesis, Arguments,
  1860.                       RightParenthesis) + left_expression,
  1861.   postfix_expression_tail(Expression).
  1862.  
  1863.  
  1864. postfix_expression_tail(Expression) :--
  1865.   { current_token :== left_bracket_symbol },
  1866.   !,
  1867.   {
  1868.     LeftBracket = get_current_token,
  1869.     get_next_token,
  1870.     expression(Index),
  1871.     recover_token(RightBracket, right_bracket_symbol)
  1872.   },
  1873.   LeftExpression is left_expression,
  1874.   { validate_identifier(LeftExpression) },
  1875.   build_array_reference(LeftExpression, LeftBracket, Index, RightBracket)
  1876.     + left_expression,
  1877.   postfix_expression_tail(Expression).
  1878.  
  1879.  
  1880. postfix_expression_tail(Expression) :--
  1881.   {  
  1882.     current_token :== {'->'; '.'},
  1883.     !,
  1884.     Operator = get_current_token,
  1885.     get_next_token,
  1886.     current_token :== identifier,
  1887.     Field = get_current_token,
  1888.     get_next_token
  1889.   },
  1890.   LeftExpression is left_expression,
  1891.   { validate_identifier(LeftExpression) },  
  1892.   build_struct_reference(LeftExpression, Operator, Field)
  1893.     + left_expression,
  1894.   postfix_expression_tail(Expression).
  1895.  
  1896.  
  1897. postfix_expression_tail(Expression) :--
  1898.   { 
  1899.     is_incrementation_operation(current_token),
  1900.     !,
  1901.     Operator = get_current_token,
  1902.     get_next_token
  1903.   },
  1904.   LeftExpression is left_expression,
  1905.   { validate_identifier(LeftExpression) },
  1906.   build_postfix_expression(LeftExpression, Operator) + left_expression,
  1907.   postfix_expression_tail(Expression).
  1908.  
  1909.  
  1910. postfix_expression_tail(Expression) :--
  1911.   Expression is left_expression,
  1912.   { validate_identifier(Expression) }.
  1913.  
  1914.  
  1915. %
  1916. % ------------------------------------------------------------------------------
  1917. %
  1918.  
  1919.  
  1920. primary_expression(Expression) :-
  1921.   current_token :== {identifier; number; characters_string; character},
  1922.   !,
  1923.   Expression = get_current_token,
  1924.   get_next_token.
  1925.  
  1926.  
  1927. primary_expression(Expression) :-
  1928.   current_token :== left_parenthesis_symbol,
  1929.   LeftParenthesis = get_current_token,
  1930.   get_next_token, 
  1931.   expression(InnerExpression),
  1932.   recover_token(RightParenthesis, right_parenthesis_symbol),
  1933.   Expression = build_protected_expression(InnerExpression, LeftParenthesis,
  1934.                                           RightParenthesis).
  1935.  
  1936.  
  1937. %
  1938. % ------------------------------------------------------------------------------
  1939. %
  1940.  
  1941.  
  1942. expressions_list -->
  1943.   { assignment_expression(Expression) },
  1944.   !,
  1945.   { Argument = build_argument(Expression) },
  1946.   [Argument],
  1947.   (
  1948.     {
  1949.       current_token :== ',',
  1950.       !,
  1951.       Comma = get_current_token,
  1952.       get_next_token,
  1953.       add_separator(Comma, Argument)
  1954.     },
  1955.     expressions_list
  1956.   ;
  1957.     { add_separator(nothing, Argument) }
  1958.   ).
  1959.  
  1960.  
  1961. expressions_list --> [].
  1962.  
  1963.  
  1964. %
  1965. % ------------------------------------------------------------------------------
  1966. %
  1967.  
  1968.  
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974.  
  1975.  
  1976.  
  1977.  
  1978.  
  1979.