fixed bugs of not handling <NL> properly in local/global variable declarations.
This commit is contained in:
parent
e337e01d46
commit
c31adc3f7c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: awk.h 213 2009-06-26 13:05:19Z hyunghwan.chung $
|
||||
* $Id: awk.h 214 2009-06-27 02:50:54Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -609,6 +609,7 @@ enum qse_awk_errnum_t
|
||||
QSE_AWK_EDUPLCL, /* duplicate local variable name */
|
||||
QSE_AWK_EBADPAR, /* not a valid parameter name */
|
||||
QSE_AWK_EBADVAR, /* not a valid variable name */
|
||||
QSE_AWK_EVARMS, /* variable name missing */
|
||||
QSE_AWK_EUNDEF, /* undefined identifier */
|
||||
QSE_AWK_ELVALUE, /* l-value required */
|
||||
QSE_AWK_EGBLTM, /* too many global variables */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: err.c 213 2009-06-26 13:05:19Z hyunghwan.chung $
|
||||
* $Id: err.c 214 2009-06-27 02:50:54Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -99,6 +99,7 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum)
|
||||
QSE_T("duplicate local variable '${0}'"),
|
||||
QSE_T("'${0}' not a valid parameter name"),
|
||||
QSE_T("'${0}' not a valid variable name"),
|
||||
QSE_T("variable name missing"),
|
||||
QSE_T("undefined identifier '${0}'"),
|
||||
QSE_T("l-value required"),
|
||||
QSE_T("too many global variables"),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: parse.c 213 2009-06-26 13:05:19Z hyunghwan.chung $
|
||||
* $Id: parse.c 214 2009-06-27 02:50:54Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -387,10 +387,14 @@ static global_t gtab[] =
|
||||
qse_awk_seterror ((awk), (code), (line), &errarg); \
|
||||
} while (0)
|
||||
|
||||
#define MATCH_TERMINATOR_NORMAL(awk) \
|
||||
(MATCH((awk),TOKEN_SEMICOLON) || MATCH((awk),TOKEN_NEWLINE))
|
||||
|
||||
#define MATCH_TERMINATOR_RBRACE(awk) \
|
||||
((awk->option & QSE_AWK_NEWLINE) && MATCH((awk),TOKEN_RBRACE))
|
||||
|
||||
#define MATCH_TERMINATOR(awk) \
|
||||
(MATCH((awk),TOKEN_SEMICOLON) || \
|
||||
MATCH((awk),TOKEN_NEWLINE) || \
|
||||
((awk->option & QSE_AWK_NEWLINE) && MATCH((awk),TOKEN_RBRACE)))
|
||||
(MATCH_TERMINATOR_NORMAL(awk) || MATCH_TERMINATOR_RBRACE(awk))
|
||||
|
||||
qse_size_t qse_awk_getmaxdepth (qse_awk_t* awk, int type)
|
||||
{
|
||||
@ -592,7 +596,7 @@ exit_parse:
|
||||
static qse_awk_t* parse_progunit (qse_awk_t* awk)
|
||||
{
|
||||
/*
|
||||
gbl xxx, xxxx;
|
||||
global xxx, xxxx;
|
||||
BEGIN { action }
|
||||
END { action }
|
||||
pattern { action }
|
||||
@ -1204,6 +1208,12 @@ static qse_awk_nde_t* parse_block (
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
/* skip new lines before local declaration in a block*/
|
||||
while (MATCH(awk,TOKEN_NEWLINE))
|
||||
{
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
}
|
||||
|
||||
if (!MATCH(awk,TOKEN_LOCAL)) break;
|
||||
|
||||
if (get_token(awk) <= -1)
|
||||
@ -1624,6 +1634,14 @@ int qse_awk_delgbl (
|
||||
|
||||
static qse_awk_t* collect_globals (qse_awk_t* awk)
|
||||
{
|
||||
if (MATCH(awk,TOKEN_NEWLINE))
|
||||
{
|
||||
/* special check if the first name is on the
|
||||
* same line when QSE_AWK_NEWLINE is on */
|
||||
SETERR (awk, QSE_AWK_EVARMS);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!MATCH(awk,TOKEN_IDENT))
|
||||
@ -1640,7 +1658,19 @@ static qse_awk_t* collect_globals (qse_awk_t* awk)
|
||||
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
|
||||
if (MATCH_TERMINATOR(awk)) break;
|
||||
if (MATCH_TERMINATOR_NORMAL(awk))
|
||||
{
|
||||
/* skip a terminator (;, <NL>) */
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* unlike collect_locals(), the right brace cannot
|
||||
* terminate a global declaration as it can never be
|
||||
* placed within a block.
|
||||
* so do not perform MATCH_TERMINATOR_RBRACE(awk))
|
||||
*/
|
||||
|
||||
if (!MATCH(awk,TOKEN_COMMA))
|
||||
{
|
||||
@ -1648,11 +1678,13 @@ static qse_awk_t* collect_globals (qse_awk_t* awk)
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
}
|
||||
while (MATCH(awk,TOKEN_NEWLINE));
|
||||
}
|
||||
|
||||
/* skip a semicolon */
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
|
||||
return awk;
|
||||
}
|
||||
@ -1660,11 +1692,19 @@ static qse_awk_t* collect_globals (qse_awk_t* awk)
|
||||
static qse_awk_t* collect_locals (
|
||||
qse_awk_t* awk, qse_size_t nlcls, qse_bool_t istop)
|
||||
{
|
||||
qse_xstr_t lcl;
|
||||
qse_size_t n;
|
||||
if (MATCH(awk,TOKEN_NEWLINE))
|
||||
{
|
||||
/* special check if the first name is on the
|
||||
* same line when QSE_AWK_NEWLINE is on */
|
||||
SETERR (awk, QSE_AWK_EVARMS);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
qse_xstr_t lcl;
|
||||
qse_size_t n;
|
||||
|
||||
if (!MATCH(awk,TOKEN_IDENT))
|
||||
{
|
||||
SETERRTOK (awk, QSE_AWK_EBADVAR);
|
||||
@ -1741,7 +1781,18 @@ static qse_awk_t* collect_locals (
|
||||
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
|
||||
if (MATCH_TERMINATOR(awk)) break;
|
||||
if (MATCH_TERMINATOR_NORMAL(awk))
|
||||
{
|
||||
/* skip the terminator (;, <NL>) */
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MATCH_TERMINATOR_RBRACE(awk))
|
||||
{
|
||||
/* should not skip } */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!MATCH(awk,TOKEN_COMMA))
|
||||
{
|
||||
@ -1749,11 +1800,12 @@ static qse_awk_t* collect_locals (
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
}
|
||||
|
||||
/* skip a semicolon */
|
||||
if (get_token(awk) <= -1) return QSE_NULL;
|
||||
while (MATCH(awk,TOKEN_NEWLINE));
|
||||
}
|
||||
|
||||
return awk;
|
||||
}
|
||||
@ -1924,18 +1976,20 @@ static qse_awk_nde_t* parse_statement_nb (qse_awk_t* awk, qse_size_t line)
|
||||
|
||||
if (nde == QSE_NULL) return QSE_NULL;
|
||||
|
||||
/* check if a statement ends with a semicolon */
|
||||
if (MATCH_TERMINATOR(awk))
|
||||
if (MATCH_TERMINATOR_NORMAL(awk))
|
||||
{
|
||||
/* eat up the semicolon or a new line and read in the next token
|
||||
* when QSE_AWK_NEWLINE is set, a statement may end with }.
|
||||
* it should not be eaten up here. */
|
||||
if (!MATCH(awk,TOKEN_RBRACE) && get_token(awk) <= -1)
|
||||
/* check if a statement ends with a semicolon or <NL> */
|
||||
if (get_token(awk) <= -1)
|
||||
{
|
||||
if (nde != QSE_NULL) qse_awk_clrpt (awk, nde);
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
else if (MATCH_TERMINATOR_RBRACE(awk))
|
||||
{
|
||||
/* do not skip the right brace as a statement terminator.
|
||||
* is there anything to do here? */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nde != QSE_NULL) qse_awk_clrpt (awk, nde);
|
||||
@ -5992,4 +6046,3 @@ int qse_awk_putsrcstrx (
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
3
qse/regress/awk/lang-001.awk
Normal file
3
qse/regress/awk/lang-001.awk
Normal file
@ -0,0 +1,3 @@
|
||||
# cannot use function name as a parameter name
|
||||
function f(f) { print f; }
|
||||
BEGIN { f("hello"); }
|
7
qse/regress/awk/lang-002.awk
Normal file
7
qse/regress/awk/lang-002.awk
Normal file
@ -0,0 +1,7 @@
|
||||
function f(f)
|
||||
{
|
||||
print f;
|
||||
f("my hello");
|
||||
}
|
||||
|
||||
BEGIN { f(10); }
|
3
qse/regress/awk/lang-003.awk
Normal file
3
qse/regress/awk/lang-003.awk
Normal file
@ -0,0 +1,3 @@
|
||||
# should print 50
|
||||
function fn(f) { f = 20; }
|
||||
BEGIN { f = 50; fn(100); print f; }
|
3
qse/regress/awk/lang-004.awk
Normal file
3
qse/regress/awk/lang-004.awk
Normal file
@ -0,0 +1,3 @@
|
||||
# A function and a named variable cannot have the same name.
|
||||
function a () { }
|
||||
BEGIN { a = 20; }
|
7
qse/regress/awk/lang-005.awk
Normal file
7
qse/regress/awk/lang-005.awk
Normal file
@ -0,0 +1,7 @@
|
||||
function a (a) { print a; }
|
||||
|
||||
BEGIN {
|
||||
local a;
|
||||
a = 20;
|
||||
a (1000);
|
||||
}
|
2
qse/regress/awk/lang-006.awk
Normal file
2
qse/regress/awk/lang-006.awk
Normal file
@ -0,0 +1,2 @@
|
||||
global a;
|
||||
function a () { }
|
4
qse/regress/awk/lang-007.awk
Normal file
4
qse/regress/awk/lang-007.awk
Normal file
@ -0,0 +1,4 @@
|
||||
function fn () { a = 20; return a;}
|
||||
global a;
|
||||
BEGIN { a = 30; print fn (); print a; }
|
||||
|
16
qse/regress/awk/lang-008.awk
Normal file
16
qse/regress/awk/lang-008.awk
Normal file
@ -0,0 +1,16 @@
|
||||
global x;
|
||||
BEGIN {
|
||||
x = 1;
|
||||
{
|
||||
local x;
|
||||
x = 2;
|
||||
{
|
||||
local x;
|
||||
x = 3;
|
||||
print x;
|
||||
}
|
||||
print x;
|
||||
}
|
||||
print x;
|
||||
}
|
||||
|
9
qse/regress/awk/lang-009.awk
Normal file
9
qse/regress/awk/lang-009.awk
Normal file
@ -0,0 +1,9 @@
|
||||
function a (a) { print a; }
|
||||
|
||||
BEGIN {
|
||||
local a;
|
||||
a = 20;
|
||||
}
|
||||
|
||||
END { a (1000); }
|
||||
|
@ -23,6 +23,7 @@ print_usage()
|
||||
###################
|
||||
|
||||
QSEAWK=${QSEAWK:=../../cmd/awk/qseawk}
|
||||
TMPFILE="${TMPFILE:=./regress.temp}"
|
||||
|
||||
PROGS="
|
||||
cou-001.awk/cou.dat//
|
||||
@ -81,6 +82,16 @@ PROGS="
|
||||
emp-026.awk/emp.dat//
|
||||
emp-027.awk/emp.dat//
|
||||
|
||||
lang-001.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-002.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-003.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-004.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-005.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-006.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-007.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-008.awk///--implicit=off --explicit=on --newline=on -o-
|
||||
lang-009.awk/lang-009.awk//--implicit=off --explicit=on --newline=on -o-
|
||||
|
||||
quicksort.awk/quicksort.dat//
|
||||
quicksort2.awk/quicksort2.dat//
|
||||
asm.awk/asm.s/asm.dat/
|
||||
@ -96,13 +107,24 @@ PROGS="
|
||||
exit 1;
|
||||
}
|
||||
|
||||
for prog in ${PROGS}
|
||||
echo "${PROGS}" > "${TMPFILE}"
|
||||
|
||||
while read prog
|
||||
do
|
||||
[ -z "${prog}" ] && continue
|
||||
|
||||
script="`echo ${prog} | cut -d/ -f1`"
|
||||
datafile="`echo ${prog} | cut -d/ -f2`"
|
||||
redinfile="`echo ${prog} | cut -d/ -f3`"
|
||||
awkopts="`echo ${prog} | cut -d/ -f4`"
|
||||
|
||||
[ -z "${script}" ] && continue
|
||||
[ -f "${script}" ] ||
|
||||
{
|
||||
echo_so "${script} not found"
|
||||
continue
|
||||
}
|
||||
|
||||
if [ -n "${redinfile}" ]
|
||||
then
|
||||
echo_so "${QSEAWK} ${awkopts} -f ${script} ${datafile} < ${redinfile}"
|
||||
@ -111,6 +133,9 @@ do
|
||||
echo_so "${QSEAWK} ${awkopts} -f ${script} ${datafile}"
|
||||
${QSEAWK} ${awkopts} -f ${script} ${datafile}
|
||||
fi
|
||||
done
|
||||
|
||||
done < "${TMPFILE}"
|
||||
|
||||
rm -f "${TMPFILE}"
|
||||
|
||||
exit 0
|
||||
|
Loading…
Reference in New Issue
Block a user