diff options
author | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 |
---|---|---|
committer | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 |
commit | 670a8f984fc6d8342180c59ae9e96b0b76f34d3d (patch) | |
tree | 9f2ce7eec1a77e56b3bb1ad0ad40f212d7a996b0 /jam-files/engine/jamgram.yy | |
parent | eb3ee28dc0eb1d3e5ed01ba0df843be329ae450d (diff) | |
parent | 2f64af3e06a518b93f7ca2c30a9d0aeb2c947031 (diff) |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'jam-files/engine/jamgram.yy')
-rw-r--r-- | jam-files/engine/jamgram.yy | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/jam-files/engine/jamgram.yy b/jam-files/engine/jamgram.yy new file mode 100644 index 00000000..15243487 --- /dev/null +++ b/jam-files/engine/jamgram.yy @@ -0,0 +1,329 @@ +/* + * Copyright 1993, 2000 Christopher Seiwald. + * + * This file is part of Jam - see jam.c for Copyright information. + */ + +/* This file is ALSO: + * Copyright 2001-2004 David Abrahams. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + */ + +/* + * jamgram.yy - jam grammar + * + * 04/13/94 (seiwald) - added shorthand L0 for null list pointer + * 06/01/94 (seiwald) - new 'actions existing' does existing sources + * 08/23/94 (seiwald) - Support for '+=' (append to variable) + * 08/31/94 (seiwald) - Allow ?= as alias for "default =". + * 09/15/94 (seiwald) - if conditionals take only single arguments, so + * that 'if foo == bar' gives syntax error (use =). + * 02/11/95 (seiwald) - when scanning arguments to rules, only treat + * punctuation keywords as keywords. All arg lists + * are terminated with punctuation keywords. + * + * 09/11/00 (seiwald) - Support for function calls: + * + * Rules now return lists (LIST *), rather than void. + * + * New "[ rule ]" syntax evals rule into a LIST. + * + * Lists are now generated by compile_list() and + * compile_append(), and any other rule that indirectly + * makes a list, rather than being built directly here, + * so that lists values can contain rule evaluations. + * + * New 'return' rule sets the return value, though + * other statements also may have return values. + * + * 'run' production split from 'block' production so + * that empty blocks can be handled separately. + */ + +%token ARG STRING + +%left `||` `|` +%left `&&` `&` +%left `=` `!=` `in` +%left `<` `<=` `>` `>=` +%left `!` + +%{ +#include "jam.h" + +#include "lists.h" +#include "parse.h" +#include "scan.h" +#include "compile.h" +#include "newstr.h" +#include "rules.h" + +# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */ + +# define F0 (LIST *(*)(PARSE *, FRAME *))0 +# define P0 (PARSE *)0 +# define S0 (char *)0 + +# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 ) +# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c ) +# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x ) +# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 ) +# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 ) +# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 ) +# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 ) +# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 ) +# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 ) +# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 ) +# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 ) +# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 ) +# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 ) +# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a ) +# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a ) +# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l ) +# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f ) +# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 ) +# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 ) + +# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 ) +# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 ) + +%} + +%% + +run : /* empty */ + /* do nothing */ + | rules + { parse_save( $1.parse ); } + ; + +/* + * block - zero or more rules + * rules - one or more rules + * rule - any one of jam's rules + * right-recursive so rules execute in order. + */ + +block : null + { $$.parse = $1.parse; } + | rules + { $$.parse = $1.parse; } + ; + +rules : rule + { $$.parse = $1.parse; } + | rule rules + { $$.parse = prules( $1.parse, $2.parse ); } + | `local` list assign_list_opt `;` block + { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); } + ; + +null : /* empty */ + { $$.parse = pnull(); } + ; + +assign_list_opt : `=` list + { $$.parse = $2.parse; $$.number = ASSIGN_SET; } + | null + { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; } + ; + +arglist_opt : `(` lol `)` + { $$.parse = $2.parse; } + | + { $$.parse = P0; } + ; + +local_opt : `local` + { $$.number = 1; } + | /* empty */ + { $$.number = 0; } + ; + +rule : `{` block `}` + { $$.parse = $2.parse; } + | `include` list `;` + { $$.parse = pincl( $2.parse ); } + | ARG lol `;` + { $$.parse = prule( $1.string, $2.parse ); } + | arg assign list `;` + { $$.parse = pset( $1.parse, $3.parse, $2.number ); } + | arg `on` list assign list `;` + { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); } + | `return` list `;` + { $$.parse = $2.parse; } + | `for` local_opt ARG `in` list `{` block `}` + { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); } + | `switch` list `{` cases `}` + { $$.parse = pswitch( $2.parse, $4.parse ); } + | `if` expr `{` block `}` + { $$.parse = pif( $2.parse, $4.parse, pnull() ); } + | `module` list `{` block `}` + { $$.parse = pmodule( $2.parse, $4.parse ); } + | `class` lol `{` block `}` + { $$.parse = pclass( $2.parse, $4.parse ); } + | `while` expr `{` block `}` + { $$.parse = pwhile( $2.parse, $4.parse ); } + | `if` expr `{` block `}` `else` rule + { $$.parse = pif( $2.parse, $4.parse, $7.parse ); } + | local_opt `rule` ARG arglist_opt rule + { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); } + | `on` arg rule + { $$.parse = pon( $2.parse, $3.parse ); } + | `actions` eflags ARG bindlist `{` + { yymode( SCAN_STRING ); } + STRING + { yymode( SCAN_NORMAL ); } + `}` + { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); } + ; + +/* + * assign - = or += + */ + +assign : `=` + { $$.number = ASSIGN_SET; } + | `+=` + { $$.number = ASSIGN_APPEND; } + | `?=` + { $$.number = ASSIGN_DEFAULT; } + | `default` `=` + { $$.number = ASSIGN_DEFAULT; } + ; + +/* + * expr - an expression for if + */ +expr : arg + { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); } + | expr `=` expr + { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); } + | expr `!=` expr + { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); } + | expr `<` expr + { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); } + | expr `<=` expr + { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); } + | expr `>` expr + { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); } + | expr `>=` expr + { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); } + | expr `&` expr + { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); } + | expr `&&` expr + { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); } + | expr `|` expr + { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); } + | expr `||` expr + { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); } + | arg `in` list + { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); } + | `!` expr + { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); } + | `(` expr `)` + { $$.parse = $2.parse; } + ; + + +/* + * cases - action elements inside a 'switch' + * case - a single action element inside a 'switch' + * right-recursive rule so cases can be examined in order. + */ + +cases : /* empty */ + { $$.parse = P0; } + | case cases + { $$.parse = pnode( $1.parse, $2.parse ); } + ; + +case : `case` ARG `:` block + { $$.parse = psnode( $2.string, $4.parse ); } + ; + +/* + * lol - list of lists + * right-recursive rule so that lists can be added in order. + */ + +lol : list + { $$.parse = pnode( P0, $1.parse ); } + | list `:` lol + { $$.parse = pnode( $3.parse, $1.parse ); } + ; + +/* + * list - zero or more args in a LIST + * listp - list (in puncutation only mode) + * arg - one ARG or function call + */ + +list : listp + { $$.parse = $1.parse; yymode( SCAN_NORMAL ); } + ; + +listp : /* empty */ + { $$.parse = pnull(); yymode( SCAN_PUNCT ); } + | listp arg + { $$.parse = pappend( $1.parse, $2.parse ); } + ; + +arg : ARG + { $$.parse = plist( $1.string ); } + | `[` { yymode( SCAN_NORMAL ); } func `]` + { $$.parse = $3.parse; } + ; + +/* + * func - a function call (inside []) + * This needs to be split cleanly out of 'rule' + */ + +func : arg lol + { $$.parse = prule( $1.string, $2.parse ); } + | `on` arg arg lol + { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); } + | `on` arg `return` list + { $$.parse = pon( $2.parse, $4.parse ); } + ; + + +/* + * eflags - zero or more modifiers to 'executes' + * eflag - a single modifier to 'executes' + */ + +eflags : /* empty */ + { $$.number = 0; } + | eflags eflag + { $$.number = $1.number | $2.number; } + ; + +eflag : `updated` + { $$.number = EXEC_UPDATED; } + | `together` + { $$.number = EXEC_TOGETHER; } + | `ignore` + { $$.number = EXEC_IGNORE; } + | `quietly` + { $$.number = EXEC_QUIETLY; } + | `piecemeal` + { $$.number = EXEC_PIECEMEAL; } + | `existing` + { $$.number = EXEC_EXISTING; } + ; + + +/* + * bindlist - list of variable to bind for an action + */ + +bindlist : /* empty */ + { $$.parse = pnull(); } + | `bind` list + { $$.parse = $2.parse; } + ; + + |