Permalink
Browse files

Clean up error messages from word_parse.py.

- Parse error test for ${a[@z (where Z is invalid)
- Slicing error cases cleaned up

Addresses issue #27 and #103.
  • Loading branch information...
Andy Chu
Andy Chu committed Aug 21, 2018
1 parent f487093 commit 82f52d8d7a55922f63a1a38e4b91ec821c64f20d
Showing with 48 additions and 22 deletions.
  1. +18 −15 osh/word_parse.py
  2. +30 −7 test/parse-errors.sh
View
@@ -189,8 +189,8 @@ def _ReadSliceVarOp(self):
return ast.Slice(begin, length)
else:
self.AddErrorContext("Unexpected token in slice: %s", self.cur_token)
return None
p_die("Unexpected token in slice: %r", self.cur_token.val,
token=self.cur_token)
def _ReadPatSubVarOp(self, lex_mode):
"""
@@ -232,8 +232,8 @@ def _ReadPatSubVarOp(self, lex_mode):
do_suffix = True
pat.parts.pop(0)
# TODO: Print the modifier better.
if len(pat.parts) == 0:
# TODO: Print the modifier better.
p_die('Pattern in ${x/pat/replace} must not be empty (got modifier %s)',
first_part, token=self.cur_token)
@@ -258,9 +258,7 @@ def _ReadPatSubVarOp(self, lex_mode):
else:
# Happens with ${x//} and ${x///foo}, see test/parse-errors.sh
# TODO: Print the token better.
p_die("Expected } after pat sub, got %s", self.cur_token,
p_die("Expected } after pat sub, got %r", self.cur_token.val,
token=self.cur_token)
def _ReadSubscript(self):
@@ -282,10 +280,9 @@ def _ReadSubscript(self):
return None
op = ast.ArrayIndex(anode)
#self._Peek() # Can't do this here. Should the test go elsewhere?
if self.token_type != Id.Arith_RBracket: # Should be looking at ]
self._BadToken('Expected ] after subscript, got %s', self.cur_token)
return None
p_die('Expected ] after subscript, got %r', self.cur_token.val,
token=self.cur_token)
self._Next(lex_mode_e.VS_2) # skip past ]
self._Peek() # Needed to be in the same spot as no subscript
@@ -333,6 +330,7 @@ def _ParseVarExpr(self, arg_lex_mode):
op_id = self.token_type
arg_word = self._ReadVarOpArg(arg_lex_mode)
if self.token_type != Id.Right_VarSub:
# NOTE: Not sure how to tickle this. May not be possible.
self._BadToken('Unexpected token after test arg: %s', self.cur_token)
return None
@@ -351,16 +349,20 @@ def _ParseVarExpr(self, arg_lex_mode):
elif op_kind == Kind.VOp2:
if self.token_type == Id.VOp2_Slash:
op = self._ReadPatSubVarOp(arg_lex_mode)
if not op: return None
if not op:
return None
# Checked by the method above
assert self.token_type == Id.Right_VarSub, self.cur_token
elif self.token_type == Id.VOp2_Colon:
op = self._ReadSliceVarOp()
if not op: return None
if self.token_type != Id.Arith_RBrace:
self._BadToken('Unexpected token after slice: %s', self.cur_token)
if not op:
return None
# NOTE: } in arithmetic mode.
if self.token_type != Id.Arith_RBrace:
# Token seems off; doesn't point to X in # ${a:1:2 X
p_die('Unexpected token after slice: %r', self.cur_token.val,
token=self.cur_token)
else:
p_die('Unexpected token %s', self.cur_token, token=self.cur_token)
@@ -370,8 +372,9 @@ def _ParseVarExpr(self, arg_lex_mode):
# NOTE: Arith_RBrace is for slicing, because it reads } in arithmetic
# mode. It's redundantly checked above.
if self.token_type not in (Id.Right_VarSub, Id.Arith_RBrace):
self._BadToken('Unexpected token after var sub: %s', self.cur_token)
return None
# ${a.} or ${!a.}
p_die('Unexpected token after var sub: %r', self.cur_token.val,
token=self.cur_token)
# Now look for ops
return part
View
@@ -24,15 +24,10 @@ _error-case() {
$SH -c "$@"
}
cases-in-strings() {
# All in osh/word_parse.py
patsub() {
set +o errexit
_error-case 'echo < <<'
_error-case '${foo:}'
_error-case '$(( 1 + ))'
_error-case 'echo $( echo > >> )'
_error-case 'echo ${'
_error-case 'echo ${x/}' # pattern must not be empty
_error-case 'echo ${x/%}' # pattern must not be empty (only had modifier)
@@ -52,6 +47,34 @@ cases-in-strings() {
_error-case 'echo ${x//foo/replace$foo}'
}
# osh/word_parse.py
word-parse() {
set +o errexit
_error-case 'echo ${a[@Z'
_error-case 'echo ${x.}'
_error-case 'echo ${!x.}'
# NOTE: This is because of EOF
_error-case 'echo ${a:1;}'
# NOTE: Doesn't point to X
_error-case 'echo ${a:1:2;}'
}
cases-in-strings() {
set +o errexit
_error-case 'echo < <<'
_error-case '${foo:}'
_error-case '$(( 1 + ))'
_error-case 'echo $( echo > >> )'
_error-case 'echo ${'
patsub
word-parse
}
# Cases in their own file
cases-in-files() {
set +o errexit # Don't fail

0 comments on commit 82f52d8

Please sign in to comment.