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.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
@ -609,6 +609,7 @@ enum qse_awk_errnum_t
|
|||||||
QSE_AWK_EDUPLCL, /* duplicate local variable name */
|
QSE_AWK_EDUPLCL, /* duplicate local variable name */
|
||||||
QSE_AWK_EBADPAR, /* not a valid parameter name */
|
QSE_AWK_EBADPAR, /* not a valid parameter name */
|
||||||
QSE_AWK_EBADVAR, /* not a valid variable name */
|
QSE_AWK_EBADVAR, /* not a valid variable name */
|
||||||
|
QSE_AWK_EVARMS, /* variable name missing */
|
||||||
QSE_AWK_EUNDEF, /* undefined identifier */
|
QSE_AWK_EUNDEF, /* undefined identifier */
|
||||||
QSE_AWK_ELVALUE, /* l-value required */
|
QSE_AWK_ELVALUE, /* l-value required */
|
||||||
QSE_AWK_EGBLTM, /* too many global variables */
|
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.
|
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("duplicate local variable '${0}'"),
|
||||||
QSE_T("'${0}' not a valid parameter name"),
|
QSE_T("'${0}' not a valid parameter name"),
|
||||||
QSE_T("'${0}' not a valid variable name"),
|
QSE_T("'${0}' not a valid variable name"),
|
||||||
|
QSE_T("variable name missing"),
|
||||||
QSE_T("undefined identifier '${0}'"),
|
QSE_T("undefined identifier '${0}'"),
|
||||||
QSE_T("l-value required"),
|
QSE_T("l-value required"),
|
||||||
QSE_T("too many global variables"),
|
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.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
@ -387,10 +387,14 @@ static global_t gtab[] =
|
|||||||
qse_awk_seterror ((awk), (code), (line), &errarg); \
|
qse_awk_seterror ((awk), (code), (line), &errarg); \
|
||||||
} while (0)
|
} 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) \
|
#define MATCH_TERMINATOR(awk) \
|
||||||
(MATCH((awk),TOKEN_SEMICOLON) || \
|
(MATCH_TERMINATOR_NORMAL(awk) || MATCH_TERMINATOR_RBRACE(awk))
|
||||||
MATCH((awk),TOKEN_NEWLINE) || \
|
|
||||||
((awk->option & QSE_AWK_NEWLINE) && MATCH((awk),TOKEN_RBRACE)))
|
|
||||||
|
|
||||||
qse_size_t qse_awk_getmaxdepth (qse_awk_t* awk, int type)
|
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)
|
static qse_awk_t* parse_progunit (qse_awk_t* awk)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
gbl xxx, xxxx;
|
global xxx, xxxx;
|
||||||
BEGIN { action }
|
BEGIN { action }
|
||||||
END { action }
|
END { action }
|
||||||
pattern { action }
|
pattern { action }
|
||||||
@ -1204,6 +1208,12 @@ static qse_awk_nde_t* parse_block (
|
|||||||
{
|
{
|
||||||
while (1)
|
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 (!MATCH(awk,TOKEN_LOCAL)) break;
|
||||||
|
|
||||||
if (get_token(awk) <= -1)
|
if (get_token(awk) <= -1)
|
||||||
@ -1624,6 +1634,14 @@ int qse_awk_delgbl (
|
|||||||
|
|
||||||
static qse_awk_t* collect_globals (qse_awk_t* awk)
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
if (!MATCH(awk,TOKEN_IDENT))
|
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 (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))
|
if (!MATCH(awk,TOKEN_COMMA))
|
||||||
{
|
{
|
||||||
@ -1648,11 +1678,13 @@ static qse_awk_t* collect_globals (qse_awk_t* awk)
|
|||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
if (get_token(awk) <= -1) return QSE_NULL;
|
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;
|
return awk;
|
||||||
}
|
}
|
||||||
@ -1660,11 +1692,19 @@ static qse_awk_t* collect_globals (qse_awk_t* awk)
|
|||||||
static qse_awk_t* collect_locals (
|
static qse_awk_t* collect_locals (
|
||||||
qse_awk_t* awk, qse_size_t nlcls, qse_bool_t istop)
|
qse_awk_t* awk, qse_size_t nlcls, qse_bool_t istop)
|
||||||
{
|
{
|
||||||
qse_xstr_t lcl;
|
if (MATCH(awk,TOKEN_NEWLINE))
|
||||||
qse_size_t n;
|
{
|
||||||
|
/* 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)
|
while (1)
|
||||||
{
|
{
|
||||||
|
qse_xstr_t lcl;
|
||||||
|
qse_size_t n;
|
||||||
|
|
||||||
if (!MATCH(awk,TOKEN_IDENT))
|
if (!MATCH(awk,TOKEN_IDENT))
|
||||||
{
|
{
|
||||||
SETERRTOK (awk, QSE_AWK_EBADVAR);
|
SETERRTOK (awk, QSE_AWK_EBADVAR);
|
||||||
@ -1741,7 +1781,18 @@ static qse_awk_t* collect_locals (
|
|||||||
|
|
||||||
if (get_token(awk) <= -1) return QSE_NULL;
|
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))
|
if (!MATCH(awk,TOKEN_COMMA))
|
||||||
{
|
{
|
||||||
@ -1749,11 +1800,12 @@ static qse_awk_t* collect_locals (
|
|||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
if (get_token(awk) <= -1) return QSE_NULL;
|
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;
|
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;
|
if (nde == QSE_NULL) return QSE_NULL;
|
||||||
|
|
||||||
/* check if a statement ends with a semicolon */
|
if (MATCH_TERMINATOR_NORMAL(awk))
|
||||||
if (MATCH_TERMINATOR(awk))
|
|
||||||
{
|
{
|
||||||
/* eat up the semicolon or a new line and read in the next token
|
/* check if a statement ends with a semicolon or <NL> */
|
||||||
* when QSE_AWK_NEWLINE is set, a statement may end with }.
|
if (get_token(awk) <= -1)
|
||||||
* it should not be eaten up here. */
|
|
||||||
if (!MATCH(awk,TOKEN_RBRACE) && get_token(awk) <= -1)
|
|
||||||
{
|
{
|
||||||
if (nde != QSE_NULL) qse_awk_clrpt (awk, nde);
|
if (nde != QSE_NULL) qse_awk_clrpt (awk, nde);
|
||||||
return QSE_NULL;
|
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
|
else
|
||||||
{
|
{
|
||||||
if (nde != QSE_NULL) qse_awk_clrpt (awk, nde);
|
if (nde != QSE_NULL) qse_awk_clrpt (awk, nde);
|
||||||
@ -5992,4 +6046,3 @@ int qse_awk_putsrcstrx (
|
|||||||
|
|
||||||
return 0;
|
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}
|
QSEAWK=${QSEAWK:=../../cmd/awk/qseawk}
|
||||||
|
TMPFILE="${TMPFILE:=./regress.temp}"
|
||||||
|
|
||||||
PROGS="
|
PROGS="
|
||||||
cou-001.awk/cou.dat//
|
cou-001.awk/cou.dat//
|
||||||
@ -81,6 +82,16 @@ PROGS="
|
|||||||
emp-026.awk/emp.dat//
|
emp-026.awk/emp.dat//
|
||||||
emp-027.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//
|
quicksort.awk/quicksort.dat//
|
||||||
quicksort2.awk/quicksort2.dat//
|
quicksort2.awk/quicksort2.dat//
|
||||||
asm.awk/asm.s/asm.dat/
|
asm.awk/asm.s/asm.dat/
|
||||||
@ -96,13 +107,24 @@ PROGS="
|
|||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for prog in ${PROGS}
|
echo "${PROGS}" > "${TMPFILE}"
|
||||||
|
|
||||||
|
while read prog
|
||||||
do
|
do
|
||||||
|
[ -z "${prog}" ] && continue
|
||||||
|
|
||||||
script="`echo ${prog} | cut -d/ -f1`"
|
script="`echo ${prog} | cut -d/ -f1`"
|
||||||
datafile="`echo ${prog} | cut -d/ -f2`"
|
datafile="`echo ${prog} | cut -d/ -f2`"
|
||||||
redinfile="`echo ${prog} | cut -d/ -f3`"
|
redinfile="`echo ${prog} | cut -d/ -f3`"
|
||||||
awkopts="`echo ${prog} | cut -d/ -f4`"
|
awkopts="`echo ${prog} | cut -d/ -f4`"
|
||||||
|
|
||||||
|
[ -z "${script}" ] && continue
|
||||||
|
[ -f "${script}" ] ||
|
||||||
|
{
|
||||||
|
echo_so "${script} not found"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if [ -n "${redinfile}" ]
|
if [ -n "${redinfile}" ]
|
||||||
then
|
then
|
||||||
echo_so "${QSEAWK} ${awkopts} -f ${script} ${datafile} < ${redinfile}"
|
echo_so "${QSEAWK} ${awkopts} -f ${script} ${datafile} < ${redinfile}"
|
||||||
@ -111,6 +133,9 @@ do
|
|||||||
echo_so "${QSEAWK} ${awkopts} -f ${script} ${datafile}"
|
echo_so "${QSEAWK} ${awkopts} -f ${script} ${datafile}"
|
||||||
${QSEAWK} ${awkopts} -f ${script} ${datafile}
|
${QSEAWK} ${awkopts} -f ${script} ${datafile}
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
done < "${TMPFILE}"
|
||||||
|
|
||||||
|
rm -f "${TMPFILE}"
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
Loading…
Reference in New Issue
Block a user